]> git.proxmox.com Git - lvm.git/blame - LVM2.2.02.168.tgz
bump version to 2.02.168-pve1
[lvm.git] / LVM2.2.02.168.tgz
Content-type: text/html ]> git.proxmox.com Git - lvm.git/blame - LVM2.2.02.168.tgz


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 157806.
CommitLineData
9f3003c1
FG
1LVM2.2.02.168/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0015047\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/WHATS_NEW\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000001000416\013062740170\0016373\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Version 2.02.168 - 30th November 2016
2=====================================
3 Display correct sync_percent on large RaidLVs
4 lvmdbusd --blackboxsize <n> added, used to override default size of 16
5 Allow a transiently failed RaidLV to be refreshed
6 Use lv_update_and_reload() inside mirror code where it applies.
7 Preserve mirrored status for temporary layered mirrors.
8 Use transient raid check before repairing raid volume.
9 Implement transient status check for raid volumes.
10 Only log msg as debug if lvm2-lvmdbusd unit missing for D-Bus notification.
11 Avoid duplicated underscore in name of extracted LV image.
12 Missing stripe filler now could be also 'zero'.
13 lvconvert --repair accepts --interval and --background option.
14 More efficiently prepare _rmeta devices when creating a new raid LV.
15
16Version 2.02.167 - 5th November 2016
17====================================
18 Use log_error in regex and sysfs filter to describe reason of failure.
19 Fix blkdeactivate to deactivate dev stack if dev on top already unmounted.
20 Prevent non-synced raid1 repair unless --force
21 Prevent raid4 creation/conversion on non-supporting kernels
22 Add direct striped -> raid4 conversion
23 Fix raid4 parity image pair position on conversions from striped/raid0*
24 Fix a few unconverted return code values for some lvconvert error path.
25 Disable lvconvert of thin pool to raid while active.
26 Disable systemd service start rate limiting for lvm2-pvscan@.service.
27
28Version 2.02.166 - 26th September 2016
29======================================
30 Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
31 Fix lvchange-rebuild-raid.sh to cope with older target versions.
32 Use dm_config_parse_without_dup_node_check() to speedup metadata reading.
33 Fix lvconvert --repair regression
34 Fix reported origin lv field for cache volumes. (2.02.133)
35 Always specify snapshot cow LV for monitoring not internal LV. (2.02.165)
36 Fix lvchange --discard|--zero for active thin-pool.
37 Enforce 4MiB or 25% metadata free space for thin pool operations.
38 Fix lock-holder device for thin pool with inactive thin volumes.
39 Use --alloc normal for mirror logs even if the mimages were stricter.
40 Use O_DIRECT to gather metadata in lvmdump.
41 Ignore creation_time when checking for matching metadata for lvmetad.
42 Fix possible NULL pointer derefence when checking for monitoring.
43 Add lvmreport(7) man page.
44 Don't install lvmraid(7) man page when raid excluded. (2.02.165)
45 Report 0% as dirty (copy%) for cache without any used block.
46 Fix lvm2api reporting of cache data and metadata percent.
47 Restore reporting of metadata usage for cache volumes (2.02.155).
48 Support raid scrubbing on cache origin LV.
49
50Version 2.02.165 - 7th September 2016
51=====================================
52 Add lvmraid(7) man page.
53 Use udev db to check for mpath components before running pvscan for lvmetad.
54 Use lsblk -s and lsblk -O in lvmdump only if these options are supported.
55 Fix number of stripes shown in lvcreate raid10 message when too many.
56 Change lvmdbusd to use new lvm shell facilities.
57 Do not monitor cache-pool metadata when LV is just being cleared.
58 Add allocation/cache_pool_max_chunks to prevent misuse of cache target.
59 Give error not segfault in lvconvert --splitmirrors when PV lies outside LV.
60 Fix typo in report/columns_as_rows config option name recognition (2.02.99).
61 Avoid PV tags when checking allocation against parallel PVs.
62 Disallow mirror conversions of raid10 volumes.
63 Fix dmeventd unmonitoring when segment type (and dso) changes.
64 Don't allow lvconvert --repair on raid0 devices or attempt to monitor them.
65 No longer adjust incorrect number of raid stripes supplied to lvcreate.
66 Move lcm and gcd to lib/misc.
67 Fix vgsplit of external origins. (2.02.162)
68 Prohibit creation of RAID LVs unless VG extent size is at least the page size.
69 Suppress some unnecessary --stripesize parameter warnings.
70 Fix 'pvmove -n name ...' to prohibit collocation of RAID SubLVs
71
72Version 2.02.164 - 15th August 2016
73===================================
74 Fix selection of PVs when allocating raid0_meta.
75 Fix sdbus socket leak leading to hang in lvmnotify.
76 Specify max stripes for raid LV types: raid0:64; 1:10; 4,5:63; 6:62; 10:32.
77 Avoid double suffix when naming _rmeta LV paired with _rimage LV.
78
79Version 2.02.163 - 10th August 2016
80===================================
81 Add profile for lvmdbusd which uses lvm shell json report output.
82 Restrict in-command modification of some parms in lvm shell.
83 Apply LVM_COMMAND_PROFILE early for lvm shell.
84 Refactor reporting so lvm shell log report collects whole of cmd execution.
85 Support LVM_*_FD envvars to redirect output to file descriptors.
86 Limit use of --corelog and --mirrorlog to mirrors in lvconvert.
87 Reject --nosync option for RAID6 LVs in lvcreate.
88 Do not refresh whole cmd context if profile dropped after processing LVM cmd.
89 Support straightforward lvconvert between striped and raid4 LVs.
90 Support straightforward lvconvert between raid1 and mirror LVs.
91 Report supported conversions when asked for unsupported raid lvconvert.
92 Add "--rebuild PV" option to lvchange to allow for PV selective rebuilds.
93 Preserve existing mirror region size when using --repair.
94 Forbid stripe parameters with lvconvert --repair.
95 Unify stripe size validation into get_stripe_params to catch missing cases.
96 Further lvconvert validation logic refactoring.
97
98Version 2.02.162 - 28th July 2016
99=================================
100 Extend vg_validate also to check raid configurations thoroughly.
101 Support lvconvert -Zn also when doing full cache pool conversion.
102 Suppress not zeroing warn when converting to thin LV for non-zeroing tpool.
103 Fix automatic updates of PV extension headers to newest version.
104 Improve lvconvert --trackchanges validation to require --splitmirrors 1.
105 Add note about lastlog built-in command to lvm man page.
106 Fix unrecognised segtype flag message.
107 lvconvert not clears cache pool metadata ONLY with -Zn.
108 Add allocation/raid_stripe_all_devices to reinstate previous behaviour.
109 Create raid stripes across fixed small numbers of PVs instead of all PVs.
110 Enabled lvconvert --uncache to work with partial VG.
111 Disallow lvconvert --replace with raid0* LVs.
112 Fix some lvmetad changed VG metadata notifications that sent uncommitted data.
113
114Version 2.02.161 - 15th July 2016
115=================================
116 Prohibit some lvchange/lvresize that were failing on raid0 volumes.
117 Fix segfaults in complex vgsplits. (2.02.159)
118 Reformat unwieldy lvconvert man page.
119 Allow --force to be passed through to pvcreate from vgcreate. (2.02.144)
120 Fix lvresize of filesystem when LV has already right size (2.02.141)
121 New LVM_LOG_FILE_MAX_LINES env var to limit max size of created logs.
122
123Version 2.02.160 - 6th July 2016
124================================
125 Minor fixes from coverity.
126
127Version 2.02.159 - 6th July 2016
128================================
129 Add raid0_meta segment type that provides metadata space for raid conversions.
130 Fix created link for a used pool for vgmknode.
131 Introduce and use is_power_of_2 macro.
132 Support conversions between striped and raid0 segment types.
133 Add infrastructure for raid takeover lvconvert options.
134
135Version 2.02.158 - 25th June 2016
136=================================
137 Add a more efficient native vgimportclone command to replace the script.
138 Make lvmlockd always attempt to connect to lvmetad if no connection exists.
139 Let lvmetad handle new connections after shutdown signal.
140 Disable lvmetad when vgcfgrestore begins and enable it again after.
141 Make pvscan do activation if lvmetad is configured but not running.
142 Fix rescanning the PVs for a single VG when using lvmetad.
143 Pool metadata lvresize uses now same code as resize of normal volume.
144 Preserve monitoring status when updating thin-pool metadata.
145 Return 0 (inactive) when status cannot be queried in _lv_active().
146 Switch to log_warn() for failing activation status query.
147 Replace vgimportclone script with binary.
148 While lvmetad is shutting down, continue handling all connections cleanly.
149 Refactor lvconvert argument handling code.
150 Notify lvmetad when vgcfgrestore changes VG metadata.
151 Add --logonly option to report only cmd log for a command, not other reports.
152 Add log/command_log_selection to configure default selection used on cmd log.
153 Use 'orphan' object type in cmd log for groups to collect PVs not yet in VGs.
154 Add lvm lastlog command for query and display of last cmd's log in lvm shell.
155 Report per-object return codes via cmd log while processing multiple objects.
156 Annotate processing code with log report hooks for per-object command log.
157 Also pass common printed messages (besides warnings and errors) to log report.
158 Log warnings and errors via report during cmd processing if this is enabled.
159 Make it possible to iterate over internal 'orphan' VGs in process_each_vg fn.
160 Make -S|--select option groupable that allows this option to be repeated.
161 Make -O|--sort option groupable that allows this option to be repeated.
162 Add --configreport option to select report for which next options are applied.
163 Add support for priorities on grouping command arguments.
164 Add report/{pvs,vgs,lvs,pvsegs,segs}_{cols,sort}_full to lvm.conf.
165 Add lvm fullreport command for joined PV, VG, LV and segment report per VG.
166 Integrate report group handling and cmd log report into cmd processing code.
167 Add log/report_command_log to lvm.conf to enable or disable cmd log report.
168 Add log/report_output_format to lvm.conf for default report output format.
169 Recognize --reportformat {basic|json} option to select report output format.
170 Add log/command_log_{sort,cols} to lvm.conf to configure command log report.
171 Add log_object_{type,name,id,group,group_id} fields to cmd log.
172 Add log_{seq_num,type,context,message,errno,ret_code} fields to cmd log.
173 Add CMDLOG report type - a separate report type for command logging.
174
175Version 2.02.157 - 17th June 2016
176=================================
177 Change pvscan --cache -aay to scan locally if lvmetad fails.
178
179Version 2.02.156 - 11th June 2016
180=================================
181 Don't allow duplicate orphan PVs to be used with vgcreate/vgextend/pvcreate.
182 Improve handling of lvmetad update failures.
183 Yes/No prompt accepts '^[ ^t]*([Yy]([Ee]([Ss]|)|)|[Nn]([Oo]|))[ ^t]*$'.
184 If available, also collect output from lsblk command when running lvmdump -s.
185
186Version 2.02.155 - 3rd June 2016
187================================
188 Reject PV tags on pvmove cmdline because only 1 PV is supported. (2.02.141)
189 Fix compilation error when building with configure --disable-devmapper.
190 Fix lvmconfig --type diff to display complete diff if config cascade used.
191 Automatically filter out partitioned loop devices with partscan (losetup -P).
192 Fix lvm devtypes internal error if -S used with field name from pvs/vgs/lvs.
193 When reporting Data%,Snap%,Meta%,Cpy%Sync use single ioctl per LV.
194 Add lvseg_percent_with_info_and_seg_status() for percent retrieval.
195 Enhance internal seg_status handling to understand snapshots better.
196 When refresh failed in suspend, call resume upon error path.
197 Support passthrough cache mode when waiting for clean cache.
198 Check cache status only for 'in-use' cache pools.
199 Extend setup_task() to preset flushing for dm_task object.
200 When checking LV is a merging COW, validate its a COW LV first.
201 Correcting value in copy_percent() for 100%.
202 Update vgreduce to use process_each_vg.
203 Update lvconvert to use process_each_lv.
204 Update pvscan to use process_each_vg for autoactivation.
205 Add basic support for --type raid0 using md.
206 Add support for lvchange --cachemode for cached LV.
207 Fix liblvm2app error handling when setting up context.
208 Delay liblvm2app init in python code until it is needed.
209 Simplify thread locking in lvmetad to fix locking problems.
210 Allow pvremove -ff to remove a duplicate PV.
211 Fix lvm2-activation-generator to read lvm.conf without full command setup.
212 Allow a minimal context to be used in lvm2app for reading lvm.conf.
213
214Version 2.02.154 - 14th May 2016
215================================
216 Fix liblvm segfault after failure initialising lvmetad connection.
217 Retry open without O_NOATIME if it fails (not file owner/CAP_FOWNER).
218 Split _report into one fn for options and arguments and one for processing.
219
220Version 2.02.153 - 7th May 2016
221===============================
222 Change warning messages related to duplicate PVs.
223 A named device is always processed itself, not switched for a duplicate.
224 Add PV attr "d" and report field "duplicate" for duplicate PVs.
225 Add config setting to disallow VG changes when duplicate PVs exist.
226 Use device size and active LVs to choose the preferred duplicate PV.
227 Disable lvmetad when duplicate PVs are seen.
228 Support --chunksize option also when caching LV when possible.
229 Add function to check for target presence and version via 1 ioctl.
230
231Version 2.02.152 - 30th April 2016
232==================================
233 Use any inherited tags when wiping metadata sub LVs to ensure activation.
234 Add str_list_wipe.
235 Improve support for interrupting procesing of volumes during lvchange.
236 Use failed command return code when lvchanging read-only volume.
237 Show creation transaction_id and zeroing state of pool with thin volume.
238 Stop checking for dm_cache_mq policy with cache target 1.9 (alias to smq).
239 Check first /sys/module/dm_* dir existance before using modprobe.
240 Remove mpath from 10-dm.rules, superseded by 11-dm-mpath.rules (mpath>=0.6.0).
241
242Version 2.02.151 - 23rd April 2016
243==================================
244 Fix error path after reusing of _setup_task (2.02.150).
245 Fix memory access for empty sysfs values (2.02.149).
246 Disable lvmetad when lvm1 metadata is seen, so commands revert to scanning.
247 Suppress errors when snapshot merge gets delayed because volume is in use.
248 Avoid internal snapshot LV names in messages.
249 Autodetect and use /run/lock dir when available instead of /var/lock.
250 lvchange --refresh for merging thin origin will retry to deactivate snapshot.
251 Recognize in-progress snapshot merge for thin volumes from dm table.
252 Avoid deciding to initiate a pending snapshot merge during resume.
253 Improve retrying lvmetad requests while lvmetad is being updated.
254 Read devices instead of using the lvmetad cache if rescan fails.
255 Move lvmetad token/filter check and device rescan to the start of commands.
256 Don't try deactivating fictional internal LV before snapshot merge. (2.02.105)
257 When not obtaining devs from udev, check they exist before caching them.
258 Detect device mismatch also when compiling without udev support.
259
260Version 2.02.150 - 9th April 2016
261=================================
262 Avoid using flushing dm status ioctl when checking for usable DM device.
263 Check for devices without LVM- uuid prefix only with kernels < 3.X.
264 Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
265 Allow the lvmdump directory to exist already provided it is empty.
266 Show lvconverted percentage with 2 decimal digits.
267 Fix regression in suspend when repairing --type mirror (2.02.133).
268
269Version 2.02.149 - 1st April 2016
270=================================
271 Do not flush thin-pool when checking metadata fullness.
272 Remove spurious error about no value in /sys/dev/block/major:minor/dm/uuid.
273 Fix device mismatch detection for LV if persistent .cache file is used.
274 Fix holder device not being found in /dev while sysfs has it during dev scan.
275
276Version 2.02.148 - 26th March 2016
277==================================
278 Introduce TARGET_NAME and MODULE NAME macros.
279 Replace hard-coded module and target names with macros.
280 Add pv_major and pv_minor report fields.
281 Detect and warn about mismatch between devices used and assumed for an LV.
282
283Version 2.02.147 - 19th March 2016
284==================================
285 If available, use /proc/self/mountinfo to detect mounted volume in fsadm.
286 Fix resize of stacked raid thin data volume (2.02.141).
287 Fix test for lvremove failure in lvconvert --uncache (2.02.146).
288
289Version 2.02.146 - 11th March 2016
290==================================
291 More man page cleanups in lvconvert.
292 Fix makefile vpath in /udev when generating udev rules files.
293 Another attempt to improve VG name parsing for lvconvert (2.02.144).
294 Use new cache status info and skip flushing for failed cache.
295 Support --uncache with missing PVs.
296 Tidy report field names, headings and widths.
297 Add vgscan --notifydbus to send a dbus notification.
298 Add dbus notification from commands after a PV/VG/LV changes state.
299
300Version 2.02.145 - 4th March 2016
301=================================
302 Make it possible to use lvremove and lvrename on historical LVs.
303 For historical LVs, report 'none' for lv_layout and 'history' for lv_role.
304 Add full_{ancestors,descendants} fields to report LV ancestry with history.
305 Report (h)istorical state within 5th bit (State) of the lv_attr field.
306 Add lv_historical reporting field to report if LV is historical or not.
307 Add lv_time_removed reporting field to display removal time for hist. LVs.
308 Report lv_name, lv_uuid, vg_name, lv_time for historical LVs.
309 Add --nohistory switch to lvremove to disable history recording on demand.
310 Add -H|--history switch to lvs and lvdisplay to include historical LVs.
311 Create historical LVs out of removed thin snapshot LVs and record in history.
312 Add metadata/lvs_history_retention_time for automatic removal of hist. LVs.
313 Add metadata/record_lvs_history config for switching LV history recording.
314 Add support and infrastructure for tracking historical LVs.
315 Improve lvconvert man page.
316 Add kernel_cache_policy lvs field.
317 Display [unknown] instead of 'unknown device' in pvs output.
318 Fix error path when pvcreate allocation fails (2.02.144).
319 Display [unknown] instead of blank for unknown VG names in pvs output.
320
321Version 2.02.144 - 26th February 2016
322=====================================
323 Use new PV processing code in pvcreate/vgcreate/vgextend/pvremove.
324 Add new PV processing code that prompts user without locks held.
325 Prevent lvmlockd blocking with new flag requiring sanlock 3.3.0.
326 Only show (u)sed pv_attr char when PV is not (a)llocatable. (2.02.143)
327 Update makefile to generate lcov output also for lvmpolld and lvmlockd.
328 Fix SystemdService lvm2-lvmdbusd.service name.
329 Improve support for env LVM_VG_NAME for reference VG name in lvconvert.
330 Fix regression when lvresize accepted zero sizes. (2.02.141)
331 Always warn user about PV in use even when pvremove uses --force --force.
332 Use uninitialized pool header detection in all cases.
333 Fix read error detection when checking for uninitialized thin-pool header.
334 Fix error path for internal error in lvmetad VG lookup code.
335
336Version 2.02.143 - 21st February 2016
337=====================================
338 Fix error path when sending thin-pool message fails in update_pool_lv().
339 Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
340 For failing thin-pool and thin volume correctly report percentage as INVALID.
341 Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
342 Add configure --enable-dbus-service for an LVM D-Bus service.
343 Replace configure --enable-python_bindings with python2 and python3 versions.
344 If PV belongs to some VG and metadata missing, skip it if system ID is used.
345 Automatically change PV header extension to latest version if writing PV/VG.
346 Identify used PVs in pv_attr field by new 'u' character.
347 Add pv_in_use reporting field to report if PV is used or not.
348 Add pv_ext_vsn reporting field to report PV header extension version.
349 Add protective flag marking PVs as used even if no metadata available.
350
351Version 2.02.142 - 15th February 2016
352=====================================
353 Fix memory pool corruption in pvmove (2.02.141).
354 Support control of spare metadata creation when repairing thin-pool.
355 Fix config type of 'log/verbose' from bool to int (2.02.99).
356 Fix inverted data LV thinp watermark calc for dmeventd response (2.02.133).
357 Use use_blkid_wiping=0 if not defined in lvm.conf and support not compiled in.
358 Do not check for suspended devices if scanning for lvmetad update.
359 Clear cached bootloader areas when PV format changed.
360 Fix partn table filter with external_device_info_source="udev" and blkid<2.20.
361
362Version 2.02.141 - 25th January 2016
363====================================
364 Add metadata/check_pv_device_sizes switch to lvm.conf for device size checks.
365 Warn if device size is less than corresponding PV size in metadata.
366 Cache device sizes internally.
367 Restore support for command breaking in process_each_lv_in_vg() (2.02.118).
368 Use correct mempool when process_each_lv_in_vg() (2.02.118).
369 Fix lvm.8 man to show again prohibited suffixes.
370 Fix configure to set proper use_blkid_wiping if autodetected as disabled.
371 Initialise udev in clvmd for use in device scanning. (2.02.116)
372 Add seg_le_ranges report field for common format when displaying seg devices.
373 Honour report/list_item_separator for seg_metadata_le_ranges report field.
374 Don't mark hidden devs in -o devices,metadata_devices,seg_pe_ranges.(2.02.140)
375 Change LV sizes in seg_pe_ranges report field to match underlying devices.
376 Add kernel_cache_settings report field for cache LV settings used in kernel.
377
378Version 2.02.140 - 16th January 2016
379====================================
380 Fix lvm2app to return either 0 or 1 for lvm_vg_is_{clustered,exported}.
381 Add kernel_discards report field to display thin pool discard used in kernel.
382 Correct checking of target presence when driver access is disabled.
383 Eval poolmetadatasize arg earlier in lvresize.
384 Fix vgcfgrestore to respect allocatable attribute of PVs.
385 Add report/mark_hidden_devices to lvm.conf.
386 Use brackets consistently in report fields to mark hidden devices.
387 Restore background polling processing during auto-activation (2.02.119).
388 Fix invalid memory read when reporting cache LV policy_name (2.02.126).
389
390Version 2.02.139 - 8th January 2016
391===================================
392 Update lvmlockd with the new VG seqno before devices are suspended.
393 Rework vgrename to use the common processing code in toollib.
394 Make pvs show new devices on the system since the last .cache update.
395 Document F,D and M thin pool health status chars for lv_attr in lvs man page.
396 Also add lvm2-activation{-early,-net}.service systemd status for lvmdump -s.
397
398Version 2.02.138 - 14th December 2015
399=====================================
400 Support lvrename for hidden (used) cache pools.
401 Fix lvrename for stacked cache pools.
402
403Version 2.02.137 - 5th December 2015
404====================================
405 Restore archiving before changing metadata in vgextend (2.02.117).
406 Dropped internal usage of log_suppress(2).
407 Cleaned logging code for buffer size usage.
408 Added internal id_read_format_try() function to check and read valid UUID.
409 Change lvcreate, lvrename, lvresize to use process_each_vg.
410 Change process_each_vg to handle single VG as separate arg.
411 Issue error if ambiguous VG name is supplied in most commands.
412 Make process_each fns always work through full list of known VG names.
413 Use dm_get_status_mirror() instead of individual parsers.
414 Add mem pool arg for check_transient_status() target function.
415 Avoid misleading error with -m is omitted with lvconvert to raid types.
416 Add system_id to vginfo cache.
417
418Version 2.02.136 - 28th November 2015
419=====================================
420 Add new --sinceversion option for lvmconfig --type new.
421 Fix inactive table loaded for wrapping thin-pool when resizing it.
422 Extend the list of ignored libraries when locking memory.
423
424Version 2.02.135 - 23rd November 2015
425=====================================
426 Add a model file for Coverity.
427 Show correct error message for unsupported yet cache pool repair.
428 Allow lvconvert cache pools' data and metadata LV to raid.
429 Fix reading of old metadata with missing cache policy or mode settings.
430 Issue error if external_device_info_source=udev and udev db record incomplete.
431 Update lvmetad duplicate VG name handling to use hash function extensions.
432 Detect invalid vgrenames by vgid where the name is unchanged.
433 Fix passing of 32bit values through daemons (mostly lvmlockd).
434 Use local memory pool for whole alloc_handle manipulation.
435 Add missing pointer validation after dm_get_next_target().
436 Do not deref NULL pointer in debug message for _match_pv_tags().
437 Drop unneeded stat() call when checking for sysfs file.
438 Fix memory leak on error path of failing thin-pool percentage check.
439 Add missing test for failing node allocation in lvmetad.
440 Correct configure messages when enabling/disabling lvmlockd.
441
442Version 2.02.134 - 9th November 2015
443====================================
444 Refactor some lvmetad code and adjust some duplicate PV messages.
445 No longer repair/wipe VG/PVs if inaccessible because foreign or shared.
446 Pass correct data size to mirror log calc so log can be bigger than 1 extent.
447
448Version 2.02.133 - 30th October 2015
449====================================
450 Support repeated -o|--options for reporting commands.
451 Support -o- and -o# for reporting commands to remove and compact fields.
452 Fix missing PVs from pvs output if vgremove is run concurrently.
453 Remove unwanted error message when running pvs/vgs/lvs and vgremove at once.
454 Check newly created VG's metadata do not overlap in metadata ring buffer.
455 Check metadata area size is at least the minimum size defined for the format.
456 Thin pool targets uses low_water_mark from profile.
457 Dropping 'yet' from error of unsupported thick snapshot of snapshots.
458 Do not support unpartitioned DASD devices with CDL formatted with pvcreate.
459 For thins use flush for suspend only when volume size is reduced.
460 Enable code which detects the need of flush during suspend.
461 Ensure --use-policy will resize volume to fit below threshold.
462 Correct percentage evaluation when checking thin-pool over threshold.
463 Fix lvmcache to move PV from VG to orphans if VG is removed and lvmetad used.
464 Fix lvmcache to not cache even invalid info about PV which got removed.
465 Support checking of memlock daemon counter.
466 Allow all log levels to be used with the lvmetad -l option.
467 Add optional shutdown when idle support for lvmetad.
468 Fix missing in-sync progress info while lvconvert used with lvmpolld.
469 Add report/compact_output_cols to lvm.conf to define report cols to compact.
470 Do not change logging in lvm2 library when it's already set.
471 Check for enough space in thin-pool in command before creating new thin.
472 Make libblkid detect all copies of the same signature if use_blkid_wiping=1.
473 Fix vgimportclone with -n to not add number unnecessarily to base VG name.
474 Cleanup vgimportclone script and remove dependency on awk, grep, cut and tr.
475 Add vg_missing_pv_count report field to report number of missing PVs in a VG.
476 Properly identify internal LV holding sanlock locks within lv_role field.
477 Add metadata_devices and seg_metadata_le_ranges report fields for raid vols.
478 Fix lvm2-{activation,clvmd,cmirrord,monitor} service to exec before mounting.
479
480Version 2.02.132 - 22nd September 2015
481======================================
482 Fix lvmconf to set locking_type=2 if external locking library is requested.
483 Remove verbose message when rescanning an unchanged device. (2.02.119)
484 Add origin_uuid, mirror_log_uuid, move_pv_uuid, convert_lv_uuid report fields.
485 Add pool_lv_uuid, metadata_lv_uuid, data_lv_uuid reporting fields.
486 Fix PV label processing failure after pvcreate in lvm shell with lvmetad.
487
488Version 2.02.131 - 15th September 2015
489======================================
490 Rename 'make install_full_man' to install_all_man and add all_man target.
491 Fix vgimportclone cache_dir path name (2.02.115).
492 Swapping of LV identifiers handles more complex LVs.
493 Use passed list of PVS when allocating space in lvconvert --thinpool.
494 Disallow usage of --stripe and --stripesize when creating cache pool.
495 Warn user when caching raid or thin pool data LV.
496 When layering LV, move LV flags with segments.
497 Ignore persistent cache if configuration changed. (2.02.127)
498 Fix devices/filter to be applied before disk-accessing filters. (2.02.112)
499 Make tags only when requested via 'make tags'.
500 Configure supports --disable-dependency-tracking for one-time builds.
501 Fix usage of configure.h when building in srcdir != builddir.
502
503Version 2.02.130 - 5th September 2015
504=====================================
505 Fix use of uninitialized device status if reading outdated .cache record.
506 Restore support for --monitor option in lvcreate (2.02.112).
507 Read thin-pool data and metadata percent without flush.
508 Detect blocked thin-pool and avoid scanning their thin volumes.
509 Check if dm device is usable before checking its size (2.02.116).
510 Extend parsing of cache_check version in configure.
511 Make lvpoll error messages visible in lvmpolld's stderr and in syslog.
512 Add 'make install_full_man' to install all man pages regardless of config.
513
514Version 2.02.129 - 26th August 2015
515===================================
516 Drop error message when vgdisplay encounters an exported VG. (2.02.27)
517 Fix shared library generation to stop exporting internal functions.(2.02.120)
518 Accept --cachemode with lvconvert.
519 Fix and improve reporting properties of cache-pool.
520 Enable usage of --cachepolicy and --cachesetting with lvconvert.
521 Don't allow to reduce size of thin-pool metadata.
522 Fix debug buffer overflows in cmirrord logging.
523 Add --foreground and --help to cmirrord.
524
525Version 2.02.128 - 17th August 2015
526===================================
527 Allocation setting cache_pool_cachemode is replaced by cache_mode.
528 Don't attempt to close config file that couldn't be opened.
529 Check for valid cache mode in validation of cache segment.
530 Change internal interface handling cache mode and policy.
531 When no cache policy specified, prefer smq (if available) over mq.
532 Add demo cache-mq and cache-smq profiles.
533 Add cmd profilable allocation/cache_policy,cache_settings,cache_mode.
534 Require cache_check 0.5.4 for use of --clear-needs-check-flag.
535 Fix lvmetad udev rules to not override SYSTEMD_WANTS, add the service instead.
536
537Version 2.02.127 - 10th August 2015
538===================================
539 Do not init filters, locking, lvmetad, lvmpolld if command doesn't use it.
540 Order fields in struct cmd_context more logically.
541 Add lock_type to lvmcache VG summary and info structs.
542 Fix regression in cache causing some PVs to bypass filters (2.02.105).
543 Make configure --enable-realtime the default now.
544 Update .gitignore and configure.in files to reflect usage of current tree.
545
546Version 2.02.126 - 24th July 2015
547=================================
548 Fix long option hyphen removal. (2.02.122)
549 Fix clvmd freeze if client disappears without first releasing its locks.
550 Fix lvconvert segfaults while performing snapshots merge.
551 Ignore errors during detection if use_blkid_wiping=1 and --force is used.
552 Recognise DM_ABORT_ON_INTERNAL_ERRORS env var override in lvm logging fn.
553 Fix alloc segfault when extending LV with fewer stripes than in first seg.
554 Fix handling of cache policy name.
555 Set cache policy before with the first lvm2 cache pool metadata commit.
556 Fix detection of thin-pool overprovisioning (2.02.124).
557 Fix lvmpolld segfaults on 32 bit architectures.
558 Add lvmlockd lock_args validation to vg_validate.
559 Fix ignored --startstopservices option if running lvmconf with systemd.
560 Hide sanlock LVs when processing LVs in VG unless named or --all used.
561
562Version 2.02.125 - 7th July 2015
563================================
564 Fix getline memory usage in lvmpolld.
565 Add support --clear-needs-check-flag for cache_check of cache pool metadata.
566 Add lvmetactl for developer use only.
567 Rename global/lock_retries to lvmlockd_retries.
568 Replace --enable-lvmlockd by --enable-lockd-sanlock and --enable-lockd-dlm.
569
570Version 2.02.124 - 3rd July 2015
571================================
572 Move sending thin pool messages from resume to suspend phase.
573 Report warning when pool is overprovisioned and not auto resized.
574 Recognize free-form date/time values for lv_time field in selection criteria.
575 Added experimental lvmlockd with configure --enable-lvmlockd.
576 Fix regression in select to match string fields if using synonyms (2.02.123).
577 Fix regression when printing more lv names via display_lvname (2.02.122).
578 Add missing error logging to unlock_vg and sync_local_dev_names callers.
579
580Version 2.02.123 - 30th June 2015
581=================================
582 Add report/time_format lvm.conf option to define time format for report.
583 Fix makefile shell compare == when building lvmetad lvmpolld (2.02.120).
584 Add --type full to lvmconfig for full configuration tree view.
585 Add undocumented environment variables to lvm man page. (2.02.119)
586 Add device synchronization point before activating a new snapshot.
587 Add --withspaces to lvmconfig to add spaces in output for better readability.
588 Add custom main function to libdaemon.
589 Use lvmetad to track out-of-date metadata discovered.
590
591Version 2.02.122 - 20th June 2015
592=================================
593 Flush stdout before printing to stderr.
594 Use pre-allocated buffer for printed LV names in display_lvname.
595 Support thins with size of external origin unaligned with thin pool chunk.
596 Allow extension of reduced thin volumes with external origins.
597 Consider snapshot and origin LV as unusable if component devices suspended.
598 Fix lvmconfig segfault on settings with undefined default value (2.02.120).
599 Add explicit 's' (shared) LV activation mode.
600 Ignore hyphens in long options names (i.e. --long-option == --longoption).
601
602Version 2.02.121 - 12th June 2015
603=================================
604 Distinguish between on-disk and lvmetad versions of text metadata.
605 Remove DL_LIBS from Makefiles for daemons that don't need them.
606 Zero errno in before strtoul call in dmsetup if tested after the call.
607 Zero errno in before strtoul call in lvmpolld.
608 Fix a segfault in pvscan --cache --background command.
609 Fix test for AREA_PV when checking for failed mirrors.
610 Do not use --sysinit in lvm2-activation{-early,-net}.service if lvmpolld used.
611 Maintain outdated PV info in lvmetad till all old metadata is gone from disk.
612 Do not fail polling when poll LV not found (already finished or removed).
613 Replace poll_get_copy_vg/lv fns with vg_read() and find_lv() in polldaemon.
614 Close all device fds only in before sleep call in polldaemon.
615 Simplify Makefile targets that generate exported symbols.
616 Move various -D settings from Makefiles to configure.h.
617
618Version 2.02.120 - 15th May 2015
619================================
620 Make various adjustments to Makefile compilation flags.
621 Add lvmpolld debug message class.
622 Add lvmpolld client mode for querying running server instance for status info.
623 Fix some libdaemon socket creation and reuse error paths.
624 Daemons (libdaemon) support exit on idle also in non-systemd environment.
625 Provide make dist and make rpm targets
626 Configure lvm.conf for use_lvmetad and use_lvmpolld.
627 Add lvpoll for cmdline communication with lvmpolld.
628 Add lvmpolld acting as a free-standing version of polldaemon.
629 Avoid repeated identical lvmetad VG lookups in commands processing all VGs.
630 Handle switches to alternative duplicate PVs efficiently with lvmetad.
631 Properly validate PV size for pvcreate --restorefile.
632 Fix check if pvcreate wiped device (2.02.117).
633 Fix storing of vgid when caching metadata (2.02.118).
634 Fix recursive lvm-config man page. (2.02.119)
635 Refactor polldaemon interfaces to poll every operation by VG/LV couple
636 Skip wait after testing in _wait_for_single_lv when polling finished
637 Return 'None' in python for empty string properties instead of crashing.
638 Distinguish signed numerical property type in reports for lvm2app library.
639 Reread raid completion status immediately when progress appears to be zero.
640 lvm2app closes locking on lvm_quit().
641 Configure detects /run or /var/run.
642 Add missing newline in clvmd --help output.
643
644Version 2.02.119 - 2nd May 2015
645===============================
646 New LVM_LOG_FILE_EPOCH, LVM_EXPECTED_EXIT_STATUS env vars. Man page to follow.
647 Remove detailed content from lvm.conf man page: use lvmconfig instead.
648 Generate complete config files with lvmconfig or 'make generate'.
649 Also display info on deprecated config with lvmconfig --withcomments.
650 Display version since which config is deprecated in lvmconfig --withversions.
651 Add --showdeprecated to lvmconfig to also display deprecated settings.
652 Hide deprecated settings in lvmconfig output for all types but current,diff.
653 Introduce support for exit on idle feature in libdaemon
654 Add --showunsupported to lvmconfig to also display unsupported settings.
655 Display unsupported settings for lvmconfig --type current,diff only by default
656 Honour lvmconfig --ignoreunsupported and --ignoreadvanced for all --type.
657 Make python bindings usable with python3 (and compatible with 2.6 & 2.7).
658 Add lvmconfig -l|--list as shortcut for lvmconfig --type list --withsummary.
659 Add lvmconfig --type list to display plain list of configuration settings.
660 Introduce lvmconfig as the preferred form of 'lvm dumpconfig'.
661 Add lv_ancestors and lv_descendants reporting fields.
662 Add --ignorelocal option to dumpconfig to ignore the local section.
663 Close connection to lvmetad after fork.
664 Make lvchange able to resume background pvmove polling again.
665 Split pvmove update metadata fn in an initial one and a subsequent one.
666 Refactor shared pvmove and lvconvert code into new _poll files.
667 Add --unconfigured option to dumpconfig to print strings unconfigured.
668 Add --withsummary option to dumpconfig to print first line - summary comment.
669 Use number of device holders to help choose between duplicate PVs.
670 Try to make lvmetad and non-lvmetad duplicate PV handling as similar as poss.
671 Issue warnings about duplicate PVs discovered by lvmetad.
672 Track alternative devices with matching PVIDs in lvmetad.
673 Check for lvm binary in blkdeactivate and skip LVM processing if not present.
674 Add --enable-halvm and --disable-halvm options to lvmconf script.
675 Add --services, --mirrorservice and --startstopservices option to lvmconf.
676 Use proper default value of global/use_lvmetad when processing lvmconf script.
677 Respect allocation/cling_tag_list during intial contiguous allocation.
678 Add A_PARTITION_BY_TAGS set when allocated areas should not share tags.
679 Make changes persist with python addTag/removeTag.
680 Set correct vgid when updating cache when writing PV metadata.
681 More efficient clvmd singlenode locking emulation.
682 Reject lvcreate -m with raid4/5/6 to avoid unexpected layout.
683 Don't skip invalidation of cached orphans if vg write lck is held (2.02.118).
684 Log relevant PV tags when using cling allocation.
685 Add str_list_add_list() to combine two lists.
686 Fix LV processing with selection to always do the selection on initial state.
687 Add internal LV_REMOVED LV status flag.
688
689Version 2.02.118 - 23rd March 2015
690==================================
691 Store metadata size + checksum in lvmcache and add struct lvmcache_vgsummary.
692 Remove inaccessible clustered PVs from 'pvs -a'.
693 Don't invalidate cached orphan information while global lock is held.
694 Avoid rescan of all devices when requested pvscan for removed device.
695 Measure configuration timestamps with nanoseconds when available.
696 Disable lvchange of major and minor of pool LVs.
697 Fix pvscan --cache to not scan and read ignored metadata areas on PVs.
698 Add After=iscsi-shutdown.service to blk-availability.service systemd unit.
699 Disallow vgconvert from changing metadata format when lvmetad is used.
700 Don't do a full read of VG when creating a new VG with an existing name.
701 Reduce amount of VG metadata parsing when looking for vgname on a PV.
702 Avoid reparsing same metadata when reading same metadata from multiple PVs.
703 Save extra device open/close when scanning device for size.
704 Fix seg_monitor field to report status also for mirrors and thick snapshots.
705 Replace LVM_WRITE with LVM_WRITE_LOCKED flags in metadata if system ID is set.
706 Remove ACCESS_NEEDS_SYSTEM_ID VG status flag. (2.02.117)
707 Enable system ID features.
708
709Version 2.02.117 - 4th March 2015
710=================================
711 Add CFG_DISABLED for new system ID config settings that must not yet be used.
712 Preserve original format type field when processing backup files.
713 Implement status action for lvm2-monitor initscript to display monitored LVs.
714 Allow lvchange -p to change kernel state only if metadata state differs.
715 Fix incorrect persistent .cache after report with label fields only (2.02.106).
716 Reinstate PV tag recognition for pvs if reporting label fields only (2.02.105).
717 Rescan devices before vgimport with lvmetad so exported VG is seen.
718 Fix hang by adjusting cluster mirror regionsize, avoiding CPG msg limit.
719 Do not crash when --cachepolicy is given without --cachesettings.
720 Add NEEDS_FOREIGN_VGS flag to vgimport so --foreign is always supplied.
721 Add --foreign to the 6 display and reporting tools and vgcfgbackup.
722 Install /etc/lvm/lvmlocal.conf template with local section for systemid.
723 Record creation_host_system_id in lvm2 metadata (never set yet).
724 Reinstate recursive config file tag section processing. (2.02.99)
725 Add 'lvm systemid' to display the current system ID (never set yet).
726 Fix configure to properly recognize --with-default-raid10-segtype option.
727 Do not refresh filters/rescan if no signature is wiped during pvcreate.
728 Enforce none external dev info for wiping during pvcreate to avoid races.
729 Add global/system_id_source and system_id_file to lvm.conf (disabled).
730 Add support for VG system_id to control host access to VGs.
731 Update vgextend to use process_each_vg.
732 Add --ignoreskippedcluster to pvchange.
733 Allow pvchange to modify several properties at once.
734 Update pvchange to use process_each_pv.
735 Fix pvs -a used with lvmetad to filter out devices unsuitable for PVs.
736 Fix selection to recognize units for ba_start, vg_free and seg_start fields.
737 Add support for -S/--select to vgexport and vgimport.
738 Add support for -S/--select to vgdisplay, lvdisplay and pvdisplay without -C.
739 Add support for -S/--select to vgremove and lvremove.
740 Add support for -S/--select to vgchange,lvchange and pvchange.
741 Add infrastructure to support selection for non-reporting tools.
742 Add LVM_COMMAND_PROFILE env var to set default command profile name to use.
743 Set CLOEXEC flag on file descriptors originating in libdaemon.
744
745Version 2.02.116 - 30th January 2015
746====================================
747 Deactivate unused thin pools activated with lvm2 pre-2.02.112 versions.
748 Check lock holding LV when lvconverting stacked raid LV in cluster.
749 Support udev external dev info for filters: PV min size, mpath, md, partition.
750 Add fw_raid_component_detection lvm.conf option to enable FW raid detection.
751 Add devices/external_device_info_source lvm.conf option ("none" by default).
752 Scan pools in for_each_sub_lv() and add for_each_sub_lv_except_pools().
753 Fix lvm2app lvm_lv_get_property return value for fields with info/status ioctl.
754 Fix lvm2app regression in lvm_lv_get_attr causing unknown values (2.02.115).
755 Set default cache_mode to writehrough when missing in metadata.
756 Preserve chunk size with repair and metadata swap of a thin pool.
757 Fix raid --splitmirror 1 functionality (2.02.112).
758 Fix tree preload to handle splitting raid images.
759 Do not support unpartitioned DASD devices.
760 Improve config validation to check if setting with string value can be empty.
761
762Version 2.02.115 - 21st January 2015
763====================================
764 Report segment types without monitoring support as undefined.
765 Support lvchange --errorwhenfull for thin pools.
766 Improve the processing and reporting of duplicate PVs.
767 Report lv_health_status and health attribute also for thin pool.
768 Add lv_when_full reporting field.
769 Add support for lvcreate --errorwhenfull y|n for thin pools.
770 Fix lvconvert --repair to honour resilience requirement for segmented RAID LV.
771 Filter out partitioned device-mapper devices as unsuitable for use as PVs.
772 Also notify lvmetad about filtered device if using pvscan --cache DevicePath.
773 Use LVM's own selection instead of awk expressions in clvmd startup scripts.
774 Do not filter out snapshot origin LVs as unusable devices for an LVM stack.
775 Fix incorrect rimage names when converting from mirror to raid1 LV (2.02.112).
776 Introduce pvremove_many to avoid excessive metadata re-reading and messages.
777 Check for cmirror availability during cluster mirror creation and activation.
778 Add cache_policy and cache_settings reporting fields.
779 Add missing recognition for --binary option with {pv,vg,lv}display -C.
780 Fix vgimportclone to notify lvmetad about changes done if lvmetad is used.
781 Fix vgimportclone to properly override config if it is missing in lvm.conf.
782 Fix automatic use of configure --enable-udev-systemd-background-jobs.
783 Correctly rename active split LV with -splitmirrors for raid1.
784 Add report/compact_output to lvm.conf to enable/disable compact report output.
785 Still restrict mirror region size to power of 2 when VG extent size is not.
786
787Version 2.02.114 - 28th November 2014
788=====================================
789 Release socket in daemon_close and protocol string in daemon_open error path.
790 Add --cachepolicy and --cachesettings to lvcreate.
791 Fix regression when parsing /dev/mapper dir (2.02.112).
792 Fix missing rounding to 64KB when estimating optimal thin pool chunk size.
793 Fix typo in clvmd initscript causing CLVMD_STOP_TIMEOUT var to be ignored.
794 Fix size in pvresize "Resizing to ..." verbose msg to show proper result size.
795
796Version 2.02.113 - 24th November 2014
797=====================================
798 Add --cachepolicy and --cachesettings options to lvchange.
799 Validate that converted volume and specified pool volume differ in lvconvert.
800 Fix regression in vgscan --mknodes usage (2.02.112).
801 Respect --prefix when setting CLMVD_PATH configure (2.02.89).
802 Default to configure --enable-udev-systemd-background-jobs for systemd>=205.
803 Fix ignore_vg() to properly react on various vg_read errors (2.02.112).
804 Failed recovery returns FAILED_RECOVERY status flag for vg_read().
805 Exit with non-zero status code when pvck encounters a problem.
806 Fix clean_tree after activation/resume for cache target (2.02.112).
807
808Version 2.02.112 - 11th November 2014
809=====================================
810 Add cache_{read,write}_{hits,misses} reporting fields.
811 Add cache_{total,used,dirty}_blocks reporting fields.
812 Add _corig as reserved suffix.
813 Reduce number of VG writes and commits when creating spare volumes.
814 When remove_layer_from_lv() removes layer, restore subLV names.
815 Cache-pool in use becomes invisible LV.
816 Don't prompt for removal of _pmspare in VG without pool metadata LV.
817 Deactivation of snapshot origin detects and deactivates left-over snapshots.
818 Properly report error when taking snapshot of any cache type LV.
819 Add basic thread debugging messages to dmeventd.
820 Include threads being shutdown in dmeventd device registration responses.
821 Inital support for external users of thin pools based on transaction_id.
822 Report some basic percentage info for cache pools.
823 Introduce size_mb_arg_with_percent() for advanced size arg reading.
824 Add extra support for '.' as decimal point in size args.
825 Add configure parameters for default segment type choices.
826 Add global/sparse_segtype_default setting to use thin for --type sparse.
827 Update and correct lvcreate and lvcovert man pages.
828 Mark pools and snapshots as unzeroable volumes.
829 Check for zeroing of volume after segment type is fully detected.
830 Better support for persistent major and minor options with lvcreate.
831 Refactor lvcreate towards more complete validation of all supported options.
832 Support lvcreate --type linear.
833 Improve _should_wipe_lv() to warn with message.
834 Inform about temporarily created volumes only in verbose mode.
835 Better support for --test mode with pool creation.
836 Query lock holding LV when replacing and converting raid volumes.
837 Add extra validate for locked lv within validate_lv_cache_create().
838 Add internal lvseg_name() function.
839 Skip use of lock files for virtual internal VG names.
840 Fix selection on {vg,lv}_permissions fields to properly match selection criteria.
841 Fix lv_permissions reporting to display read-only{-override} instead of blank.
842 Fix liblvm2cmd and lvm shell to respect quotes around args in cmd line string.
843 Permit extent sizes > 128KB that are not power of 2 with lvm2 format.
844 Remove workaround for lvm2-monitor.service hang on stop if lvmetad stopped.
845 Change vgremove to use process_each_lv_in_vg.
846 Allow lvconvert --repair and --splitmirrors on internal LVs.
847 Introduce WARN_ flags to control some metadata warning messages.
848 Use process_each_pv in vgreduce.
849 Refactor process_each_pv in toollib.
850 Introduce single validation routine for pool chunk size.
851 Support --yes like --force in vg/lvremove to skip y|n prompt.
852 Support --yes with lvconvert --splitsnapshot.
853 Fix detection of unsupported thin external lvconversions.
854 Fix detection of unsupported cache and thin pool lvconversions.
855 Fix detection of unsupported lvconversion of cache to snapshot.
856 Improve code for creation of cache and cache pool volumes.
857 Check cluster-wide (not local) active status before removing LV.
858 Properly check if activation of removed cached LV really activated.
859 lvremove cached LV removes cachepool (keep with lvconvert --splitcache).
860 Always remove spare LV with last removed pool volume.
861 Support lvconvert --splitcache and --uncache of cached LV.
862 Option --cache has also shortcut -H (i.e. lvcreate -H).
863 Refactor lvcreate code and better preserve --type argument.
864 Refactor filter processing around lvmetad.
865 Refactor process_each_lv in toollib.
866 Refactor process_each_vg in toollib.
867 Pools cannot be used as external origin.
868 Use lv_update_and_reload() for snapshot reload.
869 Don't print message in adjusted_mirror_region_size() in activation.
870 Improve lv_update_and_reload() to find out proper lock holding LV.
871 Improve search of LV in lv_ondisk().
872 Do not scan sysfs in lv_check_not_in_use() when device is closed.
873 Backup final metadata after resync of mirror/raid.
874 Unify handling of --persistent option for lvcreate and lvchange.
875 Validate major and minor numbers stored in metadata.
876 Use -fPIE when linking -pie executables.
877 Support DEBUG_MEMLOCK to trap unsupported mmap usage.
878 Enable cache segment type by default.
879 Ensure only supported volume types are used with cache segments.
880 Fix inablility to specify cachemode when 'lvconvert'ing to cache-pool.
881 Grab cluster lock for active LVs when setting clustered attribute.
882 Use va_copy to properly pass va_list through functions.
883 Add function to detect rotational devices.
884 Review internal checks for mirror/raid/pvmove volumes.
885 Track mirror segment type with separate MIRROR flag.
886 Fix cmirror endian conversions.
887 Introduce lv_is_pvmove/locked/converting/merging macros.
888 Avoid leaving linear logical volume when thin pool creation fails.
889 Don't leak alloc_handle on raid target error path.
890 Properly validate raid leg names.
891 Archive metadata before starting their modification in raid target.
892 Add missing vg_revert() in suspend_lv() raid and snapshot error path.
893 Add missing backup of lvm2 metadata after some raid modifications.
894 Use vg memory pool for extent allocation.
895 Add allocation/physical_extent_size config option for default PE size of VGs.
896 Demote an error to a warning when devices known to lvmetad are filtered out.
897 Re-order filter evaluation, making component filters global.
898 Fix logic that checks for full scan before iterating through devices.
899 Introduce common code to modify metadata and reload updated LV.
900 Fix rename of active snapshot volume in cluster.
901 Make sure shared libraries are built with RELRO option.
902
903Version 2.02.111 - 1st September 2014
904=====================================
905 Pass properly sized char buffers for sscanf when initializing clvmd.
906 Reinstate nosync logic when extending mirror. (2.02.110)
907 Fix total area extent calculation when allocating cache pool. (2.02.110)
908
909Version 2.02.110 - 26th August 2014
910===================================
911 Fix manipulation with thin-pools which are excluded via volume_list.
912 Support lv/vgremove -ff to remove thin vols from broken/inactive thin pools.
913 Fix typo breaking configure --with-lvm1=shared.
914 Modify lvresize code to handle raid/mirrors and physical extents.
915 Don't allow pvcreate to proceed if scanning or filtering fails.
916 Cleanly error when creating RAID with stripe size < PAGE_SIZE.
917 Print name of LV which on activation triggers delayed snapshot merge.
918 Add lv_layout and lv_role LV reporting fields.
919 Properly display lvs lv_attr volume type and target type bit for cache origin.
920 Fix pvcreate_check() to update cache correctly after signature wiping.
921 Fix primary device lookup failure for partition when processing mpath filter.
922 If LV inactive and non-clustered, do not issue "Cannot deactivate" on -aln.
923 Remove spurious "Skipping mirror LV" message on pvmove of clustered mirror.
924
925Version 2.02.109 - 5th August 2014
926==================================
927 Remove lv_volume_type field from reports. (2.02.108)
928 Fix a segfault in lvscan --cache when devices were already missing. (2.02.108)
929 Fix incorrect persistent .cache after vgcreate with PV creation. (2.02.108)
930 Display actual size changed when resizing LV.
931 Allow approximate allocation with +%FREE in lvextend.
932 Remove possible spurious "not found" message on PV create before wiping.
933 Handle upgrade from 2.02.105 when an LV now gaining a uuid suffix is active.
934
935Version 2.02.108 - 23rd July 2014
936=================================
937 Add lvscan --cache which re-scans constituents of a particular LV.
938 Make dmeventd's RAID plugin re-scan failed PVs when lvmetad is in use.
939 Improve code sharing for lvconvert and lvcreate and pools (cache & thin).
940 Improve lvconvert --merge validation.
941 Improve lvconvert --splitsnapshot validation.
942 Add report/list_item_separator lvm.conf option.
943 Add lv_active_{locally,remotely,exclusively} LV reporting fields.
944 Comment out devices/{preferred_names,filter} in default lvm.conf file.
945 Enhance lvconvert thin, thinpool, cache and cachepool command line support.
946 Display 'C' only for cache and cache-pool target types in lvs.
947 Prompt for confirmation before change LV into a snapshot exception store.
948 Return proper error codes for some failing lvconvert funtions.
949 Add initial code to use cache tools (cache_check|dump|repair|restore).
950 Support lvdisplay --maps for raid.
951 Add --activationmode degraded to activate degraded raid volumes by default.
952 Add separate lv_active_{locally,remotely,exclusively} LV reporting fields.
953 Recognize "auto"/"unmanaged" values in selection for appropriate fields only.
954 Add report/binary_values_as_numeric lvm.conf option for binary values as 0/1.
955 Add --binary arg to pvs,vgs,lvs and {pv,vg,lv}display -C for 0/1 on reports.
956 Add separate reporting fields for each each {pv,vg,lv}_attr bit.
957 Separate LV device status reporting fields out of LV fields.
958 Fix regression causing PVs not in VGs to be marked as allocatable (2.02.59).
959 Fix VG component of lvid in vgsplit/vgmerge and check in vg_validate.
960 Add lv_full_name, lv_parent and lv_dm_path fields to reports.
961 Change lv_path field to suppress devices that never appear in /dev/vg.
962 Postpone thin pool lvconvert prompts (2.02.107).
963 Require --yes option to skip prompt to lvconvert thin pool chunksize.
964 Support lvremove -ff to remove thin volumes from broken thin pools.
965 Require --yes to skip raid repair prompt.
966 Change makefile %.d generation to handle filename changes without make clean.
967 Fix use of buildir in make pofile.
968 Enhance private volumes UUIDs with suffixed for easier detection.
969 Do not use reserved _[tc]meta volumes for temporary LVs.
970 Leave backup pool metadata with _meta%d suffix instead of reserved _tmeta%d.
971 Allow RAID repair to reuse PVs from same image that suffered a failure.
972 New RAID images now avoid allocation on any PVs in the same parent RAID LV.
973 Always reevaluate filters just before creating PV.
974
975Version 2.02.107 - 23rd June 2014
976=================================
977 Introduce LCK_ACTIVATION to avoid concurrent activation of basic LV types.
978 Fix open_count test for lvchange --refresh or mirrors and raids.
979 Update pvs,vgs,lvs and lvm man page for selection support.
980 Add -S/--select to lvm devtypes for report selection.
981 Add -S/--select to pvs,vgs,lvs and {pv,vg,lv}display -C for report selection.
982 Use dm_report_init_with_selection now, implicit "selected" field appears.
983 Make use of libdm's DM_REPORT_FIELD_TYPE{SIZE,PERCENT,STRING_LIST} for fields.
984 Support all-or-nothing pvmove --atomic.
985 Automatically add snapshot metadata size for -l %ORIGIN calculation.
986 When converting RAID origin to cache LV, properly rename sub-LVs.
987 Use RemoveOnStop for lvm2-lvmetad.socket systemd unit.
988 Add thin-generic configuration profile for generic thin settings.
989 Fix crash when reporting empty labels on pvs.
990 Use retry_deactivation also when cleaning orphan devices.
991 Wait for client threads when shutting down lvmetad.
992 Remove PV from cache on pvremove.
993 Avoid repeatedly reporting of failure to connect to lvmetad.
994 Introduce MDA_FAILED to permit metadata updates even if some mdas are missing.
995 Prompt when setting the VG cluster attr if the cluster is not setup.
996 Allow --yes to skip prompt in vgextend (worked only with -f).
997 Don't use name mangling for LVM - it never uses dm names with wrong char set.
998 Remove default.profile and add {command,metadata}_profile_template.profile.
999 Use proper umask for systemd units generated by lvm2-activation-generator.
1000 Check for failing mirror_remove_missing() function.
1001 Prompt before converting volumes to thin pool and thin pool metadata.
1002 Add dumpconfig --type profilable-{metadata,command} to select profile type.
1003 Exit immediately with error if command profile is found invalid.
1004 Separate --profile cmd line arg into --commandprofile and --metadataprofile.
1005 Strictly separate command profiles and per-VG/LV profiles referenced in mda.
1006 Fix dumpconfig --type diff when run as second and later cmd in lvm shell.
1007 Fix wrong profile reuse from previous run if another cmd is run in lvm shell.
1008 Move cache description from lvm(8) to new lvmcache(7) man page.
1009 Display skipped prompt in silent mode.
1010 Make reporting commands show help about possible sort keys on '-O help'.
1011 Add metadata_percent to lvs_cols.
1012 Take account of parity areas with alloc anywhere in _calc_required_extents.
1013 Use proper uint64 casting for calculation of cache metadata size.
1014 Better support for nesting of blocking signals.
1015 Use only sigaction handler and drop duplicate signal handler.
1016 Separate signal handling and flock code out into lib/misc.
1017 Don't start dmeventd checking seg_monitor and monitoring is disabled.
1018 Catch CTRL-c during pvremove prompts.
1019 Show correct availability status for snapshot origin in lvscan.
1020 Move segment thin pool/volume info into segment display 'lvdisplay --maps'.
1021 Display thin pool usage even when just thin volume is available.
1022 Display monitoring status for monitorable segments in 'lvdisplay --maps'.
1023 Display virtual extents for virtual LVs in 'lvdisplay --maps'.
1024 Make vgsplit fail cleanly when not all PVs are specified for RAID 4/5/6.
1025 Make vgsplit work on mirrors with logs that share PVs with images.
1026 Use devices/ignore_suspended_devices=0 by default if not defined in lvm.conf.
1027 Use proper libmem mempool for allocation of unknown segment name.
1028 Add --readonly to reporting and display tools for lock-free metadata access.
1029 Add locking_type 5 for dummy locking for tools that do not need any locks.
1030 Fix _recover_vg() error path when lock conversion fails.
1031 Use X for LV attributes that are unknown when activation disabled.
1032 Only output lvdisplay 'LV Status' field when activation is enabled.
1033 Use lvmetad_used() in pvscan instead of config_tree.
1034 Configure --enable-udev-systemd-background-jobs if not disabled explicitly.
1035 Add lvmdump -s to collect system info and context (currently systemd only).
1036 Refactor allocation code to make A_POSITIONAL_FILL explicit.
1037 Use thread-safe ctime_r() for clvmd debug logging.
1038 Skip adding replies to already finished reply thread.
1039 Use mutex to check number of replies in request_timed_out() in clvmd.
1040 Drop usage of extra reply_mutex for localsock in clvmd.
1041 Protect manipulation with finished flag with mutex in clvmd.
1042 Shift mutex creation and destroy for localsock in clvmd to correct place.
1043 Fix usage of --test option in clvmd.
1044 Skip more libraries to be mlocked in memory.
1045 Remove LOCKED flag for pvmove replaced with error target.
1046 Return invalid command when specifying negative polling interval.
1047
1048Version 2.02.106 - 10th April 2014
1049==================================
1050 Fix ignored --dataalignment/dataalignment offset for pvcreate --restorefile.
1051 Fix lost information about bootloader area when using lvmetad.
1052 Don't require --major to be specified when using -My option on kernels > 2.4.
1053 Add configure --disable-thin_check_needs_check to support old thin_check.
1054 Use thin_check --clear-needs-check-flag by default.
1055 Export lvm_even_rand() for controlled provision of random numbers.
1056 Add lvmthin man page to section 7.
1057 Ensure mapped device names are not too long in vg_validate and lvrename.
1058 Ensure resume failure in lvrename results in command failure.
1059 Add explicit error message when using lvdisplay -c -m.
1060 Report error if superfluous argument (e.g. PV name) supplied to pvscan.
1061 Fix error message for pvdisplay -c -m and add one for pvdisplay -c -s.
1062 Use EINVALID_CMD_LINE correctly instead of ECMD_FAILED in vgimport/export.
1063 Obtain list of known VGs from lvmetad for pvchange --all.
1064 Add man page for lvm-dumpconfig to section 8.
1065 Drop unused cmd pointer for internal function for_each_sub_lv().
1066 Validate name for renamed sub LVs.
1067 When lvrename fails on argument parsing return EINVALID_CMD_LINE.
1068 Fix exit code regression in failing pvchange command (2.02.66).
1069 Include 'lvm dumpconfig --type missing' and '--type diff' output to lvmdump.
1070 Return failure when specifying negative size for pvresize.
1071 Fix memory corruption in cmd context refresh if clvmd leaks opened device.
1072 Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
1073 Add 'lvm dumpconfig --type diff' to show differences from defaults.
1074 Fix swap signature detection for devices smaller then 2MB.
1075 Use dm_malloc function in clvmd.c.
1076 Resolve memory release order for clvmd shutdown.
1077 Report error when lvm2 activation is released in critical_section.
1078 Fix memory corruption when pvscan reports long pv names.
1079 Do not report internal orphan VG names when reporting pvdisplay/pvscan.
1080 Fix pvdisplay -c man page referencing KB instead of sectors.
1081 Skip redundant synchronization calls on local clvmd.
1082 Use correct PATH_MAX for locking dir path.
1083 Do not check for backups when when its creation is disabled.
1084 Don't allow --mergedconfig without --type current in dumpconfig. Fix memleak.
1085 Make global/lvdisplay_shows_full_device_path lvm.conf setting profilable.
1086 Make global/{units|si_unit_consistency|suffix} lvm.conf setting profilable.
1087 Validate minimal chunk size for snapshot COW volume in lvconvert.
1088 Disallow lvconvert of origin to snapshot COW volume.
1089 Make report lvm.conf settings profilable.
1090 Add existing report settings to lvm.conf.
1091 Use VG read lock during 'pvscan --cache -aay' autoactivation.
1092 Issue a VG refresh before autoactivation only if the PV has changed/is new.
1093 Add flag to lvmetad protocol to indicate the PV scanned has changed/is new.
1094 Also add vgname to lvmetad protocol when referencing VGs for PVs scanned.
1095 Add man page for lvm2-activation-generator.
1096 Don't print an error and accept empty value for global/thin_disabled_features.
1097 Update API for internal function build_dm_uuid().
1098 Do not try to check empty pool with scheduled messages.
1099 Fix return value in pool_has_message() when quering for any message.
1100 Cleanup all client resources on clvmd exit.
1101 Use dm_zalloc to clear members of clvmd client struct.
1102 Use BLKID_CFLAGS when compiling with blkid support.
1103 Use correct rl_completion_func_t typedef for new readline.
1104 Make lvm 'dumpconfig --type default' complete for it to be consumed by lvm.
1105 Run pvscan --cache via systemd-run in udev if the PV label is detected lost.
1106 Fix memleak when lvmetad discovers PV to appear on another device.
1107 Fix calculation of maximum size of COW device for snapshot (2.02.99).
1108 Do not allow stripe size to be bigger then extent size for lvresize.
1109 Zero snapshot COW header when creating read-only snapshot.
1110 Comment out config lines in dumpconfig output without default values defined.
1111 Improve detection of clustered mirror support.
1112 Enhance raid code with feature flags, for now checks for raid10.
1113 Move parsing of VG metadata from vg_commit() back to vg_write() (2.02.99)
1114 Avoid a PV label scan while in a critical section.
1115 Remove (always 0) skip argument from lv_activation_skip().
1116 Create /dev/disk/by-id/lvm-pv-uuid-<PV_UUID> symlink for each PV via udev.
1117 lvcreate computes RAID4/5/6 stripes if not given from # of allocatable PVs.
1118 Fix merging of old snapshot into thin volume origin.
1119 Use --ignoreskippedcluster in lvm2-monitor initscript/systemd unit.
1120 Do not use VG read/write state for LV read/write state.
1121 Use --ignoreskippedcluster in activation systemd units if use_lvmetad=0.
1122 Allow approximate allocation when specifying size in percentage terms.
1123 Add basic LVM support for cache[pool] segment types.
1124 Use local exclusive activation for creation of raid in cluster.
1125 Use correctly signed 64b constant when selecting raid volumes.
1126 Add systemd native service for clvmd, cmirrord and clustered LV activation.
1127 Remove ExecReload from lvmetad systemd unit: lvmetad -R undefined. (2.02.98)
1128 Do not fork lvmetad if running under systemd.
1129 Wipe DM_snapshot_cow signature without prompt in new LVs with blkid wiping.
1130 Avoid exposing temporary devices when initializing raid metadata volumes.
1131 Add internal tags command to display any tags defined on the host.
1132 Prohibit use of external origin with size incompatible with thin pool.
1133 Avoid trying to convert single to thin pool and volume at the same time.
1134 Add support for partitions on ZFS zvol.
1135 Fix unwanted drop of hold flocks on forked children.
1136 Respect LVM_LVMETAD_PIDFILE env var for lvm command.
1137 Avoid exposing temporary devices when initializing thin pool volume.
1138 Fix test when checking target version for available thin features.
1139 Detect thin feature external_origin_extend and limit extend when missing.
1140 Rename internal pool_can_resize_metadata() to thin_pool_feature_supported().
1141 Issue error if libbblkid detects signature and fails to return offset/length.
1142 Update autoconf config.guess/sub to 2014-01-01.
1143 Online thin pool metadata resize requires 1.10 kernel thin pool target.
1144
1145Version 2.02.105 - 20th January 2014
1146====================================
1147 Fix thin LV flagging for udev to skip scanning only if the LV is wiped.
1148 Replace use of xfs_check with xfs_repair in fsadm.
1149 Mark lvm1 format metadata as FMT_OBSOLETE. Do not use it with lvmetad.
1150 Invalidate cached VG struct after a PV in it gets orphaned. (2.02.87)
1151 Mark pool format metadata as FMT_OBSOLETE.
1152 Use major:minor in lvm2-pvscan@.service for proper global_filter application.
1153 Syntax and spelling fixes in some man pages.
1154 Dependency scan counts with snapshots and external origins.
1155 Make sure VG extent size is always greater or equal to PV phys. block size.
1156 Optimize double call of stat() for cached devices.
1157 Enable support for thin provisioning for default configuration.
1158 Improve process_each_lv_in_vg() tag processing.
1159 Reordered and simplified logging code.
1160 Fix SYSTEMD_READY assignment for foreign devices in lvmetad udev rules.
1161 Disable online thin pool metadata resize for 1.9 kernel thin target.
1162 Shortened code for initialization of raid segment types.
1163 Cache global library dir in command context.
1164 Return success when inserting dirs and links into device cache.
1165 Test for remote exclusive activation after activation fails.
1166 Support lvconvert --merge for thin snapshots.
1167 Add support to read thin device id from table line entry.
1168 Drop extra test for origin when testing merging origin in lv_refresh().
1169 Extend lv_remove_single() to not print info about removed LV.
1170 Replace open_count check with lv_check_not_in_use() for snapshot open test.
1171 Add error messages with LV names for failing lv refresh.
1172 Compile/link executables with new RELRO and PIE options (non-static builds).
1173 Support per-object compilation cflags via CFLAGS_object.o.
1174 Automatically detect support for compiler/linker options to use RELRO and PIE.
1175 Add --splitsnapshot to lvconvert to separate out cow LV.
1176 Reinstate origin reload to complete lvconvert -s with active LVs. (2.02.98)
1177 Select only active volume groups if vgdisplay -A is used.
1178 Add -p and LVM_LVMETAD_PIDFILE env var to lvmetad to change pid file.
1179 Allow lvmetad to reuse stale socket.
1180 Only unlink lvmetad socket on error if created by the same process.
1181 Append missing newline to lvmetad missing socket path error message.
1182 Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0.
1183 Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping.
1184 Enable blkid_wiping by default if the blkid library is present.
1185 Add configure --disable-blkid_wiping to disable libblkid signature detection.
1186 Add -W/--wipesignatures lvcreate option to support wiping on new LVs.
1187 Add allocation/wipe_signatures_when_zeroing_new_lvs to lvm.conf.
1188 Do not fail the whole autoactivation if the VG refresh done before fails.
1189 Do not connect to lvmetad on vg/lvchange --sysinit -aay and socket absent.
1190 Use lv_check_not_in_use() when testing device in use before merging.
1191 Move test for target present from init_snapshot_merge() to lvconvert.
1192 Check for failure of lvmcache_add_mda() when writing pv.
1193 Check for failure of dev_get_size() when reporting device size.
1194 Drop extra unneeded '/' when scanning sysfs directory.
1195 Fix undef value if skipped clustered VG ignored for toollib PV seg. (2.02.103)
1196 Support validation of VG/LV names in liblvm/python.
1197 Allow creation of PVs with arguments to liblvm/python.
1198 Ensure sufficient metadata copies retained in liblvm/python vgreduce.
1199 Fix installation of profiles from conf subdir when not building in srcdir.
1200 Show UUIDs for missing PVs in reports.
1201 Change dev_size/name, pv_fmt/mda_free/mda_size/uuid fields from pv to label.
1202 Add struct device *dev to struct label.
1203 Introduce process_each_label.
1204 Change void *private to struct format_type *fmt in struct labeller.
1205 Remove pv_read.
1206 Add reporting of thin_id device id for thin volumes.
1207 Fix reporting of empty numerical values for recently-added fields.
1208 Use _field_set_percent/value in reporting code.
1209
1210Version 2.02.104 - 13th November 2013
1211=====================================
1212 Workaround VG refresh race during autoactivation by retrying the refresh.
1213 Handle failures in temporary mirror used when adding images to mirrors.
1214 Fix and improve logic for implicitely exclusive activations.
1215 Return success when LV cannot be activated because of volume_list filter.
1216 Return proper error state for remote exclusive activation.
1217 Fix missing lvmetad scan for PVs found on MD partitions.
1218 Respect DM_UDEV_DISABLE_OTHER_RULES_FLAG in lvmetad udev rules.
1219 Fix clvmd message verification to not reject REMOTE flag. (2.02.100)
1220 Compare equality of double values with DBL_EPSILON predefined constant.
1221 Use additional gcc warning flags by default.
1222 Add ignore_lvm_mirrors to config file to read/ignore labels on mirrors.
1223 Add internal flag for temporary LVs to properly direct udev to not interfere.
1224 Fix endless loop in blkdeactivate <device>... if unable to umount/deactivate.
1225 Add dev-block-<major>:<minor>.device systemd alias for complete PV tracking.
1226 Use major:minor as short form of --major and --minor arg for pvscan --cache.
1227 Remove 2>/dev/null from three lvm commands executed by vgimportclone.
1228 Add configure --enable-udev-systemd-background-jobs.
1229 Add lvm2-pvscan@.service to run pvscan as a service for lvmetad/autoactivation.
1230 Use #ifdef __linux__ instead of linux throughout.
1231 Fix lvconvert swap of poolmetadata volume for active thin pool.
1232 Check for open count with a timeout before removal/deactivation of an LV.
1233 Report RAID images split with tracking as out-of-sync ("I").
1234 Improve parsing of snapshot lv segment.
1235 Add workaround for deactivation problem of opened virtual snapshot.
1236 Disable unsupported merge for virtual snapshot.
1237 Move code to remove virtual snapshot from tools to lib for lvm2app.
1238 Fix possible race during daemon worker thread creation (lvmetad).
1239 Fix possible deadlock while clearing lvmetad cache for full rescan.
1240 Recognise NVM Express devices in filter.
1241 Fix failing metadata repair when lvmetad is used.
1242 Fix incorrect memory handling when reading messages from lvmetad.
1243 Fix locking in lvmetad when handling the PV which is gone.
1244 Recognize new flag to skip udev scanning in udev rules and act appropriately.
1245 Add support for flagging an LV to skip udev scanning during activation.
1246 Improve message when unable to change discards setting on active thin pool.
1247 Run full scan before vgrename operation to avoid any cache name collision.
1248 Fix lvconvert when converting to a thin pool and thin LV at once. (2.02.99)
1249
1250Version 2.02.103 - 4th October 2013
1251===================================
1252 Ensure vgid matches before removing vgname entry from lvmetad cache.
1253 Add --ignoreskippedcluster for exit status success when clustered VGs skipped.
1254 Fix 3 minute udev timeout so that it is applied for all LVM volumes.
1255 Fix thin/raid & activation config defaults with configure --disable-devmapper.
1256 Fix RAID calculation for sufficient allocatable space.
1257 lvconvert from linear to mirror or RAID1 now honors mirror_segtype_default.
1258 Add thin-performance configuration profile.
1259 Add lvm.conf allocation/thin_pool_chunk_size_policy option.
1260 Fix contiguous & cling allocation policies for parity RAID. (2.02.100)
1261 Have lvmconf --enable/disable-cluster reset/set use_lvmetad.
1262 Don't install separate command symlink for 'lvm devtypes'. (2.02.101)
1263 Add seg_size_pe field to reports.
1264 Support start+length notation with command line PE ranges.
1265 Exit cleanly with message when pvmove cannot restart because LV is inactive.
1266
1267Version 2.02.102 - 23rd September 2013
1268======================================
1269 Fix missing build dependency for scripts subdir in Makefile.
1270 Extend lv_info() for more efficient lv_is_active_locally() check.
1271 Fix node up/down handling in clvmd corosync module.
1272
1273Version 2.02.101 - 20th September 2013
1274======================================
1275 Fix 3-thread clvmd deadlock triggered by cleanup on EOF from client.
1276 Remove VG from lvmetad before restoring it with vgcfgrestore.
1277 Use strtoull instead of strtol in _get_int_arg.
1278 Add devtypes report command to display built-in recognised block device types.
1279 Fix CC Makefile override which had reverted to using built-in value. (2.02.75)
1280 Recognise bcache block devices in filter (experimental).
1281 Run lvm2-activation-net after lvm2-activation service to prevent parallel run.
1282 Add man page entries for lvmdump's -u and -l options.
1283 Fix lvm2app segfault while using lvm_list_pvs_free fn if there are no PVs.
1284 Improve of clvmd singlenode locking simulation.
1285 lvconvert no longer converts LVs of "mirror" segment type to thinpool.
1286 lvconvert no longer converts thinpool sub-LVs to "mirror" segment type.
1287 Direct udev to use 3min timeout for LVM devices. Recent udev has default 30s.
1288 Do not scan multipath or RAID components and avoid incorrect autoactivation.
1289 Fix MD/loop udev handling to fire autoactivation after setup or coldplug only.
1290 Make RAID capable of single-machine exclusive operations in a cluster.
1291 Drop calculation of read ahead for deactivated volume.
1292 Check for exactly one lv segment in validation of thin pools and volumes.
1293 Fix dmeventd unmonitoring of thin pools.
1294 Fix lvresize for stacked thin pool volumes (i.e. mirrors).
1295 Write Completed debug message before reinstating log defaults after command.
1296 Refresh existing VG before autoactivation (event retrigger/device reappeared).
1297 Use pvscan -b in udev rules to avoid a deadlock on udev process count limit.
1298 Add pvscan -b/--background for the command to be processed in the background.
1299 Don't assume stdin file descriptor is readable.
1300 Avoid unlimited recursion when creating dtree containing inactive pvmove LV.
1301 Require exactly 3 arguments for lvm2-activation-generator. Remove defaults.
1302 Inform lvmetad about any lost PV label to make it in sync with system state.
1303 Support most of lvchange operations on stacked thin pool meta/data LVs.
1304 Enable non-clustered pvmove of snapshots and snapshot origins.
1305 Add ability to pvmove non-clustered RAID, mirror, and thin volumes.
1306 Make lvm2-activation-generator silent unless it's in error state.
1307 Remove "mpath major is not dm major" msg for mpath component scan (2.02.94).
1308 Prevent cluster mirror logs from being corrupted by redundant checkpoints.
1309 Fix ignored lvmetad update on loop device configuration (2.02.99).
1310 Use LVM_PATH instead of hardcoded value in lvm2 activation systemd generator.
1311 Fix vgck to notice on-disk corruption even if lvmetad is used.
1312 Move mpath device filter before partitioned filter (which opens devices).
1313 Split partitioned filter out of lvm_type filter.
1314 Merge filter*.h into a single filter.h.
1315 Require confirmation for vgchange -c when no VGs listed explicitly.
1316 Also skip /var and /var/log by default in blkdeactivate when unmounting.
1317 Add support for bind mounts in blkdeactivate.
1318 Add blkdeactivate -v/--verbose for debug output from external tools used.
1319 Add blkdeactivate -e/--errors for error messages from external tools used.
1320 Suppress messages from external tools called in blkdeactivate by default.
1321
1322Version 2.02.100 - 13th August 2013
1323===================================
1324 Fix inability to remove a VG's cluster flag if it contains a mirror.
1325 Suppress arg: prefix in log_sys_error macro when arg is empty string.
1326 Fix bug making lvchange unable to change recovery rate for RAID.
1327 Prohibit conversion of thin pool to external origin.
1328 Workaround gcc v4.8 -O2 bug causing failures if config/checks=1 (32bit arch).
1329 Verify clvmd message validity before processing and log error if incorrect.
1330 When creating PV on existing LV don't forbid reserved LV names on LVs below.
1331 Split out device_is_suspended_or_blocking from device_is_usable.
1332 When converting mirrors, default segtype should be the same unless specified.
1333 Make "raid1" the default mirror segment type.
1334 Fix clogd descriptor leak when daemonizing.
1335 Fix clvmd descriptor leak on restart.
1336 Add pipe_open/close() to use instead of less efficient/secure popen().
1337 Fix metadata area offset/size overflow if it's >= 4g and while using lvmetad.
1338 Inherit and apply any profile attached to a VG if creating new thin pool.
1339 Add initial support thin pool lvconvert --repair.
1340 Add --with-thin-repair and --with-thin-dump configure options.
1341 Add lvm.conf thin_repair/dump_executable and thin_repair_options.
1342 Require 1.9 thin pool target version for online thin pool metadata resize.
1343 Ignore previous LV seg with alloc contiguous & cling when num stripes varies.
1344 Fix segfault if devices/global_filter is not specified correctly.
1345
1346Version 2.02.99 - 24th July 2013
1347================================
1348 Do not zero init 4KB of thin snapshot for non-zeroing thin pool (2.02.94).
1349 Issue an error msg if lvconvert --type used incorrectly with other options.
1350 Use LOG_DEBUG/ERR msg severity instead default for lvm2-activation-generator.
1351 Support ARG_GROUPABLE with merge_synonym (for --raidwritemostly).
1352 Fix segfault when reporting raid_syncaction for older kernels.
1353 Add LV report fields: raid_mismatch_count/raid_sync_action/raid_write_behind.
1354 Add LV reporting fields raid_min_recovery_rate, raid_max_recovery_rate.
1355 Add sync_percent as alias for copy_percent LV reporting field.
1356 Add lv_ prefix to modules reporting field.
1357 Use units B or b (never E) with no decimal places when displaying sizes < 1k.
1358 Add support for poolmetadataspare LV, that will be used for pool recovery.
1359 Improve activation order when creating thin pools in non-clustered VG.
1360 List thin-pool and thin modules for thin volumes.
1361 Correct thin creation error paths.
1362 Use local activation for clearing snapshot COW device.
1363 Add lvm2-activation-net systemd unit to activate LVs on net-attached storage.
1364 Release memory allocated with _cached_info().
1365 Add whole log_lv and metadata_lv sub volumes when creating partial tree.
1366 Properly use snapshot layer for origin which is also thin volume.
1367 Avoid generating metadata backup when calling update_pool_lv().
1368 Send thin messages also for active thin pool and inactive thin volume.
1369 Add activation/auto_set_activation_skip to control activation skip flagging.
1370 Add 's(k)ip activation' bit to lvs -o lv_attr to indicate skip flag attached.
1371 Add --ignoreactivationskip to lvcreate/vgchange/lvchange to ignore skip flag.
1372 Add --setactivationskip to lvcreate/lvchange to set activation skip flag.
1373 Automatically flag thin snapshots to be skipped during activation.
1374 Add support for persistent flagging of LVs to be skipped during activation.
1375 Add --type profilable to lvm dumpconfig to show profilable config settings.
1376 Add --mergedconfig to lvm dumpconfig for merged --config/--profile/lvm.conf.
1377 Relase memory and unblock signals in lock_vol error path.
1378 Define LVM2_* command errors in lvm2cmd.h and use in dmeventd plugins.
1379 Move errors.h to tools dir.
1380 Add man page entries for profile configuration and related options.
1381 Improve error loging when user tries to interrupt commands.
1382 Rename _swap_lv to _swap_lv_identifiers and move to allow an additional user.
1383 Rename snapshot segment returning methods from find_*_cow to find_*_snapshot.
1384 liblvm/python API: Additions: PV create/removal/resize/listing
1385 liblvm/python API: Additions: LV attr/origin/Thin pool/Thin LV creation
1386 Add vgs/lvs -o vg_profile/lv_profile to report profiles attached to VG/LV.
1387 Add default.profile configuration profile and install it on make install.
1388 Create a new 'conf' subdir for configuration files including profiles.
1389 Make selected thinp settings customizable by a profile.
1390 Support changing VG/LV profiles: vgchange/lvchange --profile/--detachprofile.
1391 Support storing profile name in metadata for both VGs and LVs.
1392 Add new --profile command line arg to select a configuration profile for use.
1393 Add config/profile_dir to set working directory to load profiles from.
1394 Add configure --with-default-profile-subdir to select dir to keep profiles in.
1395 Add support for configuration profiles.
1396 Introduce config_source wrapper for identification of configuration sources.
1397 Avoid creation of multiple archives for one command.
1398 Use mirror_segtype_default if type not specified for linear->mirror upconvert.
1399 Fix use of too big chunks of memory when communication with lvmetad.
1400 Fix vgcfgrestore crash when specified incorrect vg name.
1401 Refine lvm.conf and man page documentation for autoactivation feature.
1402 Add support for thin volumes in vgsplit.
1403 Also filter partitions on mpath components if multipath_component_detection=1.
1404 Add lvresize support for online thin pool metadata volume resize.
1405 Add helper functions find_pool_lv() and pool_can_resize_metadata().
1406 Add detection for thin pool metadata resize kernel support.
1407 Report lvs volume type 'e' with higher priority.
1408 Report lvs volume type 'o' also for external origin volumes.
1409 Report lvs target type 't' only for thin pools and thin volumes.
1410 Fix test for active snapshot in cluster before resizing it.
1411 Allow local activation to receive a locally-supplied LV struct.
1412 Add vg->vg_ondisk / lv_ondisk() holding committed metadata.
1413 Report backtrace from dump filter error path.
1414 Do not use persistent filter with lvmetad.
1415 Composable persistent filter functionality for global filter.
1416 Override system's global_filter settings for vgimportclone.
1417 Detect maximum usable size for snapshot for lvresize.
1418 Creation of snapshot takes at most 100% origin coverage.
1419 Add cow_max_extents() to calc extents for 100% origin coverage.
1420 For creation of snapshot require size for at least 3 chunks.
1421 Fix lvresize --use-policies of VALID but 100% full snapshot.
1422 Do not accept size parameters bigger then 16EiB.
1423 Fix release of PV's fid in free_pv_fid().
1424 Skip monitoring of snapshots that are already bigger then origin.
1425 Add lv_is_cow_covering_origin() to check if cow covers origin size.
1426 Use libdm dm_get_status_snapshot() to parse snapshot status.
1427 Add detection of mounted fs also for vgchange deactivation.
1428 Replace 'lv_is_active' with more correct/specific variants (e.g. *_locally).
1429 Refuse to init a snapshot merge in lvconvert if there's no kernel support.
1430 Fix exported symbols regex for non-GNU busybox sed.
1431 Accept --yes in all commands so test scripts can be simpler.
1432 Fix alignment of PV data area if detected alignment less than 1 MB (2.02.74).
1433 Fix memory resource leak in memlocking error path.
1434 Fix premature DM version checking which caused useless mapper/control access.
1435 Add "active" LV reporting field to show activation state.
1436 Add "monitor" segment reporting field to show dmevent monitoring status.
1437 Document lvextend --use-policies option in man.
1438 Fix creation and removal of clustered snapshot.
1439 Fix clvmd caching of metadata when suspending inactive volumes.
1440 Find newest timestamp of merged config files.
1441 Fix assignment order for vg fid for lvm1 and pool format.
1442 Fix memleak in dmeventd thin plugin in device list obtaining err path.
1443 Add explicit message about unsupported pvmove for thin/thinpool volumes.
1444 Fix lvmetad error path in lvmetad_vg_lookup() for null vgname.
1445 Fix clvmd _cluster_request() return code in memory fail path.
1446 Add lvcreate/lvchange --[raid]{min|max}recoveryrate for raid LVs.
1447 Add lvchange --[raid]writemostly/writebehind support for RAID1
1448 Add lv_change_activate() for common activation code in vg/lvchange.
1449 Add lvchange --[raid]syncaction for scrubbing of RAID LVs.
1450 Improve RAID kernel status retrieval to include sync_action/mismatch_cnt.
1451 Add external origin support for lvcreate.
1452 Improve lvcreate, lvconvert and lvm man pages.
1453 Clean up format1 PV write to remove a need for an orphan VG for it to pass.
1454 Fix vgextend to not allow a PV with 0 MDAs to be used while already in a VG.
1455 Move update_pool_params() from /tools to /lib for better reuse.
1456 Give precedence to EMC power2 devices with duplicate PVIDs.
1457 Add --validate option to lvm dumpconfig to validate current config on demand.
1458 Add --ignoreadvanced and --ignoreunsupported switch to lvm dumpconfig.
1459 Add --withcomments and --withversions switch to lvm dumpconfig.
1460 Add --type {current|default|missing|new} and --atversion to lvm dumpconfig.
1461 Support automatic config validation and add 'config' section to lvm.conf.
1462 Add pvs -o pv_ba_start,pv_ba_size to report bootloader area start and size.
1463 Add --bootloaderareasize to pvcreate and vgconvert to create bootloader area.
1464 Add PV header extension: extension version, flags and bootloader areas.
1465 Initial support for lvconvert of thin external origin.
1466 Add _lv_remove_segs_using_this_lv() for removal of dependent lvs.
1467 Improve activation code for better support of stacked devices.
1468 Add _add_layer_target_to_dtree() for adding linear layer into dtree.
1469 Extend _cached_info() to accept layer string.
1470 vgimport '--force' now allows import of VGs with missing PVs.
1471 Fix PV alignment to incorporate alignment offset if the PV has zero MDAs.
1472 Add global/raid10_segtype_default to lvm.conf.
1473 Allow removal or replacement of RAID LV components that are error segments.
1474 Make 'vgreduce --removemissing' able to handle RAID LVs with missing PVs.
1475 Accept activation/raid_region_size in preference to mirror_region_size config.
1476 Fix pvs -o pv_free reporting for PVs with zero PE count.
1477 Fix missing cleanup of flags when the LV is detached from pool.
1478 Fix check for some forbidden discards conversion of thin pools.
1479 Add pool_is_active() to check for any pool related active LV.
1480 Report blank origin_size field if the LV doesn't have an origin instead of 0.
1481 Do not take a free lv name argument for lvconvert --thinpool option.
1482 Avoid flushing thin pool when just requesting transaction_id.
1483 Add internal function lv_layer() to obtain layer name for LV.
1484 Report partial and in-sync RAID attribute based on kernel status
1485 Fix blkdeactivate to handle nested mountpoints and mangled mount paths.
1486 Use LC_ALL to set locale in daemons and fsadm instead of lower priority LANG.
1487 Avoid crash-inducing race in lvmetad when VG disappears during rename.
1488 Add log/debug_classes to lvm.conf to control debug log messages.
1489 Synchronize with udev in pvscan --cache and fix dangling udev_sync cookies.
1490 Fix autoactivation to not autoactivate VG/LV on each change of the PVs used.
1491 Limit RAID device replacement to repair only if LV is not in-sync.
1492 Disallow RAID device replacement or repair on inactive LVs.
1493 Fix possible race while removing metadata from lvmetad.
1494 Fix possible deadlock when querying and updating lvmetad at the same time.
1495 Check lvmcache_info_from_pvid and recall only when needed in _pv_read.
1496 Check for memory failure of dm_config_write_node() in lvmetad.
1497 Fix socket leak on error path in lvmetad's handle_connect.
1498 Check for failing id_read_format() in _pv_populate_lvmcache.
1499 Fix memleak on error path for lvmetad's pv_found.
1500 Unlock vg mutex in error path when lvmetad tries to lock_vg.
1501 Detect key string duplication failure in config_make_nodes_v in libdaemon.
1502 Detect fid creation failure in _scan_file in format_text.
1503 Log output also to syslog when abort_on_internal_error is set.
1504 Add LV snapshot support to liblvm and python-lvm.
1505 Avoid a global lock in pvs when lvmetad is in use.
1506 Fix crash in pvscan --cache -aay triggered by non-mda PV.
1507 Allow lvconvert --stripes/stripesize only with --mirrors/--repair/--thinpool.
1508 Fix memleak in device_is_usable mirror testing function.
1509 Do not ignore -f in lvconvert --repair -y -f for mirror and raid volumes.
1510 Disallow pvmove on RAID LVs until they are addressed properly
1511 Allow empty activation/{auto_activation|read_only|}_volume_list config option.
1512 Add lvm.conf option global/thin_disabled_features.
1513 Add lvconvert support to swap thin pool metadata volume.
1514 Implement internal function detach_pool_metadata_lv().
1515 Fix lvm2app to return all property sizes in bytes (not sectors).
1516 Recognize DM_DISABLE_UDEV environment variable for a complete fallback.
1517 Do not verify udev operations if --noudevsync command option is used.
1518 Fix lvm2app and return lvseg discards property as string.
1519 Allow vgcfgrestore of lvm2 metadata with thin volumes if --force is used.
1520 Recognise Storage Class Memory (IBM S/390) devices in filter.
1521 Recognise STEC skd devices in filter.
1522 Recognise Violin Memory vtms devices in filter.
1523 Add lvm.conf thin pool allocation settings thin_pool_{chunk_size|discards|zero}.
1524 Support discards for non-power-of-2 thin pool chunks.
1525 Automatically restore MISSING PVs with no MDAs.
1526 When no --stripes argument is given when creating a RAID10 volume, default to 2 stripes.
1527 Do not allow lvconvert --splitmirrors on RAID10 logical volumes.
1528 Skip mlocking [vectors] on arm architecture.
1529 Support allocation of pool metadata with lvconvert command.
1530 Move common functionality for thin lvcreate and lvconvert to toollib.
1531 Repair a mirrored log before the mirror itself when both fail.
1532 Add python-lvm unit test case
1533 Exit pvscan --cache immediately if cluster locking used or lvmetad not used.
1534 Don't use lvmetad in lvm2-monitor.service ExecStop to avoid a systemd issue.
1535 Remove dependency on fedora-storage-init.service in lvm2 systemd units.
1536 Depend on lvm2-lvmetad.socket in lvm2-monitor.service systemd unit.
1537 Hardcode use_lvmetad=0 if cluster locking used and issue a warning msg.
1538 Avoid trying to read a mirror that has a failed device in its mirrored log.
1539 Relax ignore_suspended_devices to read from mirrors that don't have a device marked failed.
1540 Change lvs heading Copy% to Cpy%Sync and print RAID4/5/6 sync% there too.
1541 Fix clvmd support for option -d and properly use its argument.
1542 Support use of option --yes for lvchange --persistent.
1543 Fix memory leak on error path for pvcreate with invalid uuid.
1544 Implement ref-counting for parents in python lib.
1545 Add lv_is_active_locally and use instead of most local lv_info calls.
1546 Reduce some log_error messages to log_warn where we don't fail.
1547 Remove python liblvm object. systemdir can only be changed using env var now.
1548
1549Version 2.02.98 - 15th October 2012
1550===================================
1551 Switch from DEBUG() to DEBUGLOG() in lvmetad as -DDEBUG is already used.
1552 Prohibit not yet supported change of thin-pool to read-only.
1553 Support creation of read-only thin volumes (lvcreate -p r).
1554 Using autoextend percent 0 for thin pool fails 'lvextend --use-policies'.
1555 Introduce blkdeactivate script to deactivate block devs with dependencies.
1556 Implement devices/global_filter to hide devices from lvmetad.
1557 Make vgscan --cache an alias for pvscan --cache.
1558 Clear lvmetad metadata/PV cache before a rescan.
1559 Fix a segmentation fault upon receiving a corrupt lvmetad response.
1560 Give inconsistent metadata warnings in pvscan --cache.
1561 Make lvremove ask before discarding data areas.
1562 Avoid overlapping locks that could cause a deadlock in lvmetad.
1563 Fix memory leaks in libdaemon and lvmetad.
1564 Optimize libdaemon logging for a fast no-output path.
1565 Only create lvmetad pidfile when running as a daemon (no -f).
1566 Warn if lvmetad is running but disabled.
1567 Warn about running lvmetad with use_lvmetad = 0 in example.conf.
1568 Update lvmetad help output (flags and their meaning).
1569 Make pvscan --cache read metadata from LVM1 PVs.
1570 Make libdaemon buffer handling asymptotically more efficient.
1571 Add lvmdump -l, to collect a state dump from lvmetad.
1572 Make --sysinit suppress lvmetad connection failure warnings.
1573 Prohibit usage of lvcreate --thinpool with --mirrors.
1574 Fix lvm2api origin reporting for thin snapshot volume.
1575 Add configure --enable-python_bindings for liblvm2app to new python subdir.
1576 Add implementation of lvm2api function lvm_percent_to_float.
1577 Allow non power of 2 thin chunk sizes if thin pool driver supports that.
1578 Allow limited metadata changes when PVs are missing via [vg|lv]change.
1579 Do not start dmeventd for lvchange --resync when monitoring is off.
1580 Remove pvscan --cache from lvm2-lvmetad init script.
1581 Remove ExecStartPost with pvscan --cache from lvm2-lvmetad.service.
1582 Report invalid percentage for property snap_percent of non-snaphot LVs.
1583 Disallow conversion of thin LVs to mirrors.
1584 Fix lvm2api data_percent reporting for thin volumes.
1585 Do not allow RAID LVs in a clustered volume group.
1586 Add --discards to lvconvert.
1587 Add --poolmetadata to lvconvert and support thin meta/data dev stacking.
1588 Support changes of permissions for thin snapshot volumes.
1589 Enhance insert_layer_for_lv() with recursive rename for _tdata LVs.
1590 Skip building dm tree for thin pool when called with origin_only flag.
1591 Add internal lv_rename_update() to rename LV without updating mda.
1592 Ensure descriptors 0,1,2 are always available, using /dev/null if necessary.
1593 Use /proc/self/fd when available for closing opened descriptors efficiently.
1594 Add missing pkg init with --enable-testing in configure.in (2.02.71).
1595 Fix inability to create, extend or convert to a large (> 1TiB) RAID LV.
1596 Split out daemon-io from daemon-shared and always build libdaemonclient.
1597 Update lvmetad communications to cope with clients using different filters.
1598 Add (p)artial attribute to lvs.
1599 Don't try to issue discards to a missing PV to avoid segfault.
1600 Clear LV_NOSYNCED flag when a RAID1 LV is converted to a linear LV.
1601 Disallow RAID1 upconvert if the LV was created with --nosync.
1602 Depend on systemd-udev-settle in units generated by activation generator.
1603 Fix vgchange -aay not to activate non-matching LVs that follow a matching LV.
1604 Fix lvchange --resync for RAID LVs which had no effect.
1605 Restructure mirror resync code.
1606 Disallow addition of RAID images until the array is in-sync.
1607 Fix RAID LV creation with '--test' so valid commands do not fail.
1608 Add lvm_lv_rename() to lvm2api.
1609 Fix setvbuf code by closing and reopening stream before changing buffer.
1610 Disable private buffering when using liblvm.
1611 When private stdin/stdout buffering is not used always use silent mode.
1612 Add log/silent to lvm.conf equivalent to -qq.
1613 Suppress non-essential stdout with -qq.
1614 Switch non-essential log_print messages to log_print_unless_silent.
1615 Use -q as short form of --quiet.
1616 Add RAID10 support (--type raid10).
1617 Reuse _reload_lv() in more lvconvert functions.
1618 Fix 32-bit device size arithmetic needing 64-bit casting throughout tree.
1619 Remove numerous unnecessary #includes and the empty util.c.
1620 Fix dereference of NULL in lvmetad error path logging.
1621 Fix buffer memory leak in lvmetad logging.
1622 Add support for lvcreate --discards.
1623 Correct the discards field in the lvs manpage (2.02.97).
1624 Use proper condition to check for discards settings unsupported by kernel.
1625 Reinstate correct default to ignore discards for thin metadata from old tools.
1626 Issue error message when -i and -m args do not match specified RAID type.
1627 Change lvmetad logging syntax from -ddd to -l {all|wire|debug}.
1628 Add new libdaemon logging infrastructure.
1629
1630Version 2.02.97 - 7th August 2012
1631=================================
1632 Improve documention of allocation policies in lvm.8.
1633 Increase limit for major:minor to 4095:1048575 when using -My option.
1634 Add make install_systemd_generators.
1635 Add generator for lvm2 activation systemd units.
1636 Add lvm_config_find_bool lvm2app fn to retrieve bool value from config tree.
1637 Respect --test when using lvmetad.
1638 No longer capitalise first LV attribute char for invalid snapshots.
1639 Allow vgextend to add PVs to a VG that is missing PVs.
1640 Recognise Micron PCIe SSDs in filter and move array out to device-types.h.
1641 Fix dumpconfig <node> to print only <node> without its siblings. (2.02.89)
1642 Do not issue "Failed to handle a client connection" error if lvmetad killed.
1643 Support lvchange --discards and -Z with thin pools.
1644 Add discard LV segment field to reports.
1645 Add --discards to lvcreate --thin.
1646 Set discard and external snapshot features if thin pool target is vsn 1.1+.
1647 Count percentage of completeness upwards not downwards when merging snapshot.
1648 Skip activation when using vg/lvchange --sysinit -a ay and lvmetad is active.
1649 Fix extending RAID 4/5/6 logical volumes
1650 Fix test for PV with unknown VG in process_each_pv to ignore ignored mdas.
1651 Update man pages with --activate ay option and auto_activation_volume_list.
1652 Fix _alloc_parallel_area to avoid picking already-full areas for raid devices.
1653 Use vgchange -aay instead of vgchange -ay in clmvd init script.
1654 Add activation/auto_activation_volume_list to lvm.conf.
1655 Add --activate ay to lvcreate, lvchange, pvscan and vgchange.
1656 Add support for volume autoactivation using lvmetad.
1657 Add --activate synonym for --available arg and prefer --activate.
1658 Never issue discards when LV extents are being reconfigured, not deleted.
1659 Allow release_lv_segment_area to fail as functions it calls can fail.
1660 Open device read-only instead of read-write when obtaining readahead value.
1661 Fix lvconvert thin pool error path NULL pointer dereference.
1662 Detect create_instance() failure in pvscan_lvmetad_single().
1663 Use 64-bit calculations for reserved memory and stack.
1664 Fix missing sync of filesystem when creating thin volume snapshot.
1665
1666Version 2.02.96 - 8th June 2012
1667===============================
1668 Upstream source repo now fedorahosted.org git not sources.redhat.com CVS.
1669 Fix error paths for regex filter initialization.
1670 Re-enable partial activation of non-thin LVs until it can be fixed. (2.02.90)
1671 Fix alloc cling to cling to PVs already found with contiguous policy.
1672 Fix cling policy not to behave like normal policy if no previous LV seg.
1673 Fix allocation loop not to use later policies when --alloc cling without tags.
1674 Append _TO_LVSEG to names of internal A_CONTIGUOUS and A_CLING flags.
1675 Add missing pkg init --with-systemdsystemunitdir in configure.in (2.02.92).
1676 Fix division by zero if PV with zero PE count is used during vgcfgrestore.
1677 Add initial support for thin pool lvconvert.
1678 Fix lvrename for thin volumes (regression in for_each_sub_lv). (2.02.89)
1679 Fix up-convert when mirror activation is controlled by volume_list and tags.
1680 Warn of deadlock risk when using snapshots of mirror segment type.
1681 Fix bug in cmirror that caused incorrect status info to print on some nodes.
1682 Remove statement that snapshots cannot be tagged from lvm man page.
1683 Disallow changing cluster attribute of VG while RAID LVs are active.
1684 Fix lvconvert error message for non-mergeable volumes.
1685 Allow subset of failed devices to be replaced in RAID LVs.
1686 Prevent resume from creating error devices that already exist from suspend.
1687 Improve clmvd singlenode locking for better testing.
1688 Update and correct lvs man page with supported column names.
1689 Handle replacement of an active device that goes missing with an error device.
1690 Change change raid1 segtype always to request a flush when suspending.
1691 Add udev info and context to lvmdump.
1692 Add lvmetad man page.
1693 Fix RAID device replacement code so that it works under snapshot.
1694 Fix inability to split RAID1 image while specifying a particular PV.
1695 Update man pages to give them all the same look&feel.
1696 Fix lvresize of thin pool for striped devices.
1697 For lvresize round upward when specifying number of extents.
1698 For lvcreate with %FREE support rounding downward stripe alignment.
1699 Change message severity to log_very_verbose for missing dev info in udev db.
1700 Fix lvconvert when specifying removal of a RAID device other than last one.
1701 Fix ability to handle failures in mirrored log in dmeventd plugin. (2.02.89)
1702 Fix unlocking volume group in vgreduce in error path.
1703 Cope when VG name is part of the supplied name in lvconvert --splitmirrors -n.
1704 Fix exclusive lvchange running from other node. (2.02.89)
1705 Add 'vgscan --cache' functionality for consistency with 'pvscan --cache'.
1706 Keep exclusive activation in pvmove if LV is already active.
1707 Disallow exclusive pvmove if some affected LVs are not exclusively activated.
1708 Remove unused and wrongly set cluster VG flag from clvmd lock query command.
1709 Fix pvmove for exclusively activated LV pvmove in clustered VG. (2.02.86)
1710 Always free hash table on update_pvid_to_vgid() in lvmetad.
1711 Update and fix monitoring of thin pool devices.
1712 Check hash insert success in lock_vg in clvmd.
1713 Check for buffer overwrite in get_cluster_type() in clvmd.
1714 Fix global/detect_internal_vg_cache_corruption config check.
1715 Update lcov Makefile target to support all dmeventd plugins.
1716 Fix initializiation of thin monitoring. (2.02.92)
1717 Cope with improperly formatted device numbers in /proc/devices. (2.02.91)
1718 Exit if LISTEN_PID environment variable incorrect in lvmetad systemd handover.
1719 Use pvscan --cache instead of vgscan in lvmetad scripts.
1720 Fix fsadm propagation of -e option.
1721 Fix fsadm parsing of /proc/mounts files (don't check for substrings).
1722 Fix fsadm usage of arguments with space.
1723 Fix arg_int_value alongside ARG_GROUPABLE --major/--minor for lvcreate/change.
1724 Fix name conflicts that prevent down-converting RAID1 when specifying a device
1725 Improve thin_check option passing and use configured path.
1726 Add --with-thin-check configure option for path to thin_check.
1727 Fix error message when pvmove LV activation fails with name already in use.
1728 Better structure layout for device_info in dev_subsystem_name().
1729 Change message severity for creation of VG over uninitialised devices.
1730 Fix error path for failed toolcontext creation.
1731 Detect lvm binary path in lvmetad udev rules.
1732 Don't unlink socket on lvmetad shutdown if instantiated from systemd.
1733 Restart lvmetad automatically from systemd if it exits from uncaught signal.
1734 Fix warn msg for thin pool chunk size and update man for chunksize. (2.02.89)
1735
1736Version 2.02.95 - 6th March 2012
1737================================
1738 If unspecified, adjust thin pool metadata and chunk size to fit into 128MB.
1739 Print just warning on thin pool check callback path for failing check.
1740 Always use 64bit arithmetic with VG extent_size expression.
1741 Validate udev structures in _insert_udev_dir().
1742 Take repeatable --major --minor with pvscan --cache instead of major:minor.
1743 Scan all devices for lvmetad if 'pvscan --cache' used without device list.
1744 Populate lvmcache from lvmetad before displaying PVs in pvscan. (2.02.94)
1745 Suppress incorrect -n pvscan warning now always displayed. (2.02.94)
1746
1747Version 2.02.94 - 3rd March 2012
1748================================
1749 Add support to execute thin_check with each de/active of thin pool.
1750 Fix automatic estimation of metadata device size for thin pool.
1751 Test for alloc fail from _alloc_pv_segment() in _extend_pv().
1752 Check for alloc fail from get_segtype_from_string() in _lvcreate_params().
1753 Add _rimage as reserved suffix to lvm.8 man page.
1754 Improve error logging from mpath filter.
1755 Check for allocation failure in hold_lock() in clvmd.
1756 Use set_lv() (wipe initial 4KiB) for non zeroed thin volume.
1757 Allow cluster mirrors to handle the absence of the checkpoint lib (libSaCkpt).
1758 Revert free of allocated segtype in init segment error path (2.02.89).
1759 Test dm_hash_insert() failures in filter-persistent.c and fid_add_mda().
1760 Ensure clvmd message is always NUL-terminated after read.
1761 Add some close() and dev_close() error path backtraces.
1762 Set stdin/stdout/stderr to /dev/null for polldaemon.
1763 Limit the max size of processed clvmd message to ~8KB.
1764 Do not send uninitialised bytes in cluster error reply messages.
1765 Use unsigned type for bitmask instead of enum type for lvm properties.
1766 Add missing cleanup of excl_uuid hash on some exit paths of clvmd.
1767 Check for existence of vg_name in _format1/_pool_vg_read().
1768 Fix missing break in _format_pvsegs (2.02.92).
1769 Test seg pointer for non-null it in raid_target_percent error path.
1770 Check for errors in _init_tags() during config loading.
1771 Always check result of _set_vg_name() in lvcreate.
1772 Drop unused call to uname() during clvmd initialization.
1773 Test allocation result in sysfs filter creation.
1774 Limit sscanf parameters with buffer size in clvmd get_initial_state().
1775 Use const lv pointer for lv_is_active...() functions.
1776 Use same signed numbers in _mirrored_transient_status().
1777 Support 'pvscan --cache' to update lvmetad state from specific PVs.
1778 Provide new metadata daemon for testing with configure --enable-lvmetad .
1779 Integrate client-side lvmetad into build.
1780
1781Version 2.02.93 - 23rd February 2012
1782====================================
1783 Require number of stripes to be greater than parity devices in higher RAID.
1784 Fix allocation code to allow replacement of single RAID 4/5/6 device.
1785 Check all tags and LV names are in a valid form in vg_validate.
1786 Add tmpfiles.d style configuration for lvm2 lock and run directory.
1787 Add configure --with-tmpfilesdir for dir holding volatile-file configuration.
1788 Allow 'lvconvert --repair' to operate on RAID 4/5/6.
1789 Fix build_parallel_areas_from_lv to account correctly for raid parity devices.
1790 Print message when faulty raid devices have been replaced.
1791
1792Version 2.02.92 - 20th February 2012
1793====================================
1794 Read dmeventd monitoring config settings for every lvm command.
1795 For thin devices, initialize monitoring only for thin pools not thin volumes.
1796 Make conversion from a synced 'mirror' to 'raid1' not cause a full resync.
1797 Properly test buffer for unit check in units_to_bytes().
1798 Add configure --with-systemdsystemunitdir.
1799 Add check for allocation failure in _build_matcher().
1800 Add check for rimage name allocation failure in _raid_add_images().
1801 Add check for mda_copy failure in _text_pv_setup().
1802 Add check for _mirrored_init_target failure.
1803 Add free_orphan_vg.
1804 Skip pv/vg_set_fid processing if the fid is same.
1805 Check for foreach loop errors in _vg_read_orphans() (2.02.91).
1806 Clean error paths for format instance creation (2.02.91).
1807 Release vg in error path of _format1_vg_read() instead of just free().
1808 Report allocation failure for allocation of PV structure.
1809 Add clvmd init dependency on dlm service when running with new corosync.
1810
1811Version 2.02.91 - 12th February 2012
1812====================================
1813 Remove PV-based format instances (which are no longer needed).
1814 Link all orphan PVs directly to a per-format global orphan VG.
1815 Refactor lvmcache around an internal API.
1816 Stop processing lvextend if trying to extend a mirror that is being recovered.
1817 Add pool_below_threshold() function to check thin pool percent status.
1818 Fix test for snap percent for failing merge when removing LV.
1819 Switch int to void return for str_list_del().
1820 Fix error path handling in _build_desc().
1821 Add range test for device number in _scan_proc_dev().
1822 Use signed long for sysconf() call in cmirrord.
1823 Do not write in front of log buffer in print_log().
1824 Add boundary test for number of mirror devs and logs.
1825 Check that whole locking_dir fits _lock_dir buffer in init_file_locking().
1826 Use list functions for label_exit().
1827 Ensure strncpy() function always ends with '\0'.
1828 Set status in _fsadm_cmd() for error path.
1829 Add missing deps for lvm2api for rebuild when lvm-internal is changed.
1830 Fix resource leaks for failing allocation of formats (lvm1/2,pool).
1831 Release allocated resources in error path for composite_filter_create().
1832 Do not use lstat() results when failed in _rm_link().
1833 Remove a "waiting for another thread" log message from dmeventd plugins.
1834
1835Version 2.02.90 - 1st February 2012
1836===================================
1837 sync_local_dev_names before (re)activating mirror log for initialisation.
1838 Disable partial activation for thin LVs and LVs with all missing segments.
1839 Do not print warning for pv_min_size between 512KB and 2MB.
1840 Clean up systemd unit ordering and requirements.
1841 Fix lcov reports when srcdir != builddir.
1842 Allow ALLOC_NORMAL to track reserved extents for log and data on same PV.
1843 Automatically detect whether corosync clvmd needs to use confdb or cmap.
1844 Fix data% report for thin volume used as origin for non-thin snapshot.
1845
1846Version 2.02.89 - 26th January 2012
1847===================================
1848 Add missing check for uname result in clvmd TEST processing.
1849 Fix memleak in target_version() error path (unsupported LIST_VERSIONS).
1850 Limit data_alignment and data_alignment_offset to 32bit values.
1851 Check for correctness of uint64 dev_size value in format_text.
1852 Thin pools have segment fields thin_count, zero, transaction_id.
1853 Add data_percent and metadata_percent for thin pools to lvs -v.
1854 Add data_lv & metadata_lv fields to lvs for thin pools.
1855 Add data_percent & pool_lv fields to lvs for thin volumes.
1856 Rename origin_only parm to use_layer for lv_info and use with thin LVs.
1857 Add lv_thin_pool_transaction_id to read the transaction_id value.
1858 Use {suspend,resume}_origin_only when up-converting RAID, as mirrors do.
1859 Always add RAID metadata LVs to deptree (even when origin_only is set).
1860 Change exclusive LV activation logic to try local node before remote nodes.
1861 Add CLVMD_FLAG_REMOTE to skip processing on local node.
1862 Prompt if request is made to remove a snapshot whose "Merge failed".
1863 Allow removal of an invalid snapshot that was to be merged on next activation.
1864 Don't allow a user to merge an invalid snapshot.
1865 Use m and M lv_attr to indicate that a snapshot merge failed in lvs.
1866 Differentiate between snapshot status of "Invalid" and "Merge failed".
1867 Report snapshot usage percent of origin volume when a snapshot is merging.
1868 Require global/lvdisplay_shows_full_device_path for (bogus) lvm1-style paths.
1869 Do not report linear segtype for non-striped targets.
1870 Record creation host & time for each LV and report as lv_time & lv_host.
1871 Make error message hit when preallocated memlock memory exceeded clearer.
1872 Use R lv_attr to indicate read-only activation of non-read-only device in lvs.
1873 Show read-only activation override in lvdisplay & add 4 to perms in -c.
1874 Add activation/read_only_volume_list to override LV permission in metadata.
1875 Give priority to emcpower devices with duplicate PVIDs.
1876 Add check for error in _adjust_policy_params() (lvextend --use-policies).
1877 Round specified percentages upwards (%LV, %VG...) when resizing LVs.
1878 Use dmeventd_lvm2_command in dmeventd plugins snapshot, raid, mirror.
1879 Add helper dmeventd_lvm2_command() to libdevmapper-event-lvm2 library.
1880 Update documentation for dmeventd.
1881 Remove unnecessary stat before opening device in dev_open_flags.
1882 Reduce number of lstat calls when selecting device alias.
1883 Add _dev_init to initialize common struct device members.
1884 Always zalloc struct device during initialization.
1885 Fix missing thread list manipulation protection in dmeventd.
1886 Do not derefence lv pointer in _percent_run() function before NULL check.
1887 Allow empty strings for description and creation_host config fields.
1888 Issue deprecation warning when removing last lvm1-format snapshot.
1889 Reinstate support for snapshot removal with lvm1 format. (2.02.86)
1890 Add policy-based automated repair of RAID logical volumes.
1891 Don't allow two images to be split and tracked from a RAID LV at one time.
1892 Don't allow size change of RAID LV that is tracking changes for a split image.
1893 Don't allow size change of RAID sub-LVs independently.
1894 Don't allow name change of RAID LV that is tracking changes for a split image.
1895 Do not allow users to change the name of RAID sub-LVs independently.
1896 Do not allow users to change permissions on RAID sub-LVs.
1897 Allow lvconvert to replace specified devices in a RAID array.
1898 Add activation/use_linear_target enabled by default.
1899 Use gcc warning options only with .c to .o compilation.
1900 Move y/n prompts to stderr and repeat if response has both 'n' and 'y'.
1901 Replace the unit testing framework with CUnit (--enable-testing).
1902 Fix dmeventd snapshot monitoring when multiple extensions were involved.
1903 Don't ignore configure --mandir and --infodir.
1904 Drop pool memory allocated within lv_has_target_type().
1905 Reduce stack allocation of some PATH_MAX sized char buffers.
1906 Unlock memory before writing metadata.
1907 Add query before removing snapshots when inactive snapshot origin is removed.
1908 Allow changing availability state of snapshots.
1909 Skip non-virtual snapshots for availability change for lvchange with vg name.
1910 Skip adjusting mirror region size unless mirror or raid.
1911 Reorder prompt conditions for removal of active volumes.
1912 Avoid 'mda inconsistency' by properly registering UNLABELLED_PV flag.(2.02.86)
1913 Fix --enable-static_link unless using --enable-dmeventd / --enable-udev_sync.
1914 Move gentoo MAKEDEV to /sbin in lvm2create_initrd.
1915 Add filter to avoid scan of device if it is part of active multipath.
1916 Add missing default $LVM_VG_NAME usage for snapshots.
1917 Avoid extent_count overflow with lvextend.
1918 Add missing lvrename mirrored log recursion in for_each_sub_lv.
1919 Improve lv_extend stack reporting.
1920 Increase virtual segment size instead of creating multiple segment list.
1921 Add last_seg(lv) internal function.
1922 Support empty string for log/prefix.
1923 Disallow mirrored logs for cluster mirrors. (2.02.72)
1924 Don't print char type[8] as a plain string in pvck PV type.
1925 Use vg memory pool implicitly for vg read.
1926 Always use vg memory pool for allocated lv segment.
1927 Remove extra 4kB buffer allocated on stack in print_log().
1928 Make move_lv_segment non-static function and use dm_list function.
1929 Pass exclusive LV locks to all nodes in the cluster.
1930 Improve lvcreate chunksize man page description.
1931 Improve man page style for lvcreate & lvs.
1932 Avoid recursive calls to dmeventd in its LVM plugins.
1933 Log dev name now returned to kernel for registering during cmirror CTR.
1934 Fix lv_info open_count test for disabled verify_udev_operations. (2.02.86)
1935 Simplify code for lvm worker thread in clvmd.
1936 Use pthread_barrier to synchronize clvmd threads at startup.
1937 Limit clvmd's thread size to 128KiB and ignore activation/reserved_stack.
1938 Reduce default preallocated stack size to 64KiB.
1939 Add check for access through NULL pointer when refresh_filter() fails.
1940 Use pthread condition for SINGLENODE lock implementation.
1941 Improve backtrace reporting for some dev_manager_ functions.
1942 Change message severity to log_warn when symlink creation fails.
1943 Add ability to convert mirror segtype to RAID1 segtype.
1944 Add ability to convert from linear to RAID1.
1945 Add ability to extend mirrors with '--nosync' option.
1946 Fix splitmirror LV names to maintain consistent state in a cluster.
1947 Apply appropriate udev flags when suspending/resuming mirror sub-LVs.
1948 Fix vgsplit to handle mirrored logs.
1949 Clarify multi-name device filter pattern matching explanation in lvm.conf.
1950 Introduce revert_lv for better pvmove cleanup.
1951 Replace incomplete pvmove activation failure recovery code with a message.
1952 Abort if _finish_pvmove suspend_lvs fails instead of cleaning up incompletely.
1953 Change suspend_lvs to call vg_revert internally.
1954 Change vg_revert to void and remove superfluous calls after failed vg_commit.
1955 Use execvp for CLVMD restart to preserve environment settings.
1956 Restart CLVMD with same cluster manager.
1957 Fix log_error() usage in raid and unknown segtype initialisation.
1958 Improve testing Makefile.
1959 Fix install_ocf make target when srcdir != builddir. (2.02.80)
1960 Support env vars LVM_CLVMD_BINARY and LVM_BINARY in clvmd.
1961 Fix restart of clvmd (preserve exlusive locks). (2.02.64)
1962 Add 'Volume Type' lv_attr characters for RAID and RAID_IMAGE.
1963 Add activation/retry_deactivation to lvm.conf to retry deactivation of an LV.
1964 Replace open_count check with holders/mounted_fs check on lvremove path.
1965 Disallow the creation of mirrors (mirror or raid1 segtype) with only one leg.
1966 Cleanup restart clvmd code (no memory allocation, debug print passed args).
1967 Add all exclusive locks to clvmd restart option args.
1968 Always send the whole clvmd packet header in refresh commands.
1969 Add missing error checks for some system calls in cmirrord.
1970 Add missing log_error() to lvresize command when fsadm tool fails.
1971 Add support for DM_DEV_DIR device path into fsadm script.
1972 Support different PATH setting for fsadm script testing.
1973 Surround all executed commands with quotes in fsadm script.
1974 Fix missing '$' in test for content of "$LVM" in fsadm script.
1975 Move debug message in exec_cmd after sync_local_dev_names.
1976 Fix clvmd processing of invalid request on local socket.
1977 Fix command line option decoding.
1978 Reset LV status when unlinking LV from VG.
1979 Fix overly-strict extent-count divisibility requirements for striped mirrors.
1980 Fix rounding direction in lvresize when reducing volume size.
1981 Fix possible overflow of size if %FREE or %VG is used.
1982 Fix vgchange activation of snapshot with virtual origin.
1983 Activate virtual snapshot origin exclusively (only on local node in cluster).
1984 Fix lv_mirror_count to handle mirrored stripes properly.
1985 Fix failure to down-convert a mirror to linear due to udev "dev open" conflict
1986 Fix mirrored log creation when PE size is small: use log_size >= region_size.
1987 Fix log size calculation when only a log is being added to a mirror.
1988 Add 7th lv_attr char to show the related kernel target.
1989 Terminate pv_attr field correctly. (2.02.86)
1990 Fix 'not not' typo in pvcreate man page.
1991 Improve man page style for fsadm, lvreduce, lvremove, lvrename & lvresize.
1992 Support break for vgchange and vgrefresh operation.
1993 Switch int to unsigned type for pvmetadatacopies for pv_create().
1994 Replace :space: with [\t ] for awk in vgimportclone (not widely supported).
1995 Begin using 64-bit status field flags.
1996 Detect sscanf recovering_region input error in cmirrord pull_state().
1997 Fix error path bitmap leak in cmirrord import_checkpoint().
1998 Log unlink() error in cmirrord remove_lockfile().
1999 Remove incorrect requirement for -j or -m from lvchange error message.
2000 Fix unsafe table load when splitting off smaller mirror from a larger one.
2001 Use size_t return type for text_vg_export_raw() and export_vg_to_buffer().
2002 Add configure --enable-lvmetad for building the (experimental) LVMetaD.
2003 Fix resource leak when strdup fails in _get_device_status() (2.02.85).
2004 Directly allocate buffer memory in a pvck scan instead of using a mempool.
2005 Add configure --with-thin for segtypes "thin" and "thin_pool".
2006 Fix raid shared lib segtype registration (2.02.87).
2007
2008Version 2.02.88 - 19th August 2011
2009==================================
2010 Remove incorrect 'Breaking' error message from allocation code. (2.02.87)
2011 Add lvconvert --merge support for raid1 devices split with --trackchanges.
2012 Support lvconvert of -m1 raid1 devices to a higher number.
2013 Add --trackchanges support to lvconvert --splitmirrors option for raid1.
2014 Support splitting off a single raid1 rimage in lvconvert --splitmirrors.
2015 Use sync_local_dev_names when reducing number of raid rimages in lvconvert.
2016 Add -V as short form of --virtualsize in lvcreate.
2017 Fix make clean not to remove Makefile. (2.02.87)
2018
2019Version 2.02.87 - 12th August 2011
2020==================================
2021 Fix make distclean to remove stray dmeventd and exported symbols files.
2022 Add global/detect_internal_vg_cache_corruption to lvm.conf.
2023 Use memory pool locking to check for corruption of internal VG structs.
2024 Cache and share generated VG structs.
2025 Fix possible format instance memory leaks and premature releases in _vg_read.
2026 Suppress locking error messages in monitoring init scripts.
2027 If pipe in clvmd fails return busy instead of using uninitialised descriptors.
2028 Add ability to reduce the number of mirrors in raid1 arrays to lvconvert.
2029 Add dmeventd plugin for raid.
2030 Replace free_vg with release_vg and move it to vg.c.
2031 Remove INCONSISTENT_VG flag from the code.
2032 Remove lock from cache in _lock_vol even if unlock fails.
2033 Initialise clvmd locks before lvm context to avoid open descriptor leaks.
2034 Remove obsolete gulm clvmd cluster locking support.
2035 Suppress low-level locking errors and warnings while using --sysinit.
2036 Remove unused inconsistent_seqno variable in _vg_read().
2037 Remove meaningless const type qualifiers on cast type.
2038 Add test for fcntl error in singlenode client code.
2039 Remove --force option from lvrename manpage.
2040 Add global/mirror_segtype_default to pick md raid or dm mirror as default.
2041 Add configure --with-raid for new segtype 'raid' for MD RAID 1/4/5/6 support.
2042 Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used if there is no config file.
2043 Add systemd unit file to provide lvm2 monitoring.
2044 Compare file size (as well as timestamp) to detect changed config file.
2045
2046Version 2.02.86 - 8th July 2011
2047===============================
2048 Remove unnecessary warning in pvcreate for MD linear devices.
2049 Move snapshot removal activation logic into lib/activate.
2050 Cope with a PV only discovered missing when creating deptree.
2051 Abort operation if dm_tree_node_add_target_area fails.
2052 Add activation/checks to lvm.conf to perform additional ioctl validation.
2053 Always preload on suspend, even if no metadata changed (lvchange --refresh).
2054 When suspending, automatically preload newly-visible existing LVs.
2055 Teardown any stray devices with $COMMON_PREFIX during test runs.
2056 Reinstate correct permissions when creating mirrors. [2.02.85]
2057 Append 'm' attribute to pv_attr for missing PVs.
2058 Annotate CLVMD_CMD_SYNC_NAMES in decode_cmd.
2059 Remove enforcement of udev verification when using non-standard /dev location.
2060 Keep an exclusive mirror non-clustered if reloaded e.g. during conversion.
2061 Reject allocation if number of extents is not divisible by area count.
2062 Fix cluster mirror creation to work with new mirror allocation algorithm.
2063 Ignore activation/verify_udev_operations if dm kernel driver vsn < 4.18.
2064 Add activation/verify_udev_operations to lvm.conf, disabled by default.
2065 Call vg_mark_partial_lvs() before VG structure is returned from the cache.
2066 Remove unused internal flag ACTIVATE_EXCL from the code.
2067 Remove useless test of ACTIVATE_EXCL in lv_add_mirrors() clustered code path.
2068 Add lv_activate_opts structure for activation (replacing activation flags).
2069 Ignore inconsistent pre-commit metadata on MISSING_PV devs while activating.
2070 Add proper udev library context initialization and finalization to liblvm.
2071 Fix last snapshot removal to avoid table reload while a device is suspended.
2072 Use dm_get_suspended_counter in replacement critical_section logic.
2073 Downgrade critical_section errors to debug level until it is moved to libdm.
2074 Fix ignored background polling default in vgchange -ay.
2075 Fix pvmove activation sequences to avoid trapped I/O with multiple LVs.
2076 Annotate critical section debug messages.
2077 Fix reduction of mirrors with striped segments to always align to stripe size.
2078 Validate mirror segments size.
2079 Include lvmetad development code in tree.
2080 Fix extent rounding for striped volumes never to reduce more than requested.
2081 Fix create_temp_name to replace any '/' found in the hostname with '?'.
2082 Always use append to file in lvmdump. selinux policy may ban file truncation.
2083 Propagate test mode to clvmd to skip activation and changes to held locks.
2084 Defer writing PV labels until vg_write.
2085 Store label_sector only in struct physical_volume.
2086 Permit --available with lvcreate so non-snapshot LVs need not be activated.
2087 Report sector containing label in verbose message.
2088 Clarify error message when unable to convert an LV into a snapshot of an LV.
2089 Add and use dev_open_readonly and variations.
2090 Do not log a superfluous stack message when the lv is properly processed.
2091 Do not issue an error message when unable to remove .cache on read-only fs.
2092 Avoid memlock size mismatch by preallocating stdio line buffers.
2093 Rewrite vgreduce --removemissing --force to share lvconvert code.
2094 Reorganize lvconvert --repair code to allow reuse.
2095
2096Version 2.02.85 - 29th April 2011
2097=================================
2098 Add new obtain_device_list_from_udev setting to lvm.conf.
2099 Obtain device list from udev by default if LVM2 is compiled with udev support.
2100 Add test for vgimportclone and querying of vgnames with duplicate pvs.
2101 Avoid use of released memory when duplicate PV is found.
2102 Add "devices/issue_discards" to lvm.conf.
2103 Issue discards on lvremove and lvreduce etc. if enabled and supported.
2104 Add seg_pe_ranges and devices fields to liblvm.
2105 Fix incorrect tests for dm_snprintf() failure.
2106 Fix some unmatching sign comparation gcc warnings in the code.
2107 Support lv_extend() on empty LVs.
2108 Avoid regenerating cache content when exported VG buffer is unchanged.
2109 Extend the set of memory regions that are not locked to memory.
2110 Workaround some problems when compiled for valgrind memcheck.
2111 Support controlled quit of the lvm_thread_fn function in clvmd.
2112 Fix reading of unallocated memory in lvm1 format import function.
2113 Replace several strncmp() calls with id_equal().
2114 Fix lvmcache_info transfer to orphan_vginfo in _lvmcache_update_vgname().
2115 Fix -Wold-style-definition gcc warnings.
2116 Rename MIRROR_NOTSYNCED to LV_NOTSYNCED.
2117 Fix _move_lv_segments to handle empty LVs.
2118 Fixes for lvconvert (including --repair) of temporary mirror stacks.
2119 Avoid potential loop when removing mirror images.
2120 Fix mirror removal always to take account of preferences as to which.
2121 Fix MIRRORED flag usage.
2122 Remove error messages issued by device_is_usable when run as non-root.
2123 Add missing \0 for grown debug object in _bitset_with_random_bits().
2124 Fix allocation of system_id buffer in volume_group structure.
2125 Fix readlink usage inside get_primary_dev().
2126 Use format instance mempool where possible and adequate.
2127 Call destroy_instance for any PVs found in VG structure during vg_free call.
2128 Add new free_pv_fid fn and use it throughout to free all attached fids.
2129 Use only vg_set_fid and new pv_set_fid fn to assign the format instance.
2130 Make create_text_context fn static and move it inside create_instance fn.
2131 Add mem and ref_count fields to struct format_instance for own mempool use.
2132 Use new alloc_fid fn for common format instance initialisation.
2133 Optimise _get_token() and _eat_space().
2134 Add _lv_postorder_vg() to improve efficiency for all LVs in VG.
2135 Add gdbinit script for debugging.
2136 Use hash tables to speedup string search in vg_validate().
2137 Refactor allocation of VG structure adding alloc_vg().
2138 Avoid possible endless loop in _free_vginfo when 4 or more VGs have same name.
2139 Use empty string instead of /dev// for LV path when there's no VG.
2140 Don't allocate unused VG mempool in _pvsegs_sub_single.
2141 Do not send uninitialised bytes in local clvmd messages.
2142 Support --help option for clvmd and return error for unknown option.
2143 Avoid reading freed memory when printing LV segment type.
2144 Fix syslog initialisation in clvmd to respect lvm.conf setting.
2145 Fix possible overflow in maximum stripe size and physical extent size.
2146 Improve pvremove error message when PV belongs to a VG.
2147 Extend normal policy to allow mirror logs on same PVs as images if necessary.
2148 Improve cling policy to recognise PVs already used during the transaction.
2149 Improve normal allocation algorithm to include clinging to existing areas.
2150 Add allocation/maximise_cling & mirror_logs_require_separate_pvs to lvm.conf.
2151 Adapt metadata balancing code to work with metadata handling changes.
2152 Add old_id field to physical_volume and fix pvchange -u for recent changes.
2153 Allow pvresize on a PV with two metadata areas.
2154 Change pvcreate to use new metadata handling interface.
2155 Restructure existing pv_setup and pv_write and add pv_initialise.
2156 Add internal interface to support adding and removing metadata areas.
2157 Allow internal indexing of metadata areas (PV id + mda order).
2158 Generalise internal format_instance infrastrusture for PV and VG use.
2159 Handle decimal digits with --units instead of ignoring them silently.
2160 Fix remaining warnings and compile with -Wpointer-arith.
2161 Fix gcc warnings for unused variables and const casts.
2162 Add stack backtraces for error paths in process_each_lv().
2163 Temporarily suppress error from calling yes_no_prompt while locks are held.
2164 Replace void* with char* arithmetic in _text_write, _text_read & send_message.
2165 Fix compilation without DEVMAPPER_SUPPORT.
2166 Remove fs_unlock() from lv_suspend error path.
2167 Allow memory to stay locked between leaving and re-entering critical sections.
2168 Rename memlock to critical_section throughout.
2169 Make pv_min_size configurable and increase to 2048KB to exclude floppy drives.
2170 Add find_config_tree_int64 to read 64-bit ints from config.
2171 Ensure resuming exclusive cluster mirror continues to use local mirror target.
2172 Clear temporary postorder LV status flags to allow re-use with same LV struct.
2173 Remove invalid snapshot umount mesg which floods syslog from dmeventd plugin.
2174 Add extended examples to pvmove man page.
2175 Support LVM_TEST_DEVDIR env var for private /dev during testing.
2176
2177Version 2.02.84 - 9th February 2011
2178===================================
2179 Fix CRC32 calculation on big endian CPU (2.02.75).
2180
2181Version 2.02.83 - 4th February 2011
2182===================================
2183 Allow exclusive activation of snapshots in a cluster.
2184 Leave EX lock unchanged when suspending a device in clvmd.
2185 Use sync_dev_names in unlock_vg macro for cluster-wide dev name sync.
2186 Fix fs operation stack handling when multiple operations on same device.
2187 Increase hash table size to 1024 lv names and 64 pv uuids.
2188 Remove fs_unlock() from lv_resume path.
2189 Fix wipe size when setting up mda.
2190 Remove unneeded checks for open_count in lv_info().
2191 Synchronize with udev before checking open_count in lv_info().
2192 Allow CLVMD_CMD_SYNC_NAMES to be propagated around the cluster if requested.
2193 Add "dmsetup ls --tree" output to lvmdump.
2194 Fix udev synchronization with no-locking --sysinit (2.02.80).
2195 Improve man page style consistency for pvcreate, pvremove, pvresize, pvscan.
2196 Avoid rebuilding of uuid validation table.
2197 Improve lvcreate error text from insufficient "extents" to "free space".
2198 Always use O_DIRECT when opening block devices to check for partitioning.
2199
2200Version 2.02.82 - 24th January 2011
2201===================================
2202 Bring lvscan man page up-to-date.
2203 Fix lvchange --test to exit cleanly.
2204 Add change_tag to toollib.
2205 Allow multiple pvchange command line options to be specified together.
2206 Do not fail pvmove polling if another process cleaned up first.
2207 Avoid clvmd incrementing dlm lockspace reference count more than once.
2208 Add -f (don't fork) option to clvmd and fix clvmd -d<num> description.
2209
2210Version 2.02.81 - 17th January 2011
2211===================================
2212 Do not scan devices in dev_reset_error_count().
2213 Skip unnecessary LOCK_NULL unlock call during volume deactivation.
2214 Skip fs_unlock when calling exec_cmd within activation code (for modprobe).
2215 Extend exec_cmd params to specify when device sync (fs_unlock) is needed.
2216 Replace fs_unlock by sync_local_dev_names to notify local clvmd. (2.02.80)
2217 Introduce sync_local_dev_names and CLVMD_CMD_SYNC_NAMES to issue fs_unlock.
2218 Accept fusion fio in device type filter.
2219 Add ability to convert mirror log type from disk to mirrored.
2220
2221Version 2.02.80 - 10th January 2011
2222===================================
2223 Use same dm cookie for consecutive dm ops in same VG to reduce udev waits.
2224 Speed up command processing by caching resolved config tree.
2225 Pass config_tree to renamed function import_vg_from_config_tree().
2226 Detect NULL handle in get_property().
2227 Fix superfluous /usr in ocf_scriptdir instalation path.
2228 Add --with-ocfdir configurable option.
2229 Add aclocal.m4 (for pkgconfig).
2230 Fix memory leak in persistent filter creation error path.
2231 Check for errors setting up dm_task struct in _setup_task().
2232 Fail polldaemon creation when lvmcache_init() fails.
2233 Return PERCENT_INVALID for errors in _copy_percent() and _snap_percent().
2234 Remove some unused variables.
2235 Improve general lvconvert man page description.
2236 Return 0 from cmirrord initscript 'start' if daemon is already running.
2237 Fix wrongly paired unlocking of VG_GLOBAL in pvchange. (2.02.66)
2238 Add backtraces for backup and backup_remove fail paths.
2239 Detect errors from dm_task_set calls in _get_device_info (dmeventd).
2240 Add backtraces for archive and backup_locally in check_current_backup().
2241 Fix memory leak in debug mode of restart_clvmd() error path.
2242 Log error message for pthread_join() failure in clvmd.
2243
2244Version 2.02.79 - 20th December 2010
2245====================================
2246 Remove some unused variables.
2247 Add missing test for reallocation error in _find_parallel_space().
2248 Add checks for allocation errors in config node cloning.
2249 Fix error path if regex engine cannot be created in _build_matcher().
2250 Use char* arithmetic in target_version(), _process_all() & _targets().
2251 Fixing const cast gcc warnings in the code.
2252 Check read() and close() results in _get_cmdline().
2253 Add const for struct config_node usage.
2254 Fix NULL pointer check in error path in clvmd do_command(). (2.02.78)
2255 Fix device.c #include to ensure 64-bit fopen64 use. (2.02.51)
2256 Add copy_percent and snap_percent to liblvm.
2257 Enhance vg_validate to ensure integrity of LV and PV structs referenced.
2258 Enhance vg_validate to check composition of pvmove LVs.
2259 Create /var/run/lvm directory during clvmd initialisation if missing.
2260 Use new dm_prepare_selinux_context instead of dm_set_selinux_context.
2261 Avoid revalidating the label cache immediately after scanning.
2262 Support scanning for a single VG in independent mdas.
2263 Don't skip full scan when independent mdas are present even if memlock is set.
2264 Set cmd->independent_metadata_areas if metadata/dirs or disk_areas in use.
2265 Cope better with an undefined target_percent operation in _percent_run.
2266 Avoid writing to freed memory in vg_release and rename to free_vg. (2.02.78)
2267
2268Version 2.02.78 - 6th December 2010
2269===================================
2270 Abort if segment tag allocation fails in pool format _add_stripe_seg.
2271 Abort in _mirrored_transient_status if referenced log/image LV is not active.
2272 Add backtraces for dev_set() and dev_close_immediate() errors in set_lv().
2273 Log any unlink() error in clvmd remove_lockfile().
2274 Log any pipe write() or close() errors in clvmd child_init_signal().
2275 Detect if orphan vginfo was lost from cache before _lvmcache_update_vgname().
2276 Do a full rescan if some device is missing in lvm1 format read_pvs_in_vg.
2277 Add missing check that dm_pool_create succeeded in write_config_node().
2278 Use dm_snprintf in clvmd-command.c to ensure an overlong buffer is truncated.
2279 Don't write to buffer if its reallocation failed in clvmd do_command().
2280 Switch from float to fixed point percentage handling.
2281 Avoid misleading missing PV warnings in vgextend --restoremissing.
2282 Fix memory leak when VG allocation policy in metadata is invalid.
2283 Ignore unrecognised allocation policy found in metadata instead of aborting.
2284 Factor out tag printing into _out_tags and avoid leaking string buffer.
2285 Remove some unused variables & assignments.
2286 Add missing vg_release calls in _vg_read_by_vgid.
2287 Fix debug logging of derived flag LCK_CACHE in clvmd.
2288 Fix test for no system_dir in _init_backup().
2289 Disallow lvconvert ops that both allocate & free supplied PEs in a single cmd.
2290 Fix liblvm seg_size to give bytes not sectors.
2291 Add functions to look up LV/PV by name/uuid to liblvm.
2292 Free cmd_context if fallback to LVM1 fails in lvm2_main().
2293 Free device name buffer in dmsetup parse_loop_device_name() error paths.
2294 Close format lib if init_format_fn fails in _init_formats().
2295 Don't leave /proc/mounts open after dmeventd snapshot event processing.
2296 Fix out-of-scope arg_vgnames use in process_each_lv().
2297 Remove incorrect dm_task_destroy(NULL) from _node_clear_table() error path.
2298 Add missing closedir in _rm_blks after removing stray LVM1 VG files.
2299 Suppress 'No PV label' message when removing several PVs without mdas.
2300 Fix default /etc/lvm permissions to be 0755. (2.02.66)
2301
2302Version 2.02.77 - 22nd November 2010
2303====================================
2304 Allocate a pool for dummy VG in _pvsegs_sub_single.
2305 Add PV and LV segment types and functions to liblvm.
2306 Add set_property functions to liblvm.
2307 Remove tag length restriction and allow / = ! : # & characters.
2308 Support repetition of --addtag and --deltag arguments.
2309 Add infrastructure for specific cmdline arguments to be repeated in groups.
2310 Split the_args cmdline arguments and values into arg_props and arg_values.
2311 Fix fsadm no longer to require '-f' to resize an unmounted filesystem.
2312 Fix fsadm to detect mounted filesystems on older systems. (2.0.75)
2313 Extend cling allocation policy to recognise PV tags (cling_by_tags).
2314 Add allocation/cling_tag_list to lvm.conf.
2315 Regenerate configure with 'autoreconf' for --enable-ocf. (2.02.76)
2316
2317Version 2.02.76 - 8th November 2010
2318===================================
2319 Clarify error messages when activation fails due to activation filter use.
2320 Add pacemaker script VolumeGroup.ocf with configure --enable-ocf.
2321 Import make.tmpl into include/ Makefile.
2322 Fix handling of online filesystem resize (using new fsadm return code).
2323 Add DIAGNOSTICS section to fsadm man page.
2324 Modify fsadm to return different status code for check of mounted filesystem.
2325 Update VG metadata only once in vgchange when making multiple changes.
2326 Allow independent vgchange arguments to be used together.
2327 Automatically unmount invalidated snapshots in dmeventd.
2328 Suppress some superfluous messages from clang static analysis.
2329 Fix a deadlock caused by double close in clvmd.
2330 Fix NULL pointer dereference on too-large MDA error path in _vg_read_raw_area.
2331 Use static for internal _align_chunk() and _new_chunk() from pool-fast.c.
2332 Fix vgchange to process -a, --refresh, --monitor and --poll like lvchange.
2333 Add lvm2app functions to query any pv, vg, or lv property / report field.
2334
2335Version 2.02.75 - 25th October 2010
2336===================================
2337 Annotate more variables and parameters as const.
2338 Fix missing variable initialization in cluster_send() function from cmirrord.
2339 Fix pointer for VG name in _pv_resize_single error code path.
2340 Fix warning for changed alignment requirements for dmeventd read/write func.
2341 Add global/metadata_read_only to use unrepaired metadata in read-only cmds.
2342 Don't take write lock in vgchange --refresh, --poll or --monitor.
2343 Skip dm devices in scan if they contain only error targets or are empty.
2344 Fix strict-aliasing compile warning in partition table scanning.
2345 Fix pthread mutex usage deadlock in clvmd.
2346 Automatically extend snapshots with dmeventd according to policy in lvm.conf.
2347 Add activation/snapshot_autoextend_threshold/percent to lvm.conf.
2348 Fix liblvm2cmd link order to support --as-needed.
2349 Remove dependency on libm by replacing floor() by an integer-based algorithm.
2350 Fix hang when repairing a mirrored-log that had both devs fail.
2351 Convey need for snapshot-merge target in lvconvert error message and man page.
2352 Add devices/disable_after_error_count config to limit access to failing devs.
2353 Give correct error message when creating a too-small snapshot.
2354 Implement vgextend --restoremissing to reinstate missing devs that return.
2355 Make lvconvert respect --yes and --force when converting an inactive log.
2356 Refactor and add 'get' functions for lv properties/fields.
2357 Update script for fsadm testing.
2358 Better support of noninteractive shell execution of fsadm.
2359 Fix usage of --yes flag for ReiserFS resize in fsadm.
2360 Fix detection of mounted filesystems for fsadm when udev is used.
2361 Fix assignment of default value to LVM variable in fsadm.
2362 Fix support for --yes flag for fsadm.
2363 Do not execute lvresize from fsadm --dry-run.
2364 Fix fsadm return error code from user's break action.
2365 Allow CC to be overridden at build time (for 'scan-build make').
2366 Rename 'flags' to 'status' in struct metadata_area.
2367 Avoid segfault by limiting partial mode for lvm1 metadata. (2.02.74)
2368 Use dm_zalloc and dm_pool_zalloc throughout.
2369 Add pv_get_property and create generic internal _get_property function.
2370 Add 'get' functions for pv and vg properties/fields.
2371 Make generic GET_*_PROPERTY_FN macros with secondary macro for vg, pv & lv.
2372 Add tags_format_and_copy() common function and call from _tags_disp.
2373 Add id_format_and_copy() common function and call from _uuid_disp.
2374 Refactor report.c '*_disp' functions to call supporting functions.
2375 Move parts of metadata*.[ch] into new {pv|vg|lv}.[ch] files.
2376 Fix vg_read memory leak with directory-based metadata.
2377 Fix memory leak of config_tree in reinitialization code path.
2378 Fix pool destruction order in dmeventd_lvm2_exit() to avoid leak debug mesg.
2379 Read whole /proc/self/maps file before working with maps entries.
2380 Speed up unquoting of quoted double quotes and backslashes.
2381 Speed up CRC32 calculations by using a larger lookup table.
2382
2383Version 2.02.74 - 24th September 2010
2384=====================================
2385 Allow : and @ to be escaped with \ in device names of PVs.
2386 Replace alloca with dm_malloc in _aligned_io to avoid stack corruption.
2387 Fix partial mode operations for lvm1 metadata format.
2388 Track recursive filter iteration to avoid refreshing while in use. (2.02.56)
2389 Revert to old glibc vsnprintf behaviour in emit_to_buffer() to catch overflow.
2390 Allocate buffer for metadata tags dynamically to remove 4k limit.
2391 Add random suffix to archive file names to prevent races when being created.
2392 Reinitialize archive and backup handling on toolcontext refresh.
2393 Make poll_mirror_progress report PROGRESS_CHECK_FAILED if LV is not a mirror.
2394 Like mirrors, don't scan origins if ignore_suspended_devices() is set.
2395 Fix return type qualifier to avoid compiler warning. (2.02.69)
2396 Automatically generate LSB Requires-Start for clvmd init script.
2397 Fix return code of pvmove --abort PV.
2398 Fix pvmove --abort to remove even for empty pvmove LV.
2399 Add configure --with-default-data-alignment.
2400 Update heuristic used for default and detected data alignment.
2401 Add "devices/default_data_alignment" to lvm.conf.
2402 Add implementation for simple numeric 'get' property functions.
2403 Define GET_NUM_PROPERTY_FN macro to simplify numeric property 'get' function
2404 Add properties.[ch] to lib/report using columns.h.
2405 Add macro definitions to report infrastructure for character array length.
2406 Remove explicit double quotes from columns.h 'id' entries.
2407 Add 'flags' field to columns.h and define FIELD_MODIFIABLE.
2408 Add vg_mda_size and vg_mda_free functions.
2409 Simplify MD/swap signature detection in pvcreate and allow aborting.
2410 Allow --yes to be used without --force mode.
2411 Fix file descriptor leak in swap signature detection error path.
2412 Detect and allow abort in pvcreate if LUKS signature is detected.
2413 Always mask lock flags correctly when checking for LCK_WRITE.
2414
2415Version 2.02.73 - 18th August 2010
2416==================================
2417 Fix potential for corruption during cluster mirror device failure.
2418 Use 'SINGLENODE' instead of 'dead' in clvmd singlenode messages.
2419 Ignore snapshots when performing mirror recovery beneath an origin.
2420 Pass LCK_ORIGIN_ONLY flag around cluster.
2421 Add suspend_lv_origin and resume_lv_origin using LCK_ORIGIN_ONLY.
2422 Allow internal suspend and resume of origin without its snapshots.
2423 Fix dev_manager_transient to access -real device not snapshot-origin.
2424 Monitor origin -real device below snapshot instead of overlay device.
2425 Don't really change monitoring status when in test mode.
2426 Fix some exit statuses when starting/stopping monitoring fails.
2427 Enable snapshot monitoring by default when dmeventd is enabled.
2428 Move cloned libdevmapper-event client code from segments into lib/activate.
2429 Fix 'lvconvert --splitmirrors' in cluster operation.
2430 Fix clvmd init script exit code to return 4 when executed as non-root user.
2431 Change default alignment of pe_start to 1MB.
2432 Add --norestorefile option to pvcreate.
2433 Require --restorefile when using pvcreate --uuid.
2434 Recognise and give preference to md device partitions (blkext major).
2435 Never scan internal LVM devices.
2436 Don't ignore user-specified PVs in split-mirror operations. (2.02.71)
2437 Fix data corruption bug in cluster mirrors.
2438 Require logical volume(s) to be explicitly named for lvconvert --merge.
2439 Avoid changing aligned pe_start as a side-effect of very verbose logging.
2440 Use built-in rule for device aliases: block/ < dm- < disk/ < mapper/ < other.
2441 Fix const warning in dev_manager_info() and _dev_manager_lv_rmnodes().
2442 Fix const warning in archive_file structure from archive.c.
2443 Clean generated files .exported_symbols_generated, example.conf for distclean.
2444 Handle failure of all mirrored log devices and all but one mirror leg.
2445 Disallow 'mirrored' log type for cluster mirrors.
2446 Do not use VPATH in include/Makefile.
2447 Fix exported_symbols generation to use standard compiler arguments.
2448 Use #include <> not "" in lvm2app.h which gets installed on the system.
2449 Make lib and liblvm.device-mapper wait for include file generation.
2450 Fix configure to supply DEFAULT_RUN_DIR to Makefiles.
2451 Fix allocation of wrong number of mirror logs with 'remove' fault policy.
2452
2453Version 2.02.72 - 28th July 2010 [CVE-2010-2526]
2454=================================================
2455 Change clvmd to communicate with lvm2 via a socket in /var/run/lvm.
2456 Return controlled error if clvmd is run by non-root user.
2457 Add configure --default-run-dir for /var/run/lvm.
2458 Never use clvmd singlenode unless explicitly requested with -Isinglenode.
2459
2460Version 2.02.71 - 28th July 2010
2461================================
2462 Document LVM fault handling in doc/lvm_fault_handling.txt.
2463 Make vgck warn about missing PVs.
2464 Clarify help text for vg_mda_count.
2465 Check if cluster log daemon is running before allowing cmirror create.
2466 Add unit-tests dir.
2467 Add configure --enable-testing and reports and report-generators dirs.
2468 Correct LV list order used by lvconvert when splitting a mirror.
2469 Check if LV with specified name already exists when splitting a mirror.
2470 Fix suspend/resume logic for LVs resulting from splitting a mirror.
2471 Update pvcreate, {pv|vg}change, and lvm.conf man pages about metadataignore.
2472 Switch cmirrord and clvmd to use dm_create_lockfile.
2473 Allow clvmd pidfile to be configurable.
2474 Update comments about memory handling in lvm2app.h.
2475 Add more verbose messages while checking volume_list and hosttags settings.
2476 Add log_error when strdup fails in {vg|lv}_change_tag().
2477 Remove unnecessary includes in liblvm files.
2478 Use __attribute__ consistently throughout.
2479 Fix redundant declarations and always compile with -Wredundant-decls.
2480 Fix possible hang when all mirror images of a mirrored log fail.
2481 Pass metadataignore to pv_create, pv_setup, _mda_setup, and add_mda.
2482 Init mda->list in mda_copy.
2483 Do not log backtrace in valid _lv_resume() code path.
2484 Cleanup help strings in configure.in.
2485 Prompt if metadataignore with vgextend or pvchange would adjust vg_mda_copies.
2486 Adjust vg_mda_copies if metadataignore given with vgextend or pvchange.
2487 Adjust auto-metadata repair and caching logic to try to cope with empty mdas.
2488
2489Version 2.02.70 - 6th July 2010
2490===============================
2491 Remove log directly if all mirror images of a mirrored log fail.
2492 Randomly select which mdas to use or ignore.
2493 Add some missing standard configure.in checks.
2494 Add printf format attributes to yes_no_prompt and fix a caller.
2495 Always pass unsuspended dm devices through persistent filter to other filters.
2496 Move test for suspended dm devices ahead of other filters.
2497 Fix another segfault in clvmd -R if no response from daemon. (2.02.68)
2498 Remove superfluous suspended device counter from clvmd.
2499 Fix lvm shell crash when input is entirely whitespace.
2500 Update partial mode warning message.
2501 Preserve memlock balance in clvmd when activation triggers a resume.
2502 Restore the removemissing behaviour of lvconvert --repair --use-policies.
2503
2504Version 2.02.69 - 30th June 2010
2505================================
2506 Fix vgremove to allow removal of VG with missing PVs. (2.02.52)
2507 Add metadata/vgmetadatacopies to lvm.conf.
2508 Add --metadataignore to pvcreate and vgextend.
2509 Add vg_mda_copies, pv_mda_used_count and vg_mda_used_count to reports.
2510 Describe --vgmetadatacopies in lvm.conf and other man pages.
2511 Add --[vg]metadatacopies to select number of mdas to use in a VG.
2512 Make the metadata ignore bit control read/write metadata areas in a PV.
2513 Add pvchange --metadataignore to set or clear a metadata ignore bit.
2514 Refactor metadata code to prepare for --metadataignore / --vgmetadatacopies.
2515 Ensure region_size of mirrored log does not exceed its full size.
2516 Generate liblvm2app exported symbols from header file.
2517 Preload libc locale messages to prevent reading it in memory locked state.
2518 Fix handling of simultaneous mirror image and mirrored log image failure.
2519
2520Version 2.02.68 - 23rd June 2010
2521================================
2522 Fix clvmd initscript status to print only active clustered LVs.
2523 Add lv_path to reports to offer full /dev pathname.
2524 Fix typo in warning message about missing device with allocated data areas.
2525 Add device name and offset to raw_read_mda_header error messages.
2526 Honour log argument when down-converting stacked mirror.
2527 Sleep to workaround clvmd -S race: socket closed early and server drops cmd.
2528 Use early udev synchronisation and update of dev nodes for clustered mirrors.
2529 Remove incorrect inclusion of kdev_t.h from cmirrord/functions.h.
2530 Add man pages for lvmconf and non-existent lvmsadc and lvmsar tools.
2531 Exit successfully when using -o help (but not -o +help) with LVM reports.
2532 Do not use internal DLM lock definitions in generic LVM2 clvmd code.
2533 Add --force, --nofsck and --resizefs to lvresize/extend/reduce man pages.
2534 Fix lvm2cmd example in documentation.
2535 Allow use of lvm2app and lvm2cmd headers in C++ code.
2536 Remove unused #includes from clvmd files and introduce clvmd-common.h.
2537 Move common inclusions to clvmd-common.h.
2538 Use #include "" for libdevmapper.h and configure.h throughout tree.
2539 Fix LVM_PATH expansion when exec_prefix=NONE. (2.02.67)
2540 Fix segfault in clvmd -R if no response from daemon received.
2541
2542Version 2.02.67 - 4th June 2010
2543===============================
2544 Handle failed restart of clvmd using -S switch properly.
2545 Fix clvmd initscript restart command to start clvmd if not yet running.
2546 Use built-in absolute paths in clvmd (clvmd restart and PV and LV queries).
2547 Require partial option in lvchange --refresh for partial LVs.
2548 Do not fail lvm_init() if init_logging() or _init_rand() generates an errno.
2549 Don't merge unchanged persistent cache file before dumping if tool scanned.
2550 Fix incorrect memory pool deallocation while using vg_read for files.
2551 Add --type parameter description to the lvcreate man page.
2552 Replace strncmp kernel version number checks with proper ones.
2553 Avoid selecting names under /dev/block if there is an alternative.
2554 Update clustered log kernel module name to log-userspace for 2.6.31 onwards.
2555 Add replicators' LVs to dtree for activation.
2556 Supress activation message if there is a missing replicator VG.
2557 Fix scripts/relpath.awk to work in mawk
2558 Extend lock_vol to check for missing replicator VGs first.
2559 Update _process_one_vg and process_each_lv_in_vg to populate cmd_vg.
2560 Add cmd_vg structure and associated functions for replicator.
2561 Extend _lv_each_dependency() to handle replicator dependencies.
2562 Add check_replicator_segment() to catch internal replicator errors.
2563 Initial support for replicator metadata.
2564 Extend process_each_lv_in_vg() to provide list of failed lvnames.
2565 Consistently return ECMD_FAILED if process_each_*lv() is interrupted.
2566
2567Version 2.02.66 - 20th May 2010
2568===============================
2569 If unable to obtain snapshot percentage leave value blank on reports.
2570 Add install_system_dirs and install_initscripts makefile targets.
2571 Add configure options for system and locking directories.
2572 Generate example.conf so default lvm.conf contents can be configured.
2573 Install lvmconf script by default.
2574 Remove unnecessary versioned dmeventd plugin symlinks.
2575 Add tests for lvm_vgname_from_{pvid|device}.
2576 Add lvm2app interfaces to lookup a vgname from a pvid and pvname.
2577 Update pvchange to always obtain a vg handle for each pv to process.
2578 Add find_vgname_from_{pvname|pvid} functions.
2579 Add pvid_from_devname and lvmcache_vgname_from_pvid lvmcache functions.
2580 Validate orphan and VG_GLOBAL lock order too.
2581 Accept orphan VG names as parameters to lock_vol() and related functions.
2582 Use is_orphan_vg in place of hard-coded prefix tests and add is_global_vg.
2583
2584Version 2.02.65 - 17th May 2010
2585===============================
2586 Fix clvmd init script never to deactivate non-clustered volume groups.
2587 Disallow vgchange --clustered if there are active mirrors or snapshots.
2588 Introduce lv_is_mirrored.
2589 Use /bin/bash for scripts with bashisms.
2590 Skip internal lvm devices in scan if ignore_suspended_devices is set.
2591 Do not merge old device cache after we run full scan. (2.02.56)
2592 Add pkgconfigdir Makefile variable for make install override.
2593 Configure pkgconfig udev and selinux dependencies.
2594 Switch Libs.private to Requires.private in devmapper.pc and lvm2app.pc.
2595 Use pkgconfig Requires.private for devmapper-event.pc.
2596 Add libdevmapper to linked libdevmapper-event.so.
2597 Link liblvm2cmd.so with libdevmapper-event and libdevmapper.
2598 Fix truncated total size displayed by pvscan.
2599 Add new --sysinit compound option to vgchange and lvchange.
2600 Drop duplicate errors for read failures and missing devices to verbose level.
2601 Use $(libdir)/lvm2 with make install_lvm2_plugin.
2602 Use $(libdir)/device-mapper with make install_dm_plugin.
2603 Add dm_list_splice() function to join two lists together.
2604
2605Version 2.02.64 - 30th April 2010
2606=================================
2607 Avoid pointless initialisation when the 'version' command is run directly.
2608 Fix memory leak for invalid regex pattern input.
2609 Display invalid regex pattern for filter configuration in case of error.
2610 Remove no-longer-used arg_ptr_value.
2611 Fix -M and --type to use strings, not pointers that change on config refresh.
2612 Fix lvconvert error message when existing mirrored LV is not found.
2613 Set appropriate udev flags for reserved LVs.
2614 Disallow the direct removal of a merging snapshot.
2615 Don't preload the origin when removing a snapshot whose merge is pending.
2616 Disallow the addition of mirror images while a conversion is happening.
2617 Disallow primary mirror image removal when mirror is not in-sync.
2618 Remove obsolete --name parameter from vgcfgrestore.
2619 Add -S command to clvmd to restart the daemon preserving exclusive locks.
2620 Increment lvm2app version from 1 to 2 (memory allocation changes).
2621 Change lvm2app memory alloc/free for pv/vg/lv properties.
2622 Change daemon lock filename from lvm2_monitor to lvm2-monitor for consistency.
2623 Install symbolic .so links with relative paths between usrlibdir and libdir.
2624 Add awk script relpath.awk to calculate paths for relative symlinks.
2625 Use @AWK@ in makefiles.
2626 Fix double DESTDIR usage for infodir and mandir.
2627
2628Version 2.02.63 - 14th April 2010
2629=================================
2630 Rename lvm_dump.sh to lvmdump.sh.
2631 Allow incomplete mirror restore in lvconvert --repair upon insufficient space.
2632 Do not reset position in metadata ring buffer on vgrename and vgcfgrestore.
2633 Allow VGs with active LVs to be renamed.
2634 Use UUIDs instead of names while processing event handlers.
2635 Only pass visible LVs to tools in cmdline VG name/tag expansions without -a.
2636 Use typedefs for toollib process_each functions.
2637 Use C locales and use_mlockall for clvmd.
2638 Refactor code related to vg->pvs list and add pv->vg link.
2639 Mask LCK_HOLD flag in cluster VG locks for backwards compatibility.
2640 Add activation/polling_interval to lvm.conf as --interval default.
2641 Don't ignore error if resuming any LV fails in resume_lvs.
2642 Skip closing persistent filter cache file if open failed.
2643 Install .a and .so links into $(usrlibdir).
2644 Add --enable-write_install options to install user-writable files.
2645 Use INSTALL_PROGRAM/DATA/WDATA target.
2646 Switch from using VPATH to vpath in Makefiles.
2647 Permit mimage LVs to be striped in lvcreate, lvresize and lvconvert.
2648 Fix pvmove allocation to take existing parallel stripes into account.
2649 Add pvmove_source_seg to struct lv_segment.
2650 Fix incorrect removal of symlinks after LV deactivation fails.
2651 Fix is_partitioned_dev not to attempt to reopen device.
2652 Fix another thread race in clvmd.
2653 Refactor management of vg->pvs list.
2654 Fix lcov rules and generate better coverage report.
2655 Improve vg_validate to detect some loops in lists.
2656 Change most remaining log_error WARNING messages to log_warn.
2657 Always use blocking lock for VGs and orphan locks.
2658 Allocate all memory for segments from private VG mempool.
2659 Return newly allocated PV segment after segment split.
2660 Optimise searching PV segments for seeking the most recently-added.
2661 Remove vg_validate call when parsing cached metadata.
2662 Use hash table of LVs to speed up parsing of text metadata with many LVs.
2663 Fix two vg_validate messages, adding whitespace and parentheses.
2664 When dmeventd is not forking because of -d flag, don't kill parent process.
2665 Fix 'make install' when $(builddir) is different from $(srcdir).
2666 Fix dso resource leak in error path of dmeventd.
2667 Use C locales and use_mlockall for dmeventd.
2668 Fix --alloc contiguous policy only to allocate one set of parallel areas.
2669 Do not allow {vg|lv}change --ignoremonitoring if on clustered VG.
2670 Improved dependency tracking for dmeventd and liblvm2cmd sources.
2671 Improved Makefile rules for distclean and cflow targets.
2672 Add ability to create mirrored logs for mirror LVs.
2673 Fix clvmd cluster propagation of dmeventd monitoring mode.
2674 Allow ALLOC_ANYWHERE to split contiguous areas.
2675 Use INTERNAL_ERROR for internal errors throughout tree.
2676 Add some assertions to allocation code.
2677 Introduce pv_area_used into allocation algorithm and add debug messages.
2678 Add activation/monitoring to lvm.conf.
2679 Add --monitor and --ignoremonitoring to lvcreate.
2680 Allow dynamic extension of array of areas selected as allocation candidates.
2681 Export and use only valid cookie value in test suite.
2682 Remove const modifier for struct volume_group* from process_each_lv_in_vg().
2683 Don't allow resizing of internal logical volumes.
2684 Fix libdevmapper-event pkgconfig version string to match libdevmapper.
2685 Avoid scanning all pvs in the system if operating on a device with mdas.
2686 Add configure --with-clvmd=singlenode to use clvmd w/o cluster infrastructure.
2687 Get stacktrace if testsuite test drops core and lvm was built with debugging.
2688 Disable long living process flag in lvm2app.
2689 Fix pvcreate device md filter check.
2690 Suppress repeated errors about the same missing PV uuids.
2691 Bypass full device scans when using internally-cached VG metadata.
2692 Only do one full device scan during each read of text format metadata.
2693 Remove unnecessary full_scan parameter from get_vgids and get_vgnames calls.
2694 Look up missing PVs by uuid not dev_name in _pvs_single to avoid invalid stat.
2695 Make find_pv_in_vg_by_uuid() return same type as related functions.
2696 Introduce is_missing_pv().
2697 Fix clvmd Makefile to not overwrite LIBS from template definition.
2698
2699Version 2.02.62 - 9th March 2010
2700================================
2701 Add use_mlockall and mlock_filter to activation section of lvm.conf.
2702 Add default alternative to mlockall using mlock to reduce pinned memory size.
2703 Remove -rdynamic from static builds.
2704 Update checks for pthread, readline & selinux libs and link only when needed.
2705 Introduce makefile vars UDEV_LIBS, DL_LIBS, SELINUX_LIBS, STATIC_LIBS.
2706 Introduce makefile vars LVMINTERNAL_LIBS, READLINE_LIBS, PTHREAD_LIBS.
2707 Toggle configure help to print --disable-fsadm.
2708 Use $() instead of ${} consistently for all Makefile variables.
2709 Replace CFLOW_CMD only in make.tmpl and use it as variable elsewhere.
2710 Use $(top_builddir) for inclusion of make.tmpl in Makefiles.
2711 Fix autoconf warning about ignored datarootdir.
2712 Increase AC_PREREQ version to 2.61 (for AC_PROC_SED, AC_PROG_MKDIR_P).
2713 Handle misaligned devices that report alignment_offset of -1.
2714 Extend core allocation code in preparation for mirrored log areas.
2715 Rewrite clvmd init script.
2716 Remove lvs_in_vg_activated_by_uuid_only call.
2717 No longer fall back to looking up active devices by name if uuid not found.
2718 Don't touch /dev in vgmknodes if activation is disabled.
2719 Update lvm2app.h Doxygen comments and add lvm2app Doxygen config file.
2720 Update nightly tests and lvm2app unit tests to cover tags.
2721 Add lvm2app functions lvm_{vg|lv}_{get|add|remove}_tag() functions.
2722 Add dm_pool_strdup to allocate and copy memory in tag library function.
2723 Refactor vgcreate, vgchange, and lvchange for tag library function.
2724 Refactor snapshot-merge deptree and device removal to support info-by-uuid.
2725
2726Version 2.02.61 - 15th February 2010
2727====================================
2728 Fix some consts and floating point gcc warnings.
2729 Fix dm_report_field_uint64 function to accept 64-bit ints.
2730 Change readhead display to use 32-bit -1 const instead of 64-bit.
2731 Add LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES environment variable.
2732 Remove hard-coding that skipped _mimage devices from 11-dm-lvm.rules.
2733 Use udev transactions in test suite.
2734 Set udev state automatically instead of using LVM_UDEV_DISABLE_CHECKING.
2735 Add lvm_pv_get_size, lvm_pv_get_free and lvm_pv_get_dev_size to lvm2app.
2736 Change lvm2app to return all sizes in bytes as documented (not sectors).
2737 Add 'fail_if_percent_unsupported' arg to _percent and _percent_run.
2738 Remove false "failed to find tree node" error when activating merging origin.
2739 Exit with success when lvconvert --repair --use-policies performs no action.
2740 Accept a list of LVs with 'lvconvert --merge @tag' using process_each_lv.
2741 Avoid unnecessary second resync when adding mimage to core-logged mirror.
2742 Exclude internal VG names and uuids from lists returned through lvm2app.
2743 Add %ORIGIN support to lv{create,extend,reduce,resize} --extents.
2744 Add _mda_copy to clone a struct metadata_area.
2745 Remove pointless versioned symlinks to dmeventd plugin libraries.
2746 Fix dmeventd snapshot plugin build dependency.
2747 Make clvmd -V return status zero.
2748 Remove unnecessary 'dmsetup resume' following 'dmsetup create' in tests.
2749 Fix cmirrord segfault in clog_cpg list processing when converting mirror log.
2750 Deactivate temporary pvmove mirror cluster-wide when activating it fails.
2751 Always query device by uuid and not name in clvmd.
2752 Add missing metadata vg_reverts in pvmove error paths.
2753 Unlock shared lock in clvmd if activation calls fail.
2754 Return success from dev_manager_info with non-existent uuid if ioctl succeeds.
2755
2756Version 2.02.60 - 23rd January 2010
2757===================================
2758 Extend cmirrord man page.
2759 Sleep before first progress check if pvmove/lvconvert interval has prefix '+'.
2760 Default to checking progress before waiting in _wait_for_single_lv.
2761 Fix cmirror initscript (including syntax error).
2762 Eliminate avoidable ioctls for checking open_count in _add_new_lv_to_dtree.
2763 Disable memory debugging if dmeventd is configured. (Not thread-safe.)
2764 Fix first log message prefix in syslog for dmeventd plugins.
2765 Fix exported symbols names for dmeventd lvm2 wrapper plugin.
2766 Make failed locking initialisation messages more descriptive.
2767
2768Version 2.02.59 - 21st January 2010
2769===================================
2770 Add libdevmapper-event-lvm2.so to serialise dmeventd plugin liblvm2cmd use.
2771 Cleanup memory initialization and freeing in pv_read() and pv_create().
2772 Clear pointer and counters after their release in _fin_commands().
2773 Stop dmeventd trying to access already-removed snapshots.
2774 Remove (fallback) /dev mknod from cmirrord.
2775 Add t-topology-support.sh and t-snapshot-merge.sh tests.
2776 Fix clvmd to never scan suspended devices.
2777 Fix dmeventd build outside source tree.
2778 Assorted cmirror code changes to remove various compiler warnings.
2779 Fix detection of completed snapshot merge.
2780 Add Red Hat cmirror initscript (unfinished).
2781 Add cmirrord man page (incomplete).
2782 Make cluster log communication structures architecture independant.
2783 Fix cluster log in-memory bitmap handling.
2784 Improve snapshot merge metadata import validation.
2785 Improve target type compatibility checking in _percent_run().
2786 Add 'target_status_compatible' method to 'struct segtype_handler'.
2787 Change underscore to hyphen in table line for clustered log type.
2788
2789Version 2.02.58 - 14th January 2010
2790===================================
2791 Cleanup some minor gcc warnings.
2792 Add --merge to lvconvert to merge a snapshot into its origin.
2793 Fix clvmd automatic target module loading crash (no reset_locking fn).
2794 Fix allocation code not to stop at the first area of a PV that fits.
2795
2796Version 2.02.57 - 12th January 2010
2797===================================
2798 Ensure exactly one process returns from poll_daemon(), never two.
2799 Reset _vgs_locked in lvmcache_init() in child after forking.
2800 Define {DM, LVM}_UDEV_DISABLE_CHECKING=1 environment variables during tests.
2801 Enable udev_sync and udev_rules in lvm.conf by default while running tests.
2802 If LVM_UDEV_DISABLE_CHECKING in set in environment, disable udev warnings.
2803 Add --splitmirrors to lvconvert to split off part of a mirror.
2804 Change background polldaemon's process name to "(lvm2)".
2805 Allow vgremove to remove a VG with PVs missing after a prompt.
2806 Return success in lvconvert --repair --use-policies on failed allocation.
2807 Keep log type consistent when changing mirror image count.
2808 Always set environment variables for an LVM2 device in 11-dm-lvm.rules.
2809 Add activation/udev_rules config option in lvm.conf.
2810 Add consts to text metadata flag structs.
2811 Add macros outfc, outsize, outhint and function out_text_with_comment.
2812 Reimplement report FIELD macro using offsetof instead of static structs.
2813 Fix fsadm man page typo (fsdam).
2814 Rename mirror_device_fault_policy to mirror_image_fault policy.
2815 Remove empty PV devices if lvconvert --repair is using defined policies.
2816 Use fixed buffer to prevent stack overflow in persistent filter dump.
2817 Use extended status of new kernel snapshot target 1.8.0 to detect when empty.
2818 Insert stack macros in suspend_lv, resume_lv & (de)activate_lv callers.
2819 Add --poll flag to vgchange and lvchange to control background daemon launch.
2820 Propagate metadata commit and revert notifications to other cluster nodes.
2821 Use proper mask for VG lock mode in clvmd.
2822 Allow precommitted metadata to be dropped from lvmcache.
2823 Move processing of VG locks to separate function in clvmd.
2824 Properly decode all flags in clvmd messages including VG locks.
2825 Properly handle precommitted cache flag when only committed metadata present.
2826 Resume renamed volumes in reverse order to preserve memlock pairing.
2827 Drop cached metadata after device was auto-repaired and removed from VG.
2828 Clear MISSING_PV flag if PV reappeared and is empty.
2829 Fix removal of multiple devices from a mirror.
2830 Also clean up PVs flagged as missing in vgreduce --removemissing --force.
2831 Introduce INTERNAL_ERROR macro for error messages and use throughout.
2832 Remove superfluous returns from void functions.
2833 Destroy allocated mempool in _vg_read_orphans() error path.
2834 Fix some pvresize and toollib error paths with missing VG releases/unlocks.
2835 Explicitly call suspend for temporary mirror layer.
2836 Allow use of precommitted metadata when a PV is missing.
2837 Add memlock information to do_lock_lv debug output.
2838 Always bypass calls to remote cluster nodes for non-clustered VGs.
2839 Permit implicit cluster lock conversion in pre/post callbacks on local node.
2840 Permit implicit cluster lock conversion to the lock mode already held.
2841 Fix lock flag masking in clvmd so intended code paths get invoked.
2842 Replace magic masks in cluster locking code by defined masks.
2843 Remove newly-created mirror log from metadata if initial deactivation fails.
2844 Correct activated or deactivated text in vgchange summary message.
2845 Improve pvmove error message when all source LVs are skipped.
2846 Fix memlock imbalance in lv_suspend if already suspended.
2847 Fix pvmove test mode not to poll (and fail).
2848 Fix vgcreate error message if VG already exists.
2849 Fix tools to use log_error when aborted due to user response to prompt.
2850 Fix ignored readahead setting in lvcreate --readahead.
2851 Fix clvmd memory leak in lv_info_by_lvid by calling release_vg.
2852 If aborting due to internal error, always send that message to stderr.
2853 Add global/abort_on_internal_errors to lvm.conf to assist testing.
2854 Fix test Makefiles when builddir and srcdir differ.
2855 Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
2856 Use locking_type 3 (compiled in) for lvmconf --enable-cluster.
2857 Remove list.c and list.h with no-longer-used dm_list macros and functions.
2858 Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
2859 Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
2860
2861Version 2.02.56 - 24th November 2009
2862====================================
2863 Add missing vg_release to pvs and pvdisplay to fix memory leak.
2864 Do not try to unlock VG which is not locked in _process_one_vg.
2865 Move is_long_lived persistent_filter_dump to happen after every full scan.
2866 Refresh device filters before full device rescan in lvmcache.
2867 Return error status if vgchange fails to activate some volume.
2868 Fix suspend/resume lock type test causing unbalanced memory locking.
2869 Revert vg_read_internal change as clvmd was not ready for vg_read. (2.02.55)
2870
2871Version 2.02.55 - 19th November 2009
2872====================================
2873 Fix deadlock when changing mirrors due to unpaired memlock refcount changes.
2874 Use separate memlock counter for dmeventd handlers to permit device scanning.
2875 Directly restrict vgchange to activating visible LVs.
2876 Fix pvmove region_size overflow for very large PVs.
2877 Fix lvcreate and lvresize %PVS argument always to use sensible total size.
2878 Tidy some uses of arg_count and introduce arg_is_set.
2879 Export outnl and indent functions for modules.
2880 Flush stdout after yes/no prompt.
2881 Update vgsplit and vgcreate to use vg_set_clustered.
2882 Add vg_mda_count and vg_set_clustered library functions.
2883 Add more vgcreate and vgsplit nightly tests.
2884 Insert some missing stack macros into activation code.
2885 Recognise DRBD devices and handle them like md devices.
2886
2887Version 2.02.54 - 26th October 2009
2888===================================
2889 Update lvcreate/lvconvert man pages to explain PhysicalVolume parameter.
2890 Document --all option in man pages, cleanup {pv|vg|lv}{s|display} man pages.
2891 Permit snapshots of mirrors.
2892 Cleanup mimagetmp LV if allocation fails for new lvconvert mimage.
2893 Fix clvmd segfault when refresh_toolcontext fails.
2894 Remember to clear 'global lock held during cache refresh' state after use.
2895 Use udev flags support in LVM and apply various fixes to udev rules.
2896 Delay announcing mirror monitoring to syslog until initialisation succeeded.
2897 Handle metadata with unknown segment types more gracefully.
2898 Set default owner and group to null.
2899 Add dmeventd.static to the build.
2900 Disable realtime support code by default.
2901 Make clvmd return 0 on success rather than 1.
2902 Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
2903 Add implict pvcreate support to vgcreate and vgextend.
2904 Correct example.conf to indicate that lvm2 not lvm1 is the default format.
2905 Remove an unused stray LVM1_SUPPORT ifdef.
2906 Only include selinux libs in libdevmapper.pc when selinux build enabled.
2907 Allow for a build directory separate from the source.
2908 Update distclean target for rename clogd to cmirrord. (2.02.52)
2909 Only do lock conversions in clvmd if we are explicitly asked for one.
2910 Introduce percent_range_t and centralise snapshot full/mirror in-sync checks.
2911 Factor out poll_mirror_progress and introduce progress_t.
2912 Distinguish between powers of 1000 and powers of 1024 in unit suffixes.
2913 Restart lvconverts in vgchange by sharing lv_spawn_background_polling.
2914 Generalise polldaemon code by changing mirror-specific variable names.
2915 Don't attempt to deactivate an LV if any of its snapshots are in use.
2916 Return error if lv_deactivate fails to remove device from kernel.
2917 Provide alternative implementation of obsolete siginterrupt().
2918 Consolidate LV allocation into alloc_lv().
2919 Treat input units of both 's' and 'S' as 512-byte sectors. (2.02.49)
2920 Use standard output units for 'PE Size' and 'Stripe size' in pv/lvdisplay.
2921 Add configure --enable-units-compat to set si_unit_consistency off by default.
2922 Add global/si_unit_consistency to enable cleaned-up use of units in output.
2923
2924Version 2.02.53 - 25th September 2009
2925=====================================
2926 Create any directories in /dev with DM_DEV_DIR_UMASK (022).
2927 Enable dmeventd monitoring section of config file by default.
2928 Update lvm2 monitoring script to lvm2_monitoring_init_red_hat.in.
2929 Fix lvm2app test to run under test/api subdirectory only when configured.
2930 Add vg_is_resizeable() and cleanup reference to VG_RESIZEABLE.
2931
2932Version 2.02.52 - 15th September 2009
2933=====================================
2934 Update _process_one_vg to cleanup properly after vg_read_error.
2935 Add lots of missing stack debug messages to tools.
2936 Make readonly locking available as locking type 4.
2937 Fix readonly locking to permit writeable global locks (for vgscan). (2.02.49)
2938 Add DM_UDEV_RULES_VSN environment variable to udev rules.
2939 Update vgsplit, vgmerge, and vgrename to obey new vgname ordering rules.
2940 Make lvm2app pv_t, lv_t, vg_t handle definitions consistent with lvm_t.
2941 Enforce an alphabetical lock ordering on vgname locking.
2942 Prioritise write locks over read locks by default for file locking.
2943 Add local lock files with suffix ':aux' to serialise locking requests.
2944 Fix global locking in PV reporting commands (2.02.49).
2945 Fix pvcreate string termination in duplicate uuid warning message.
2946 Don't loop reading sysfs with pvcreate on a non-blkext partition (2.02.51).
2947 Fix vgcfgrestore error paths when locking fails (2.02.49).
2948 Update Makefile distclean target.
2949 Add libudev configuration check.
2950 Make clvmd check corosync to see what cluster interface it should use.
2951 Add clvmd autodetection check and cleanup related configure messages.
2952 Rewrite clvmd configuration code to cope with all combinations of libs.
2953 Added configure --enable-cmirrord to build the cluster mirror log daemon.
2954 Rename clogd to cmirrord.
2955 Make lvchange --refresh only take a read lock on volume group.
2956 Fix race where non-blocking file locks could be granted in error.
2957 Fix vgextend error path - if ORPHAN lock fails, unlock / release vg (2.02.49).
2958 Fix compile warning in clvmd.
2959 Clarify use of PE ranges in lv{convert|create|extend|resize} man pages.
2960 Remove useless _pv_write wrapper.
2961 Add lvm2app.sh to tests conditional upon configure --enable-applib.
2962 Add lvm_vg_is_clustered, lvm_vg_is_exported, and lvm_vg_is_partial.
2963 Update lvm_vg_remove to require lvm_vg_write to commit remove to disk.
2964 Update test/api/test.c to call lvm_vg_create and lvm_vg_remove.
2965
2966Version 2.02.51 - 6th August 2009
2967=================================
2968 Fix locking in clvmd (2.02.50).
2969 Add --noudevsync option for relevant LVM tools.
2970 Add activation/udev_sync to lvm.conf.
2971 Only change LV symlinks on ACTIVATE not PRELOAD.
2972 Make lvconvert honour log mirror options combined with downconversion.
2973 Allow LV suspend while --ignorelockingfailure is in force.
2974 Update synopsis in lvconvert manpage to mention --repair.
2975 Set cookies in activation code and wait for udev to complete processing.
2976 Added configure --enable-udev_rules --enable-udev_sync.
2977 Added configure --with-udev-prefix --with-udevdir.
2978 Added udev dir to hold udev rules.
2979 Add devices/data_alignment_detection to lvm.conf.
2980 Add devices/data_alignment_offset_detection to lvm.conf.
2981 Add --dataalignmentoffset to pvcreate to shift start of aligned data area.
2982 Fix _mda_setup() to not check first mda's size before pe_align rounding.
2983 Document -I option of clvmd in the man page.
2984 Fix configure script to handle multiple clvmd selections.
2985 Fix lvm2app.pc installation filename.
2986 Remove pv_t, vg_t & lv_t handles from lib. Only liblvm uses them.
2987 Rename lvm.h to lvm2app.h for now.
2988
2989Version 2.02.50 - 28th July 2009
2990================================
2991 Change test/api/test.c prompt so it's not confused with the main lvm prompt.
2992 Update liblvm unit tests in test/api to cover latest liblvm changes.
2993 Add unimplemented lvm_lv_resize and lvm_pv_resize skeletons to liblvm.
2994 Add lvm_library_get_version to liblvm.
2995 Add lvm_config_override to liblvm to allow caller to override LVM config.
2996 Add lvm_lv_is_active and lvm_lv_is_suspended to liblvm.
2997 Add lvm_lv_activate and lvm_lv_deactivate to liblvm.
2998 Add lvm_scan, lvm_vg_reduce and lvm_vg_remove_lv to liblvm.
2999 Add functions to get numeric properties to liblvm.
3000 Add lvm_{pv|vg|lv}_get_{name|uuid} to liblvm.
3001 Add lvm_vg_list_pvs and lvm_vg_list_lvs to liblvm.
3002 Add lvm_vg_open and lvm_vg_create_lv_linear to liblvm.
3003 Add lvm_list_vg_names/uuids to liblvm.
3004 Add lvm_errno and lvm_errmsg to liblvm to obtain failure information.
3005 Rename lvm_create/destroy to lvm_init/quit.
3006 Rename lvm_reload_config to lvm_config_reload.
3007 Refactor _override_settings to use new override_config_tree_from_string.
3008 Add vg_reduce to metadata.c and metadata-exported.h.
3009 Update lvm.h to clarify API behavior and return codes.
3010 Update lvm_vg_extend to do an implicit pvcreate on the device.
3011 Update display.c to use vg_free(vg) instead of duplicating the calculation.
3012 Refactor vg_size, vg_free, and pv_mda_count field calculations for liblvm.
3013 Refactor pvcreate and lvcreate for liblvm.
3014 Add global/wait_for_locks to lvm.conf so blocking for locks can be disabled.
3015 All LV locks are non-blocking so remove LCK_NONBLOCK from separate macros.
3016 Fix race condition with vgcreate and vgextend on same device (2.02.49).
3017 Remove redundant validate_name call from vgreduce.
3018 Remove unused handles lvseg, pvseg inside liblvm/lvm.h.
3019 Add liblvm2app Makefile installation targets.
3020 Add liblvm pkgconfig file.
3021 Use newly-independent LVM_LIBAPI in liblvm soname. E.g. liblvm2app.so.2.1.
3022 Add an API version number, LVM_LIBAPI, to the VERSION string for liblvm.
3023 Pass a pointer to struct cmd_context to init_multiple_segtypes
3024 Return EINVALID_CMD_LINE not success when invalid VG name format is used.
3025 Remove unnecessary messages after vgcreate/vgsplit refactor (2.02.49).
3026 Add log_errno to set a specific errno and replace log_error in due course.
3027 Change create_toolcontext to still return an object if it fails part-way.
3028 Add EUNCLASSIFIED (-1) as the default LVM errno code.
3029 Store any errno and error messages issued while processing each command.
3030 Use log_error macro consistently throughout in place of log_err.
3031
3032Version 2.02.49 - 15th July 2009
3033================================
3034 Add readonly locking type to replace implementation of --ignorelockingfailure.
3035 Exclude VG_GLOBAL from vg_write_lock_held so scans open devs read-only again.
3036 Add unit test case for liblvm VG create/delete APIs.
3037 Add liblvm APIs to implement creation and deletion of VGs.
3038 Initialize cmd->cmd_line to "liblvm" in new liblvm library.
3039 Place handles to liblvm objects for pv, vg, lv, lvseg, pvseg inside lvm.h.
3040 Refactor vgsplit and vgextend to remove READ_REQUIRE_RESIZEABLE flag.
3041 Use _exit() not exit() after forking to avoid flushing libc buffers twice.
3042 Add cast to log_info arg in _find_labeller to avoid Sparc64 warning.
3043 Make cmd->cmd_line const.
3044 Fix dev name mismatch in vgcreate man page example.
3045 Refactor vg_remove_single for use in liblvm.
3046 Make all tools use consistent lock ordering obtaining VG_ORPHAN lock second.
3047 Check md devices for a partition table during device scan.
3048 Add extended device (blkext) and md partition (mdp) types to filters.
3049 Make text metadata read errors for segment areas more precise.
3050 Fix text segment metadata read errors to mention correct segment name.
3051 Include segment and LV names in text segment import error messages.
3052 Add parent node to config_node structure.
3053 Update vgsplit and vgcreate to call new vg_create and 'set' functions.
3054 Change vg_create to take minimal parameters, obtain a lock, and return vg_t.
3055 Refactor vgchange extent_size, max_lv, max_pv, and alloc_policy for liblvm.
3056 Update t-vgcreate-usage.sh to test for default vg properties.
3057 Fix memory leak in vgsplit when re-reading the vg.
3058 Make various exit/cleanup paths more robust after lvm init failures.
3059 Use LCK_NONBLOCK implicitly instead of explicit vg_read() flag.
3060 Remove unnecessary locking and existence tests from new vg_read() interface.
3061 Permit several segment types to be registered by a single shared object.
3062 Update the man pages to document size units uniformly.
3063 Allow commandline sizes to be specified in terms of bytes and sectors.
3064 Update 'md_chunk_alignment' to use stripe-width to align PV data area.
3065 Update test/t-inconsistent-metadata.sh to match new vg_read interface.
3066 Add lvmcache_init() to polldaemon initialization.
3067 Convert tools to use new vg_read / vg_read_for_update.
3068 Fix segfault in vg_release when vg->cmd is NULL.
3069
3070Version 2.02.48 - 30th June 2009
3071================================
3072 Abort if automatic metadata correction fails when reading VG to update it.
3073 Explicitly request fallback to default major number in device mapper.
3074 Ignore suspended devices during repair.
3075 Call vgreduce --removemissing automatically to fix missing PVs in dmeventd.
3076 Suggest using lvchange --resync when adding leg to not-yet-synced mirror.
3077 Destroy toolcontext on clvmd exit to avoid memory pool leaks.
3078 Fix lvconvert not to poll mirror if no conversion in progress.
3079 Fix memory leaks in toolcontext error path.
3080 Reinstate partial activation support in clustered mode. (2.02.40)
3081 Allow metadata correction even when PVs are missing.
3082 Use 'lvm lvresize' instead of 'lvresize' in fsadm.
3083 Do not use '-n' realine option in fsadm for busybox compatiblity.
3084 Add vg_lock_newname() library function for vgrename, vgsplit and vgcreate.
3085 Round up requested readahead to at least one page and print warning.
3086 Try to repair vg before actual vgremove when force flag provided.
3087 Fix possible double release of VG after recovery.
3088 Add parameter to process_each_vg specifying what to do with inconsistent VG.
3089 Unify error messages when processing inconsistent volume group.
3090 Use lvconvert --repair instead of vgreduce in mirror dmeventd DSO.
3091 Introduce lvconvert --use_policies (repair policy according to lvm.conf).
3092 Update clvmd-corosync to match new corosync API.
3093 Fix lib Makefile to include any shared libraries in default target.
3094 Fix rename of active snapshot with virtual origin.
3095 Fix convert polling to ignore LV with different UUID.
3096 Cache underlying device readahead only before activation calls.
3097 Fix segfault when calculating readahead on missing device in vgreduce.
3098 Remove verbose 'visited' messages.
3099 Handle multi-extent mirror log allocation when smallest PV has only 1 extent.
3100 Add LSB standard headers and functions (incl. reload) to clvmd initscript.
3101 When creating new LV, double-check that name is not already in use.
3102 Remove /dev/vgname/lvname symlink automatically if LV is no longer visible.
3103 Rename internal vorigin LV to match visible LV.
3104 Suppress 'removed' messages displayed when internal LVs are removed.
3105 Fix lvchange -a and -p for sparse LVs.
3106 Fix lvcreate --virtualsize to activate the new device immediately.
3107 Make --snapshot optional with lvcreate --virtualsize.
3108 Generalise --virtualoriginsize to --virtualsize.
3109 Skip virtual origins in process_each_lv_in_vg() without --all.
3110 Fix counting of virtual origin LVs in vg_validate.
3111 Attempt to load dm-zero module if zero target needed but not present.
3112
3113Version 2.02.47 - 22nd May 2009
3114===============================
3115 Rename liblvm.so to liblvm2app.so and use configure --enable-applib.
3116 Reinstate version in liblvm2cmd.so soname. (2.02.44)
3117
3118Version 2.02.46 - 21st May 2009
3119===============================
3120 Inherit readahead setting from underlying devices during activation.
3121 Detect LVs active on remote nodes by querying locks if supported.
3122 Enable online resizing of mirrors.
3123 Use suspend with flush when device size was changed during table preload.
3124 Implement query_resource_fn for cluster_locking.
3125 Support query_resource_fn in locking modules.
3126 Introduce CLVMD_CMD_LOCK_QUERY command for clvmd.
3127 Fix pvmove to revert operation if temporary mirror creation fails.
3128 Fix metadata export for VG with missing PVs.
3129 Add vgimportclone and install it and the man page by default.
3130 Force max_lv restriction only for newly created LV.
3131 Remove unneeded import parameter from lv_create_empty.
3132 Merge lv_is_displayable and lv_is_visible functions.
3133 Introduce lv_set_visible & lv_set_hidden functions.
3134 Fix lv_is_visible to handle virtual origin.
3135 Introduce link_lv_to_vg and unlink_lv_from_vg functions.
3136 Remove lv_count from VG and use counter function instead.
3137 Fix snapshot segment import to not use duplicate segments & replace.
3138 Do not query nonexistent devices for readahead.
3139 Remove NON_BLOCKING lock flag from tools and set a policy to auto-set.
3140 Remove snapshot_count from VG and use function instead.
3141 Fix first_seg() call for empty segment list.
3142 Add install_lvm2 makefile target to install only the LVM2 components.
3143 Reject missing PVs from allocation in toollib.
3144 Fix PV datalignment for values starting prior to MDA area. (2.02.45)
3145 Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
3146 Fix minimum width of devices column in reports.
3147 Add lvs origin_size field.
3148 Fix linux configure --enable-debug to exclude -O2.
3149 Implement lvconvert --repair for repairing partially-failed mirrors.
3150 Fix vgreduce --removemissing failure exit code.
3151 Fix remote metadata backup for clvmd.
3152 Introduce unlock_and_release_vg macro.
3153 Introduce vg_release() to be called to free every struct volume_group.
3154 Alloc PV internal structure from VG mempool if possible.
3155 Fix metadata backup to run after vg_commit always.
3156 Tidy clvmd volume lock cache functions.
3157 Fix pvs report for orphan PVs when segment attributes are requested.
3158 Fix pvs -a output to not read volume groups from non-PV devices.
3159 Add MMC (mmcblk) device type to filters.
3160 Introduce memory pools per volume group (to reduce memory for large VGs).
3161 Use copy of PV structure when manipulating global PV lists.
3162 Always return exit error status when locking of volume group fails.
3163 Fix mirror log convert validation question.
3164 Avoid referencing files from DESTDIR during build process.
3165 Avoid creating some static libraries unless configured --enable-static_link.
3166 Enable use of cached metadata for pvs and pvdisplay commands.
3167 Add missing 'device-mapper' internal subdir build dependency.
3168 Fix memory leak in mirror allocation code.
3169 Save and restore the previous logging level when log level is changed.
3170 Fix error message when archive initialization fails.
3171 Make sure clvmd-corosync releases the lockspace when it exits.
3172 Fix segfault for vgcfgrestore on VG with missing PVs.
3173 Block SIGTERM & SIGINT in clvmd subthreads.
3174 Detect and conditionally wipe swapspace signatures in pvcreate.
3175 Fix maximal volume count check for snapshots if max_lv set for volume group.
3176 Fix lvcreate to remove unused cow volume if the snapshot creation fails.
3177 Fix error messages when PV uuid or pe_start reading fails.
3178 Build new liblvm application-level library.
3179 Rename liblvm.a to liblvm-internal.a.
3180 Flush memory pool and fix locking in clvmd refresh and backup command.
3181 Fix unlocks in clvmd-corosync. (2.02.45)
3182 Fix error message when adding metadata directory to internal list fails.
3183 Fix size and error message of memory allocation at backup initialization.
3184 Remove old metadata backup file after renaming VG.
3185 Restore log_suppress state when metadata backup file is up-to-date.
3186
3187Version 2.02.45 - 3rd March 2009
3188================================
3189 Avoid scanning empty metadata areas for VG names.
3190 Attempt proper clean up in child before executing new binary in exec_cmd().
3191 Do not scan devices if reporting only attributes from PV label.
3192 Use pkgconfig to obtain corosync library details during configuration.
3193 Fix error returns in clvmd-corosync interface to DLM.
3194 Add --refresh to vgchange and vgmknodes man pages.
3195 Pass --test from lvresize to fsadm as --dry-run.
3196 Supply argv[] list to exec_cmd() to allow for variable number of parameters.
3197 Prevent fsadm from checking mounted filesystems.
3198 No longer treats any other key as 'no' when prompting in fsadm.
3199 Tidy fsadm command line processing.
3200 Add lib/lvm.h and lib/lvm_base.c for the new library interface.
3201 Move tools/version.h to lib/misc/lvm-version.h.
3202 Split LVM_VERSION into MAJOR, MINOR, PATCHLEVEL, RELEASE and RELEASE_DATE.
3203 Add system_dir parameter to create_toolcontext().
3204 Add --dataalignment to pvcreate to specify alignment of data area.
3205 Exclude LCK_CACHE locks from _vg_lock_count, fixing interrupt unblocking.
3206 Provide da and mda locations in debug message when writing text format label.
3207 Mention the restriction on file descriptors at invocation on the lvm man page.
3208 Index cached vgmetadata by vgid not vgname to cope with duplicate vgnames.
3209 No longer require kernel and metadata major numbers to match.
3210 Add a fully-functional get_cluster_name() to clvmd corosync interface.
3211 Remove duplicate cpg_initialize from clvmd startup.
3212 Add option to /etc/sysconfig/cluster to select cluster type for clvmd.
3213 Allow clvmd to start up if its lockspace already exists.
3214 Separate PV label attributes which do not need parse metadata when reporting.
3215 Remove external dependency on the 'cut' command from fsadm.
3216 Fix pvs segfault when pv mda attributes requested for not available PV.
3217 Add fsadm support for reszing ext4 filesysystems.
3218 Move locking_type reading inside init_locking().
3219 Rename get_vgs() to get_vgnames() and clarify related error messages.
3220 Allow clvmd to be built with all cluster managers & select one on cmdline.
3221 Mention --with-clvmd=corosync in ./configure.
3222 Replace internal vg_check_status() implementation.
3223 Rename vg_read() to vg_read_internal().
3224
3225Version 2.02.44 - 26th January 2009
3226===================================
3227 Fix --enable-static_link after the recent repository changes.
3228 Add corosync/DLM cluster interface to clvmd.
3229 Add --nameprefixes, --unquoted, --rows to pvs, vgs, lvs man pages.
3230 Fix lvresize size conversion for fsadm when block size is not 1K.
3231 Fix pvs segfault when run with orphan PV and some VG fields.
3232 Display a 'dev_size' of zero for missing devices in reports.
3233 Add pv_mda_size to pvs and vg_mda_size to vgs.
3234 Fix lvmdump /sys listing to include virtual devices directory.
3235 Add "--refresh" functionality to vgchange and vgmknodes.
3236 Avoid exceeding LV size when wiping device.
3237 Calculate mirror log size instead of using 1 extent.
3238 Ensure requested device number is available before activating with it.
3239 Fix incorrect exit status from 'help <command>'.
3240 Fix vgrename using UUID if there are VGs with identical names.
3241 Fix segfault when invalid field given in reporting commands.
3242 Move is_static from cmd to global is_static().
3243 Refactor init_lvm() for lvmcmdline and clvmd.
3244 Add liblvm interactive test infrastructure to build.
3245 Add skeleton lvm2.h file in preparation for a shared library interface.
3246 Use better random seed value in temp file creation.
3247 Add read_urandom to read /dev/urandom. Use in uuid calculation.
3248 Use displayable_lvs_in_vg and lv_is_displayable for consistency throughout.
3249 Fix race in vgcreate that would result in second caller overwriting first.
3250 Fix uninitialised lv_count in vgdisplay -c.
3251 Don't skip updating pvid hash when lvmcache_info struct got swapped.
3252 Add tinfo to termcap search path for pld-linux.
3253 Fix startup race in clvmd.
3254 Generate Red Hat clvmd startup script at config time with correct paths.
3255 Fix clvmd & dmeventd builds after tree restructuring.
3256 Cope with snapshot dependencies when removing a whole VG with lvremove.
3257 Make man pages and tool help text consistent using | for alternative options.
3258
3259Version 2.02.43 - 10th November 2008
3260====================================
3261 Merge device-mapper into the lvm2 tree.
3262 Correct prototype for --permission on lvchange and lvcreate man pages.
3263 Exit with non-zero status from vgdisplay if couldn't show any requested VG.
3264 Move list.c into libdevmapper and rename functions.
3265 Rename a couple of variables that matched function names.
3266 Use simplified x.y.z version number in libdevmapper.pc.
3267 Remove ancient debian directory.
3268 Split out lvm-logging.h from log.h and lvm-globals.[ch] from log.[ch].
3269
3270Version 2.02.42 - 26th October 2008
3271===================================
3272 Accept locking fallback_to_* options in the global section as documented.
3273 Fix temp table activation in mirror conversions not to happen in other cmds.
3274 Fix temp table in mirror conversions to use always-present error not zero.
3275
3276Version 2.02.41 - 17th October 2008
3277===================================
3278 Use temp table to set device size when converting mirrors.
3279 In resume_mirror_images replace activate_lv with resume_lv as workaround.
3280 Avoid overwriting in-use on-disk text metadata by forgetting MDA_HEADER_SIZE.
3281 Fix snapshot monitoring library to not cancel monitoring invalid snapshot.
3282 Generate man pages from templates and include version.
3283 Add usrlibdir and usrsbindir to configure.
3284 Fix conversion of md chunk size into sectors.
3285 Free text metadata buffer after a failure writing it.
3286 Fix misleading error message when there are no allocatable extents in VG.
3287 Fix handling of PVs which reappeared with old metadata version.
3288 Fix mirror DSO to call vgreduce with proper parameters.
3289 Fix validation of --minor and --major in lvcreate to require -My always.
3290 Fix release: clvmd build, vgreduce consolidate & tests, /dev/ioerror warning.
3291
3292Version 2.02.40 - 19th September 2008
3293=====================================
3294 Allow lvremove to remove LVs from VGs with missing PVs.
3295 In VG with PVs missing, by default allow activation of LVs that are complete.
3296 Track PARTIAL_LV and MISSING_PV flags internally.
3297 Require --force with --removemissing in vgreduce to remove partial LVs.
3298 No longer write out PARTIAL flag into metadata backups.
3299 Treat new default activation/missing_stripe_filler "error" as an error target.
3300 Remove internal partial_mode.
3301 Add devices/md_chunk_alignment to lvm.conf.
3302 Pass struct physical_volume to pe_align and adjust for md chunk size.
3303 Store sysfs location in struct cmd_context.
3304 Avoid shuffling remaining mirror images when removing one, retaining primary.
3305 Add missing LV error target activation in _remove_mirror_images.
3306 Prevent resizing an LV while lvconvert is using it.
3307 Avoid repeatedly wiping cache while VG_GLOBAL is held in vgscan & pvscan.
3308 Fix pvresize to not allow resize if PV has two metadata areas.
3309 Fix setting of volume limit count if converting to lvm1 format.
3310 Fix vgconvert logical volume id metadata validation.
3311 Fix lvmdump metadata gather option (-m) to work correctly.
3312 Fix allocation bug in text metadata format write error path.
3313 Fix vgcfgbackup to properly check filename if template is used.
3314 configure aborts if lcov or genhtml are missing with --enable-profiling
3315 vgremove tries to remove lv snapshot first.
3316 Added function lv_remove_with_dependencies().
3317 Improve file descriptor leak detection to display likely culprit and filename.
3318 Change clustered mirror kernel module name from cmirror to dm-log-clustered.
3319 Avoid looping forever in _pv_analyze_mda_raw used by pvck.
3320 Change lvchange exit status to indicate if any part of the operation failed.
3321 Fix pvchange and pvremove to handle PVs without mdas.
3322 Refactor _text_pv_read and always return mda list if requested.
3323 Fix configure to work w/o readline unless --enable-readline used. (2.02.39)
3324 Remove is_lvm_partition template which has not yet been coded.
3325 Refactor pvcreate to separate parameter parsing from validation logic.
3326 Check for label_write() failure in _text_pv_write().
3327 Add pvcreate tests and update vgsplit tests to handle lvm1 and lvm2 metadata.
3328 Fix pvchange -M1 -u to preserve existing extent locations when there's a VG.
3329 Cease recognising snapshot-in-use percentages returned by early devt kernels.
3330 Add backward-compatible flags field to on-disk format_text metadata.
3331 Fix dmeventd monitoring libraries to link against liblvm2cmd again. (2.02.39)
3332
3333Version 2.02.39 - 27th June 2008
3334================================
3335 Enable readline by default if available.
3336 Update autoconf to 2008-01-16.
3337 Add $DISTCLEAN_DIRS to make.tmpl.in.
3338 Create coverage reports with --enable-profiling and make lcov or lcov-dated.
3339 Fix up cache for PVs without mdas after consistent VG metadata is processed.
3340 Update validation of safe mirror log type conversions in lvconvert.
3341 Fix lvconvert to disallow snapshot and mirror combinations.
3342 Fix reporting of LV fields alongside unallocated PV segments.
3343 Add --unquoted and --rows to reporting tools.
3344 Add and use uninitialized_var() macro to suppress invalid compiler warnings.
3345 Introduce enum for md minor sb version to suppress compiler warning.
3346 Avoid undefined return value after _memlock manipulation in lvm2_run.
3347 Avoid link failure if configured without --enable-cmdlib or --enable-readline.
3348 Make clvmd return at once if other nodes down in a gulm or openais cluster.
3349 Fix and improve readahead 'auto' calculation for stripe_size.
3350 Fix lvchange output for -r auto setting if auto is already set.
3351 Add test case for readahead.
3352 Avoid ambiguous use of identifier error_message_produced.
3353 Begin syncing configure.in for merge/unification with device-mapper.
3354 Fix add_mirror_images not to dereference uninitialized log_lv upon failure.
3355 Don't call openlog for every debug line output by clvmd.
3356 Add --force to lvextend and lvresize.
3357 Fix vgchange not to activate component mirror volumes directly.
3358 Fix test directory clean up in make distclean.
3359
3360Version 2.02.38 - 11th June 2008
3361================================
3362 Fix tracking of validity of PVs with no mdas in lvmcache.
3363 Fix return values for reporting commands when run with no PVs, LVs, or VGs.
3364 Add omitted unlock_vg() call when sigint_caught() during vg processing.
3365 Fix free_count when reading pool metadata.
3366 Fix segfault when using pvcreate on a device containing pool metadata.
3367 Fix segfault after _free_vginfo by remembering to remove vginfo from list.
3368 Tweak detection of invalid fid after changes to PVs in VG in _vg_read.
3369 Revert assuming precommitted metadata is live when activating (unnecessary).
3370 Drop cached metadata for disappearing VG in vgmerge.
3371 In script-processing mode, stop if any command fails.
3372 Warn if command exits with non-zero status code without a prior log_error.
3373 Check lv_count in vg_validate.
3374 Add --nameprefixes to reporting tools for field name prefix output format.
3375
3376Version 2.02.37 - 6th June 2008
3377===============================
3378 Make clvmd-cman use a hash rather than an array for node updown info.
3379 Correct config file line numbers in messages when parsing comments.
3380 Drop cached metadata when renaming a VG.
3381 Allow for vginfo changing during _vg_read.
3382 Decode numbers in clvmd debugging output.
3383 Add missing deactivation after activation failure in lvcreate -Zy.
3384 When activating, if precommitted metadata is still cached, assume it's live.
3385 When removing LV symlinks, skip any where the VG name is not determined.
3386 Drop metadata cache if update fails in vg_revert or vg_commit.
3387 Avoid spurious duplicate VG messages referring to VGs that are gone.
3388 Drop dev_name_confirmed error message to debug level.
3389 Fix setpriority error message to signed int.
3390 Temporarily disable dmeventd mirror monitoring during lvchange --resync.
3391 Refactor some vginfo manipulation code.
3392 Add assertions to trap deprecated P_ and V_ lock usage.
3393 Add missing mutex around clvmd lvmcache_drop_metadata library call.
3394 Fix uninitialised mutex in clvmd if all daemons are not running at startup.
3395 Avoid using DLM locks with LCK_CACHE type P_ lock requests.
3396 When asked to drop cached committed VG metadata, invalidate cached PV labels.
3397 Drop metadata cache before writing precommitted metadata instead of after.
3398 Don't touch /dev in vgrename if activation is disabled.
3399
3400Version 2.02.36 - 29th April 2008
3401=================================
3402 Fix fsadm.sh to work with older blockdev, blkid & readlink binaries.
3403 Fix lvresize to pass new size to fsadm when extending device.
3404 Remove unused struct in clvmd-openais, and use correct node count.
3405 Fix nodes list in clvmd-openais, and allow for broadcast messages.
3406 Exclude VG_GLOBAL from internal concurrent VG lock counter.
3407 Fix vgsplit internal counting of snapshot LVs.
3408 Fix vgmerge snapshot_count when source VG contains snapshots.
3409 Simplify clvmd-openais by using non-async saLckResourceLock.
3410 Fix internal LV counter when a snapshot is removed.
3411 Fix metadata corruption writing lvm1-formatted metadata with snapshots.
3412 Fix lvconvert -m0 allocatable space check.
3413
3414Version 2.02.35 - 15th April 2008
3415=================================
3416 Drop cached VG metadata before and after committing changes to it.
3417 Rename P_global to P_#global.
3418 Don't attempt remote metadata backups of non-clustered VGs. (2.02.29)
3419 Don't store fid in VG metadata cache to avoid clvmd segfault. (2.02.34)
3420 Update vgsplit tests to verify loosening of active LV restriction.
3421 Update vgsplit to only restrict split with active LVs involved in split.
3422 Add lv_is_active() to determine whether an lv is active.
3423
3424Version 2.02.34 - 10th April 2008
3425=================================
3426 Improve preferred_names lvm.conf example.
3427 Fix vgdisplay 'Cur LV' field to match lvdisplay output.
3428 Fix lv_count report field to exclude hidden LVs.
3429 Add vg_is_clustered() helper function.
3430 Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
3431 Update vgsplit tests for lvnames on the cmdline.
3432 Update vgsplit man page to reflect lvnames on the cmdline.
3433 Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
3434 Use clustered mirror log with pvmove in clustered VGs, if available.
3435 Fix some pvmove error status codes.
3436 Fix vgsplit error paths to release vg_to lock.
3437 Indicate whether or not VG is clustered in vgcreate log message.
3438 Mention default --clustered setting in vgcreate man page.
3439 Add config file overrides to clvmd when it reads the active LVs list.
3440 Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
3441 Add (empty) orphan VGs to lvmcache during initialisation.
3442 Fix orphan VG name used for format_pool.
3443 Create a fid for internal orphan VGs.
3444 Update lvmcache VG lock state for all locking types now.
3445 Fix output if overriding command_names on cmdline.
3446 Add detection of clustered mirror log capability.
3447 Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
3448 Add validation of LV name to pvmove -n.
3449 Make clvmd refresh the context correctly when lvm.conf is updated.
3450 Add some basic internal VG lock validation.
3451 Add per-command flags to control which commands use the VG metadata cache.
3452 Fix vgsplit locking of new VG (2.02.30).
3453 Avoid erroneous vgsplit error message for new VG. (2.02.29)
3454 Suppress duplicate message when lvresize fails because of invalid vgname.
3455 Cache VG metadata internally while VG lock is held.
3456 Fix redundant lvresize message if vg doesn't exist.
3457 Fix another allocation bug with clvmd and large node IDs.
3458 Add find_lv_in_lv_list() and find_pv_in_pv_list().
3459 Fix uninitialised variable in clvmd that could cause odd hangs.
3460 Add vgmerge tests.
3461 Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
3462 Add list_move() for moving elements from one list to another.
3463 Add 'is_reserved_lvname()' for identifying hidden LVs.
3464 Correct command name in lvmdiskscan man page.
3465 clvmd no longer crashes if it sees nodeids over 50.
3466 Fix potential deadlock in clvmd thread handling.
3467 Refactor text format initialisation into _init_text_import.
3468 Escape double quotes and backslashes in external metadata and config data.
3469 Add functions for escaping double quotes in strings.
3470 Rename count_chars_len to count_chars.
3471 Use return_0 in a couple more places.
3472 Correct a function name typo in _line_append error message.
3473 Include limits.h in clvmd so it compiles with newer headers.
3474 Add VirtIO disks (virtblk) to filters.
3475 Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. (2.02.30)
3476 Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30)
3477 Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
3478 Remove redundant non-NULL tests before calling free in clvmd.c.
3479 Avoid a compiler warning: make is_orphan's parameter const.
3480 Fix lvconvert detection of mirror conversion in progress. (2.02.30)
3481 Avoid automatic lvconvert polldaemon invocation when -R specified. (2.02.30)
3482 Fix 'pvs -a' to detect VGs of PVs without metadata areas.
3483 Divide up internal orphan volume group by format type.
3484 Update usage message for clvmd.
3485 Fix clvmd man page not to print <br> and clarified debug options.
3486 Fix lvresize to support /dev/mapper prefix in the LV name.
3487 Fix unfilled parameter passed to fsadm from lvresize.
3488 Update fsadm to call lvresize if the partition size differs (with option -l).
3489 Fix fsadm to support VG/LV names.
3490
3491Version 2.02.33 - 31st January 2008
3492===================================
3493 Fix mirror log name construction during lvconvert. (2.02.30)
3494 Make monitor_dev_for_events recurse through the stack of LVs.
3495 Clean up some more compiler warnings.
3496 Some whitespace tidy-ups.
3497 Use stack return macros throughout.
3498 Rely upon internally-cached PV labels while corresponding VG lock is held.
3499
3500Version 2.02.32 - 29th January 2008
3501===================================
3502 Fix two check_lv_segments error messages to show whole segment.
3503 Refactor mirror log attachment code.
3504 Fix internal metadata corruption in lvchange --resync. (2.02.30)
3505 Fix new parameter validation in vgsplit and test mode. (2.02.30)
3506 Remove redundant cnxman-socket.h file from clvmd directory.
3507 Fix pvs, vgs, lvs error exit status on some error paths.
3508
3509Version 2.02.31 - 19th January 2008
3510===================================
3511 Fix lvcreate --nosync not to wait for non-happening sync. (2.02.30)
3512 Add very_verbose lvconvert messages.
3513 Avoid readahead error message with default setting of lvcreate -M1. (2.02.29)
3514
3515Version 2.02.30 - 17th January 2008
3516===================================
3517 Set default readahead to twice maximium stripe size.
3518 Reinstate VG extent size and stripe size defaults (halved). (2.02.29)
3519 Add lists of stacked LV segments using each LV to the internal metadata.
3520 Change vgsplit -l (for unimplemented --list) into --maxlogicalvolumes.
3521 Fix process_all_pvs to detect non-orphans with no MDAs correctly.
3522 Don't use block_on_error with mirror targets version 1.12 and above.
3523 Update vgsplit to accept vgcreate options when new VG is destination.
3524 Update vgsplit to accept existing VG as destination.
3525 lvconvert waits for completion of initial sync by default.
3526 Refactor vgcreate for parameter validation and add tests.
3527 Add new convert_lv field to lvs output.
3528 Print warning when lvm tools are running as non-root.
3529 Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
3530 Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
3531 Fix a segfault if using pvs with --all argument. (2.02.29)
3532 Update --uuid argument description in man pages.
3533 Fix vgreduce PV list processing not to process every PV in the VG. (2.02.29)
3534 Extend lvconvert to use polldaemon.
3535 Add support for stacked mirrors.
3536 Major restructuring of pvmove and lvconvert layer manipulation code.
3537 Replace tools/fsadm with scripts/fsadm.sh.
3538 Append fields to report/pvsegs_cols_verbose.
3539 Permit LV segment fields with PV segment reports.
3540 Add seg_start_pe and seg_pe_ranges to reports.
3541
3542Version 2.02.29 - 5th December 2007
3543===================================
3544 Make clvmd backup vg metadata on remote nodes.
3545 Refactor pvmove allocation code.
3546 Decode cluster locking state in log message.
3547 Change file locking state messages from debug to very verbose.
3548 Fix --addtag to drop @ prefix from name.
3549 Stop clvmd going haywire if a pre_function fails.
3550 Convert some vg_reads into vg_lock_and_reads.
3551 Avoid nested vg_reads when processing PVs in VGs and fix associated locking.
3552 Accept sizes with --readahead argument.
3553 Store size arguments as sectors internally.
3554 Attempt to remove incomplete LVs with lvcreate zeroing/activation problems.
3555 Add read_ahead activation code.
3556 Add activation/readahead configuration option and FMT_RESTRICTED_READAHEAD.
3557 Extend readahead arg to accept "auto" and "none".
3558 Add lv_read_ahead and lv_kernel_read_ahead fields to reports and lvdisplay.
3559 Prevent lvconvert -s from using same LV as origin and snapshot.
3560 Fix human-readable output of odd numbers of sectors.
3561 Add pv_mda_free and vg_mda_free fields to reports for raw text format.
3562 Add LVM2 version to 'Generated by' comment in metadata.
3563 Show 'not usable' space when PV is too large for device in pvdisplay.
3564 Ignore and fix up any excessive device size found in metadata.
3565 Fix error message when fixing up PV size in lvm2 metadata (2.02.11).
3566 Fix orphan-related locking in pvdisplay and pvs.
3567 Fix missing VG unlocks in some pvchange error paths.
3568 Add some missing validation of VG names.
3569 Rename validate_vg_name() to validate_new_vg_name().
3570 Change orphan lock to VG_ORPHANS.
3571 Change format1 to use ORPHAN as orphan VG name.
3572 Convert pvchange, pvdisplay, pvscan to use is_orphan()
3573 Add is_orphan_vg() and change all hard-coded checks to use it.
3574 Detect md superblocks version 1.0, 1.1 and 1.2.
3575 Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths.
3576 Add pv_dev_name() to access PV device name.
3577 Add const attributes to pv accessor functions.
3578 Refactor vg_add_snapshot() and lv_create_empty().
3579 Handle new sysfs subsystem/block/devices directory structure.
3580 Run test with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
3581 Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
3582 Fix underquotations in lvm_dump.sh.
3583 Refactor lvcreate stripe and mirror parameter validation.
3584 Print --help output to stdout, not stderr.
3585 After a cmdline processing error, don't print help text but suggest --help.
3586 Add %PVS extents option to lvresize, lvextend, and lvcreate.
3587 Add 'make check' to run tests in new subdirectory 'test'.
3588 Moved the obsolete test subdirectory to old-tests.
3589 Cope with relative paths in configure --with-dmdir.
3590 Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
3591 Fix strdup memory leak in str_list_dup().
3592 Link with -lpthread when static SELinux libraries require that.
3593 Detect command line PE values that exceed their 32-bit range.
3594 Include strerror string in dev_open_flags' stat failure message.
3595 Move guts of pvresize into library.
3596 Avoid error when --corelog is provided without --mirrorlog. (2.02.28)
3597 Correct --mirrorlog argument name in man pages (not --log).
3598 Clear MIRROR_NOTSYNCED LV flag when converting from mirror to linear.
3599 Modify lvremove to prompt for removal if LV active on other cluster nodes.
3600 Add '-f' to vgremove to force removal of VG even if LVs exist.
3601
3602Version 2.02.28 - 24th August 2007
3603==================================
3604 Fix clvmd logging so you can get lvm-level debugging out of it.
3605 Introduce VG_GLOBAL lock type for vgscan/pvscan to trigger clvmd -R.
3606 Change locking_flags from int to uint32_t.
3607 Fix clvmd -R, so it fully refreshes the caches.
3608 Change lvconvert_mirrors to use mirror segtype not striped.
3609 Fix lvconvert_mirrors detection of number of existing mirrors.
3610 Clean up numerous compiler warnings that appeared in recent releases.
3611 Remove several unused parameters from _allocate().
3612 Only permit --force, --verbose and --debug arguments to be repeated.
3613 Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
3614 Move guts of vgremove and lvremove into library, including yes_no_prompt.
3615 Allow clvmd debug to be turned on in a running daemon using clvmd -d [-C].
3616 Update to use autoconf 2.61, while still supporting 2.57.
3617 Add more cluster info to lvmdump.
3618 Add further const attributes throughout.
3619 Add support for renaming mirrored LVs.
3620 Factor out core of lvrename() to library function.
3621 Add --mirrorlog argument to specify log type for mirrors.
3622 Don't attempt to monitor devices if their creation failed in _lv_activate.
3623 Don't leak a file descriptor in fcntl_lock_file() when fcntl fails.
3624 Replace create_dir with dm_create_dir.
3625 Detect stream write failure reliably with lvm_fclose using dm_fclose.
3626 Fix clvmd if compiled with gulm support. (2.02.26)
3627 Fix lvdisplay man page to say LV size is reported in sectors, not KB.
3628 Add vg_lock_and_read() external library function.
3629 Fix loading of persistent cache if cache_dir is used. (2.02.23)
3630 Reduce _compare_paths lstat error message from log_error to log_very_verbose.
3631 Create util.h with last_path_component replacing strdup + basename.
3632 Use gcc's printf attribute wherever possible.
3633 In _line_append, use "sizeof buf - 1" rather than equivalent "4095".
3634 Introduce is_same_inode macro, now including a comparison of st_dev.
3635 Don't leak a file descriptor in _lock_file() when flock fails.
3636 Add SUN's LDOM virtual block device (vdisk) and ps3disk to filters.
3637 Split metadata-external.h out from metadata.h for the tools to use.
3638
3639Version 2.02.27 - 17th July 2007
3640================================
3641 Fix snapshot cow area deactivation if origin is not active. (2.02.13)
3642 Fix configure libdevmapper.h check when --with-dmdir is used.
3643 Turn _add_pv_to_vg() into external library function add_pv_to_vg().
3644 Add pv_by_path() external library function.
3645 Tidy clvmd-openais of redundant bits, and improve an error report.
3646 Cope with find_seg_by_le() failure in check_lv_segments().
3647 Call dev_iter_destroy() if _process_all_devs() is interrupted by sigint.
3648 Add vg_mda_count and pv_mda_count columns to reports.
3649 Fix dumpconfig to use log_print instead of stdout directly.
3650 Remove unused parameter 'fid' from _add_pv_to_vg.
3651 Add kernel and device-mapper targets versions to lvmdump.
3652 Replace BSD (r)index with C89 str(r)chr.
3653 Handle vgsplit of an entire VG as a vgrename.
3654 Reinitialise internal lvmdiskscan variables when called repeatedly.
3655 Fix missing lvm_shell symbol in lvm2cmd library. (2.02.23)
3656 Add vg_status function and clean up vg->status in tools directory.
3657 Add --ignoremonitoring to disable all dmeventd interaction.
3658 Remove get_ prefix from get_pv_* functions.
3659 clvmd-openais now uses cpg_local_get() to get nodeid, rather than Clm.
3660 Print warnings to stderr instead of stdout.
3661
3662Version 2.02.26 - 15th June 2007
3663================================
3664 Update vgcfgrestore man page.
3665 Allow keyboard interrupt during user prompts when appropriate.
3666 Remove unused clvmd system-lv code.
3667 Replace many physical_volume struct dereferences with new get_pv_* functions.
3668 Suppress a benign compile-time warning.
3669 Convert find_pv_in_vg_by_uuid and pv_create to use PV handles.
3670 Add wrappers to some functions in preparation for external LVM library.
3671 Add -f to vgcfgrestore to list metadata backup files.
3672 Add vg_check_status to consolidate vg status checks and error messages.
3673 Add pvdisplay --maps implementation.
3674 Remove unsupported LVM1 options from vgcfgrestore man page.
3675 Update vgcfgrestore man page to show mandatory VG name.
3676 Update vgrename man page to include UUID and be consistent with lvrename.
3677 Add (experimental) OpenAIS support to clvmd.
3678 Fix deactivation code to follow dependencies and remove symlinks.
3679 Fix and clarify vgsplit error messages.
3680 Fix a segfault in device_is_usable() if a device has no table.
3681 Add some more debug messages to clvmd startup.
3682 Misc clvmd cleanups.
3683
3684Version 2.02.25 - 27th April 2007
3685=================================
3686 Fix get_config_uint64() to read a 64-bit value not a 32-bit one.
3687 Add -Wformat-security and change one fprintf() to fputs().
3688 Move regex functions into libdevmapper.
3689 Change some #include lines to search only standard system directories.
3690 Add devices/preferred_names config regex list for displayed device names.
3691 Free a temporary dir string in fcntl_lock_file() after use.
3692 Fix a dm_pool_destroy() in matcher_create().
3693 Introduce goto_bad macro.
3694 Fix warnings on x86_64 involving ptrdiff_t in log_error messages.
3695 Update pvck to include text metadata area and record detection.
3696 Add support functions for token counting in config file extracts.
3697 Update pvck to read labels on disk, with --labelsector parameter.
3698 Add count_chars and count_chars_len functions.
3699 Add /sys/block listings to lvm_dump.sh.
3700 Make lvm_dump.sh list /dev recursively.
3701 Fix thread race in clvmd.
3702 Add scan_sector param to label_read and _find_labeller.
3703 Make clvmd cope with quorum devices.
3704 Add extra internal error checking to clvmd.
3705 Add dev_read_circular.
3706 Add pvck command stub.
3707 Update lists of attribute characters in man pages.
3708 Change cling alloc policy attribute character from 'C' to l'.
3709 Fix creation and conversion of mirrors with tags.
3710 Fix vgsplit for lvm1 format (set and validate VG name in PVs metadata).
3711 Split metadata areas in vgsplit properly.
3712
3713Version 2.02.24 - 19th March 2007
3714=================================
3715 Fix processing of exit status in init scripts
3716 Fix vgremove to require at least one vg argument.
3717 Fix reading of striped LVs in LVM1 format.
3718 Flag nolocking as clustered so clvmd startup sees clustered LVs. (2.02.10)
3719 Add a few missing pieces of vgname command line validation.
3720 Support the /dev/mapper prefix on most command lines.
3721
3722Version 2.02.23 - 8th March 2007
3723================================
3724 Fix vgrename active LV check to ignore differing vgids.
3725 Remove no-longer-used uuid_out parameter from activation info functions.
3726 Fix two more segfaults if an empty config file section encountered.
3727 Move .cache file into a new /etc/lvm/cache directory by default.
3728 Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
3729 Create directory in fcntl_lock_file() if required.
3730 Exclude readline support from lvm.static.
3731 Fix a leak in a reporting error path (2.02.19).
3732
3733Version 2.02.22 - 13th February 2007
3734====================================
3735 Correct -b and -P on a couple of man pages.
3736 Add global/units to example.conf.
3737 Fix loading of segment_libraries.
3738 If a PV reappears after it was removed from its VG, make it an orphan.
3739 Don't update metadata automatically if VGIDs don't match.
3740 Fix some vgreduce --removemissing command line validation.
3741
3742Version 2.02.21 - 30th January 2007
3743===================================
3744 Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
3745 Fix vgsplit to handle mirrors.
3746 Reorder fields in reporting field definitions.
3747 Fix vgs to treat args as VGs even when PV fields are displayed.
3748 Fix md signature check to handle both endiannesses.
3749
3750Version 2.02.20 - 25th January 2007
3751===================================
3752 dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
3753 Add devices/ignore_suspended_devices to ignore suspended dm devices.
3754 Add some missing close() and fclose() return code checks.
3755 Fix exit statuses of reporting tools (2.02.19).
3756 Add init script for dmeventd monitoring.
3757 lvm.static no longer interacts with dmeventd unless explicitly asked to.
3758 Add field definitions to report help text.
3759 Remove unnecessary cmd arg from target_*monitor_events().
3760 Add private variable to dmeventd shared library interface.
3761 Long-lived processes write out persistent dev cache in refresh_toolcontext().
3762 Fix refresh_toolcontext() always to wipe persistent device filter cache.
3763 Add is_long_lived to toolcontext.
3764 Add --clustered to man pages.
3765 Streamline dm_report_field_* interface.
3766 Change remaining dmeventd terminology 'register' to 'monitor'.
3767 Update reporting man pages.
3768 No longer necessary to specify alignment type for report fields.
3769
3770Version 2.02.19 - 17th January 2007
3771===================================
3772 Fix a segfault if an empty config file section encountered.
3773 Move basic reporting functions into libdevmapper.
3774 Fix partition table processing after sparc changes (2.02.16).
3775 Fix cmdline PE range processing segfault (2.02.13).
3776 Some libdevmapper-event interface changes.
3777 Report dmeventd mirror monitoring status.
3778 Fix dmeventd mirror status line processing.
3779
3780Version 2.02.18 - 11th January 2007
3781===================================
3782 Revised libdevmapper-event interface for dmeventd.
3783 Remove dmeventd mirror status line word limit.
3784 Use CFLAGS when linking so mixed sparc builds can supply -m64.
3785 Prevent permission changes on active mirrors.
3786 Print warning instead of error message if lvconvert cannot zero volume.
3787 Add snapshot options to lvconvert man page.
3788 dumpconfig accepts a list of configuration variables to display.
3789 Change dumpconfig to use --file to redirect output to a file.
3790 Avoid vgreduce error when mirror code removes the log LV.
3791 Remove 3 redundant AC_MSG_RESULTs from configure.in.
3792 Free memory in _raw_read_mda_header() error paths.
3793 Fix ambiguous vgsplit error message for split LV.
3794 Fix lvextend man page typo.
3795 Add configure --with-dmdir to compile against a device-mapper source tree.
3796 Use no flush suspending for mirrors.
3797 Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
3798 Fix create mirror with name longer than 22 chars.
3799 Fix some activate.c prototypes when compiled without devmapper.
3800 Fix dmeventd mirror to cope if monitored device disappears.
3801
3802Version 2.02.17 - 14th December 2006
3803====================================
3804 Add missing pvremove error message when device doesn't exist.
3805 When lvconvert allocates a mirror log, respect parallel area constraints.
3806 Use loop to iterate through the now-ordered policy list in _allocate().
3807 Check for failure to allocate just the mirror log.
3808 Introduce calc_area_multiple().
3809 Support mirror log allocation when there is only one PV: area_count now 0.
3810 Fix detection of smallest area in _alloc_parallel_area() for cling policy.
3811 Add manpage entry for clvmd -T
3812 Fix gulm operation of clvmd, including a hang when doing lvchange -aey
3813 Fix hang in clvmd if a pre-command failed.
3814
3815Version 2.02.16 - 1st December 2006
3816===================================
3817 Fix VG clustered read locks to use PR not CR.
3818 Adjust some alignments for ia64/sparc.
3819 Fix mirror segment removal to use temporary error segment.
3820 Always compile debug logging into clvmd.
3821 Add startup timeout to RHEL4 clvmd startup script.
3822 Add -T (startup timeout) switch to clvmd.
3823 Improve lvm_dump.sh robustness.
3824 Update lvm2create_initrd to support gentoo.
3825
3826Version 2.02.15 - 21st November 2006
3827====================================
3828 Fix clvmd_init_rhel4 line truncation (2.02.14).
3829 Install lvmdump by default.
3830 Fix check for snapshot module when activating snapshot.
3831 Fix pvremove error path for case when PV is in use.
3832 Warn if certain duplicate config file entries are seen.
3833 Enhance lvm_dump.sh for sysreport integration and add man page.
3834 Fix --autobackup argument which could never disable backups.
3835 Fix a label_verify error path.
3836
3837Version 2.02.14 - 10th November 2006
3838====================================
3839 Fix adjusted_mirror_region_size() to handle 64-bit size.
3840 Add some missing bounds checks on 32-bit extent counters.
3841 Add Petabyte and Exabyte support.
3842 Fix lvcreate error message when 0 extents requested.
3843 lvremove man page: volumes must be cluster inactive before being removed.
3844 Protect .cache manipulations with fcntl locking.
3845 Change .cache timestamp comparisons to use ctime.
3846 Fix mirror log LV writing to set all bits in whole LV.
3847 Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
3848 Fix high-level free space check for partial allocations.
3849
3850Version 2.02.13 - 27th October 2006
3851===================================
3852 Add couple of missing files to tools/Makefile CLEAN_TARGETS.
3853 When adding snapshot leave cow LV mapped device active after zeroing.
3854 Fix a clvmd debug message.
3855 Add dev_flush() to set_lv().
3856 Add lvchange --resync.
3857 Perform high-level free space check before each allocation attempt.
3858 Don't allow a node to remove an LV that's exclusively active on anther node.
3859 Cope if same PV is included more than once in cmdline PE range list.
3860 Set PV size to current device size if it is found to be zero.
3861 Add segment parameter to target_present functions.
3862
3863Version 2.02.12 - 16th October 2006
3864===================================
3865 Fix pvdisplay to use vg_read() for non-orphans.
3866 Fall back to internal locking if external locking lib is missing or fails.
3867 Retain activation state after changing LV minor number with --force.
3868 Propagate clustered flag in vgsplit and require resizeable flag.
3869
3870Version 2.02.11 - 12th October 2006
3871===================================
3872 Add clvmd function to return the cluster name. not used by LVM yet.
3873 Add cling allocation policy.
3874 Change _check_contiguous() to use _for_each_pv().
3875 Extend _for_each_pv() to allow termination without error.
3876 Abstract _is_contiguous().
3877 Remove duplicated pv arg from _check_contiguous().
3878 Accept regionsize with lvconvert.
3879 Add report columns with underscore before field names ending 'size'.
3880 Correct regionsize default on lvcreate man page (MB).
3881 Fix clvmd bug that could cause it to die when a node with a long name crashed.
3882 Add device size to text metadata.
3883 Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
3884 Fix _for_each_pv() for mirror with core log.
3885 Add lvm_dump.sh script to create a tarball of debugging info from a system.
3886 Capture error messages in clvmd and pass them back to the user.
3887 Remove unused #defines from filter-md.c.
3888 Make clvmd restart init script wait until clvmd has died before starting it.
3889 Add -R to clvmd which tells running clvmds to reload their device cache.
3890 Add LV column to reports listing kernel modules needed for activation.
3891 Show available fields if report given invalid field. (e.g. lvs -o list)
3892 Add timestamp functions with --disable-realtime configure option.
3893 Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
3894 Fix two potential NULL pointer derefs in error cases in vg_read().
3895 Separate --enable-cluster from locking lib options in lvmconf.sh.
3896 Add a missing comma in lvcreate man page.
3897
3898Version 2.02.10 - 19th September 2006
3899=====================================
3900 Fix lvconvert mirror change case detection logic.
3901 Fix mirror log detachment so it correctly becomes a standalone LV.
3902 Extend _check_contiguous() to detect single-area LVs.
3903 Include mirror log (untested) in _for_each_pv() processing.
3904 Use MIRROR_LOG_SIZE constant.
3905 Remove struct seg_pvs from _for_each_pv() to generalise.
3906 Avoid adding duplicates to list of parallel PVs to avoid.
3907 Fix several incorrect comparisons in parallel area avoidance code.
3908 Fix segment lengths when flattening existing parallel areas.
3909 Log existing parallel areas prior to allocation.
3910 Fix mirror log creation when activation disabled.
3911 Don't attempt automatic recovery without proper locking.
3912 When using local file locking, skip clustered VGs.
3913 Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
3914 lvm.static uses built-in cluster locking instead of external locking.
3915 Don't attempt to load shared libraries if built statically.
3916 Change default locking_lib to liblvm2clusterlock.so.
3917 Add skip_dev_dir() to process command line VGs.
3918 Stop clvmd complaining about nodes that have left the cluster.
3919 Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
3920 Add lvconvert man page.
3921 Add mirror options to man pages.
3922 Prevent mirror renames.
3923 Move CMDLIB code into separate file and record whether static build.
3924
3925Version 2.02.09 - 17th August 2006
3926==================================
3927 Fix PE_ALIGN for pagesize over 32KB.
3928 Separate out LVM1_PE_ALIGN and pe_align().
3929 Add lvm_getpagesize wrapper.
3930 Add --maxphysicalvolumes to vgchange.
3931
3932Version 2.02.08 - 15th August 2006
3933==================================
3934 Add checks for duplicate LV name, lvid and PV id before writing metadata.
3935 Report all sanity check failures, not just the first.
3936 Fix missing lockfs on first snapshot creation.
3937 Add unreliable --trustcache option to reporting commands.
3938 Fix locking for mimage removal.
3939 Fix clvmd_init_rhel4 'status' exit code.
3940
3941Version 2.02.07 - 17th July 2006
3942================================
3943 Fix activation logic in lvchange --persistent.
3944 Don't ignore persistent minor numbers when activating.
3945 Use RTLD_GLOBAL when loading shared libraries.
3946 Add some forgotten memlock checks to _vg_read to protect against full scans.
3947 Add mutex to dmeventd_mirror to avoid concurrent execution.
3948 Fix vgreduce --removemissing to return success if VG is already consistent.
3949 Fix return code if VG specified on command line is not found.
3950 Fix PV tools to include orphaned PVs in default output again.
3951 Fixed unaligned access when using clvm.
3952 Fix an extra dev_close in a label_read error path.
3953 Append patches to commit emails.
3954 Fix target_register_events args.
3955 Prevent snapshots of mirrors.
3956 Add DISTCLEAN_TARGETS to make template for configure.h.
3957 More fixes to error paths.
3958 Fix lvcreate corelog validation.
3959 Add --config for overriding most config file settings from cmdline.
3960 Quote arguments when printing command line.
3961 Remove linefeed from 'initialising logging' message.
3962 Add 'Completed' debug message.
3963 Don't attempt library exit after reloading config files.
3964 Always compile with libdevmapper, even if device-mapper is disabled.
3965
3966Version 2.02.06 - 12th May 2006
3967===============================
3968 Propagate --monitor around cluster.
3969 Add --monitor to vgcreate and lvcreate to control dmeventd registration.
3970 Filter LCK_NONBLOCK in clvmd lock_vg.
3971 Add --nosync to lvcreate with LV flag NOTSYNCED.
3972 Use mirror's uuid for a core log.
3973 Add mirror log fault-handling policy.
3974 Improve mirror warning messages and tidy dmeventd syslog output.
3975 Propagate nosync flag around cluster.
3976 Allow vgreduce to handle mirror log failures.
3977 Add --corelog to lvcreate and lvconvert.
3978 Create a log header for replacement in-sync mirror log.
3979 Use set_lv() and dev_set() to wipe sections of devices.
3980 Add mirror_in_sync() flag to avoid unnecessary resync on activation.
3981 Add mirror_library description to example.conf.
3982 Fix uuid_from_num() buffer overrun.
3983 Make SIZE_SHORT the default for display_size().
3984 Fix some memory leaks in error paths found by coverity.
3985 Use C99 struct initialisers.
3986 Move DEFS into configure.h.
3987 Clean-ups to remove miscellaneous compiler warnings.
3988 Improve stripe size validation.
3989 Increase maximum stripe size limit to physical extent size for lvm2 metadata.
3990 Fix activation code to check for pre-existing mirror logs.
3991 Tighten region size validation.
3992 Ignore empty strings in config files.
3993 Require non-zero regionsize and document parameter on lvcreate man page.
3994 Invalidate cache if composition of VG changed externally.
3995
3996Version 2.02.05 - 21st April 2006
3997=================================
3998 Fix vgid string termination in recent cache code.
3999
4000Version 2.02.04 - 19th April 2006
4001=================================
4002 Check for libsepol.
4003 Add some cflow & scope support.
4004 Separate out DEFS from CFLAGS.
4005 Remove inlines and use unique function names.
4006
4007Version 2.02.03 - 14th April 2006
4008=================================
4009 vgrename accepts vgid and exported VG.
4010 Add --partial to pvs.
4011 When choosing between identically-named VGs, also consider creation_host.
4012 Provide total log suppression with 2.
4013 Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
4014 Add vgid to struct physical_volume and pass with vg_name to some functions.
4015 If two or more VGs are found with the same name, use one that is not exported.
4016 Whenever vgname is captured, also capture vgid and whether exported.
4017 Remove an incorrect unlock_vg() from process_each_lv().
4018 Update extent size information in vgchange and vgcreate man pages.
4019 Introduce origin_from_cow() and lv_is_visible().
4020 pvremove without -f now fails if there's no PV label.
4021 Support lvconvert -s.
4022 Suppress locking library load failure message if --ignorelockingfailure.
4023 Propagate partial mode around cluster.
4024 Fix archive file expiration.
4025 Fix dmeventd build.
4026 clvmd now uses libcman rather than cman ioctls.
4027 clvmd will allow new cman to shutdown on request.
4028
4029Version 2.02.02 - 7th February 2006
4030===================================
4031 Add %.so: %.a make template rule.
4032 Switchover library building to use LIB_SUFFIX.
4033 Only do lockfs filesystem sync when suspending snapshots.
4034 Always print warning if activation is disabled.
4035 vgreduce removes mirror images.
4036 Add --mirrorsonly to vgreduce.
4037 vgreduce replaces active LVs with error segment before removing them.
4038 Set block_on_error parameter if available.
4039 Add target_version.
4040 Add details to format1 'Invalid LV in extent map' error message.
4041 Fix lvscan snapshot full display.
4042 Bring lvdisplay man page example into line.
4043 Add mirror dmeventd library.
4044 Add some activation logic to remove_mirror_images().
4045 lvconvert can remove specified PVs from a mirror.
4046 lvconvert turns an existing LV into a mirror.
4047 Allow signed mirrors arguments.
4048 Move create_mirror_log() into toollib.
4049 Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
4050 Fix lv_empty.
4051
4052Version 2.02.01 - 23rd November 2005
4053====================================
4054 Fix lvdisplay cmdline to accept snapshots.
4055 Fix open RO->RW promotion.
4056 Fix missing vg_revert in lvcreate error path.
4057
4058Version 2.02.00 - 10th November 2005
4059====================================
4060 Extend allocation areas to avoid overflow with contiguous with other PVs.
4061 Stop lvcreate attempting to wipe zero or error segments.
4062 Added new lvs table attributes.
4063 Separated out activation preload.
4064 Moved activation functions into libdevmapper.
4065 Fixed build_dm_name.
4066 Add return macros.
4067 Added xen xvd devices.
4068 Clear up precommitted metadata better.
4069 A pvresize implementation.
4070 Fix contiguous allocation when there are no preceding segments.
4071 Add mirror_seg pointer to lv_segment struct.
4072 Only keep a device open if it's known to belong to a locked VG.
4073 Fix lvdisplay to show all mirror destinations.
4074 Replacement suspend code using libdevmapper dependency tree.
4075 Add DEFS to make.tmpl.
4076 Use dm_is_dm_major instead of local copy.
4077 Allow mapped devices to be used as PVs.
4078 Move set_selinux_context into libdevmapper.
4079 Fix automatic text metadata buffer expansion (using macro).
4080 Cache formatted text metadata buffer between metadata area writes.
4081 Add pe_start field to pvs.
4082 Add 'LVM-' prefix to uuids.
4083 Split lv_segment_area from lv_segment to permit extension.
4084 Replacement deactivation code using libdevmapper dependency tree.
4085 Simplify dev_manager_info().
4086 Attempt to load missing targets using modprobe.
4087 Add -a to lvscan.
4088 Move mknodes into libdevmapper.
4089 Move bitset, hash, pool and dbg_malloc into libdevmapper.
4090
4091Version 2.01.15 - 16th October 2005
4092===================================
4093 Refuse to run pvcreate/pvremove on devices we can't open exclusively.
4094 Use ORPHAN lock definition throughout.
4095 Validate chunksize in lvcreate.
4096 Reduce chunksize limit to 512k.
4097 Fix chunksize field in reports.
4098 Don't hide snapshots from default 'lvs' output.
4099 Add is_dm_major() for use in duplicate device detection in lvmcache_add().
4100 Really switch device number in lvmcache when it says it is doing so.
4101 Option for bitset memory allocation using malloc as well as pool.
4102 Don't assume exactly two mirrors when parsing mirror status.
4103 Suppress fsync() error message on filesystems that don't support it.
4104 Fix yes_no_prompt() error handling.
4105 Add lvm.conf comment warning against multiple filter lines.
4106 Tidy lvmconf.sh.
4107 Add format1 dev_write debug messages.
4108 Add clustered VG attribute to report.
4109 Move lvconvert parameters into struct lvconvert_params.
4110 Add clustered VG flag to LV lock requests.
4111 Change LV locking macros to take lv instead of lvid.
4112 Prepend 'cluster' activation parameter to mirror log when appropriate.
4113 Pass exclusive flag to lv_activate and on to target activation code.
4114 Prevent snapshot creation in a clustered VG for now.
4115 Factor out adjusted_mirror_region_size() and generate_log_name_format().
4116 Move compose_log_line() into mirror directory.
4117 Factor out _get_library_path().
4118 Don't kill idling clvmd threads.
4119 clvmd no longer takes out locks for non-clustered LVs.
4120 Recognise ATA over Ethernet (aoe) devices.
4121
4122Version 2.01.14 - 4th August 2005
4123=================================
4124 Fix lvconvert PV parameter in help string.
4125 Prevent snapshots getting activated in a clustered VG.
4126 Separate out _build_dev_string.
4127 Move zero_lv to toollib.
4128 Fix pool format handler to work with pv segment code.
4129
4130Version 2.01.13 - 13th July 2005
4131================================
4132 Fix pvmove segment splitting.
4133 Abstract vg_validate.
4134 Only make one attempt at contiguous allocation.
4135 Fix lvm1 format metadata read.
4136 Fix lvm1 format non-mirror lvcreate.
4137
4138Version 2.01.12 - 14th June 2005
4139================================
4140 Various allocation-related pvmove fixes.
4141 Log an error if clvmd can't resolve a host name got from CCS.
4142 Fix potential spin loop in clvmd.
4143
4144Version 2.01.11 - 13th June 2005
4145================================
4146 Added lvmconf.sh.
4147 Use matchpathcon mode parameter.
4148 Don't defer closing dead FDs in clvmd.
4149 Remove hard-coded 64k text metadata writing restriction.
4150 Make VG name restrictions consistent.
4151 Introduce lvconvert. So far only removes mirror images.
4152 Allow mirror images to be resized.
4153 Allow mirror images to have more than one segment.
4154 Centralise restrictions on LV names.
4155 Always insert an intermediate layer for mirrors.
4156 Suppress hidden LVs from reports unless --all is given.
4157 Use square brackets for hidden LVs in reports.
4158 Allow the creation of mirrors with contiguous extents.
4159 Always perform sanity checks against metadata before committing it to disk.
4160 Split lv_extend into two steps: choosing extents + allocation to LV(s).
4161 Add mirror log region size to metadata.
4162 Use list_iterate_items throughout and add list*back macros.
4163 Introduce seg_ macros to access areas.
4164 Add segtype_is_ macros.
4165 Support tiny metadata areas for pool conversions.
4166 Mirror activation handles disk log as well as core.
4167 Activation code recognises mirror log dependency.
4168 Add mirror_log and regionsize fields to report.
4169 Fix non-orphan pvchange -u.
4170 Fix vgmerge to handle duplicate LVIDs.
4171 Move archiver code from tools into library.
4172 vgscan/change/display/vgs automatically create metadata backups if needed.
4173 Merge cloned allocation functions.
4174 Fix contiguous allocation policy with linear.
4175 Cope with missing format1 PVs again.
4176 Remove lists of free PV segments.
4177 Simplify pv_maps code and remove slow bitset algorithm.
4178 Red-Hat-ify the clvmd rhel4 initscript.
4179 %Zu->%zu
4180 Fix loopfiles alias alloc & mem debugging.
4181 Un-inline dbg_strdup.
4182 lv_reduce tidying.
4183 Remove some unnecessary parameters.
4184 Introduce seg_is macros.
4185
4186Version 2.01.10 - 3rd May 2005
4187==============================
4188 Don't create backup and archive dirs till needed.
4189 Reinstate full PV size when removing from VG.
4190 Support loopfiles for testing.
4191 Tidy lv_segment interface.
4192 pv_segment support.
4193 vgchange --physicalextentsize
4194 Internal snapshot restructuring.
4195 Remove unused internal non-persistent snapshot option.
4196 Allow offline extension of snapshot volumes.
4197 Move from 2-step to 3-step on-disk metadata commit.
4198 Scan ramdisks too and allow non-O_DIRECT fallback.
4199 Annotate, tidy and extend list.h.
4200 Alignment tidying.
4201 Make clvmd work around some "bugs" in gulm's node state notifications.
4202 Tidy clvmd's SIGHUP handler
4203
4204Version 2.01.09 - 4th April 2005
4205================================
4206 Add --ignorelockingfailure to vgmknodes.
4207 clvmd: Don't allow user operations to start until the lvm thread is fully up.
4208 clvmd-gulm: set KEEPALIVE on sockets.
4209
4210Version 2.01.08 - 22nd March 2005
4211=================================
4212 Add clustered attribute so vgchange can identify clustered VGs w/o locking.
4213 Improve detection of external changes affecting internal cache.
4214 Add 'already in device cache' debug message.
4215 Add -a to pvdisplay -C.
4216 Avoid rmdir opendir error messsages when dir was already removed.
4217 Tighten signal handlers.
4218 Avoid some compiler warnings.
4219 Additional rename failure error message.
4220 read/write may be macros.
4221 clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
4222
4223Version 2.01.07 - 8th March 2005
4224================================
4225 Cope with new devices appearing by rescanning /dev if a uuid can't be found.
4226 Remove DESTDIR from LVM_SHARED_PATH.
4227 clvmd fixes: make FDs close-on-exec
4228 gulm unlocks VG & orphan locks at startup in case they are stale
4229 gulm now unlocks VG & orphan locks if client dies.
4230
4231Version 2.01.06 - 1st March 2005
4232================================
4233 Suppress 'open failed' error messages during scanning.
4234 Option to suppress warnings of file descriptors left open.
4235 Fix default value of metadatacopies in documentation (2->1).
4236 Fix clvmd-gulm locking.
4237 ./configure --enable-debug now enables debugging code in clvmd.
4238 Fix clvmd-gulm node up/down code so it actually works.
4239 clvmd-gulm now releases locks when shut down.
4240
4241Version 2.01.05 - 18th February 2005
4242====================================
4243 Static binary invokes dynamic binary if appropriate.
4244 Make clvmd config check a little more tolerant.
4245 gulm clvmd can now cope with >1 message arriving in a TCP message.
4246
4247Version 2.01.04 - 9th February 2005
4248===================================
4249 Add fixed offset to imported pool minor numbers.
4250 Update binary pathnames in clvmd_init_rhel4.
4251 lvm2cmd.so should skip the check for open fds.
4252 Remove unused -f from pvmove.
4253 Gulm clvmd doesn't report "connection refused" errors.
4254 clvmd does a basic config file sanity check at startup.
4255 Fix potential thread shutdown race in clvmd.
4256
4257Version 2.01.03 - 1st February 2005
4258===================================
4259 More 64-bit display/report fixes.
4260 More informative startup mesg if can't create /etc/lvm.
4261 Fix snapshot device size bug (since 2.01.01).
4262 clvmd announces startup and cluster connection in syslog.
4263 Gulm clvmd doesn't hang trying to talk to a rebooted node.
4264 Gulm clvmd doesn't print cman error on startup.
4265
4266Version 2.01.02 - 21st January 2005
4267===================================
4268 Update clvmd_init_rhel4: use lvm.static and don't load dlm.
4269 Fix some size_t printing.
4270 Fix 64 bit xlate consts.
4271 Split out pool sptype_names to avoid unused const.
4272 Always fail if random id generation fails.
4273 Recognise gnbd devices.
4274 Fix clvmd startup bug introduced in cman/gulm amalgamation.
4275 Improve reporting of node-specific locking errors.
4276
4277Version 2.01.01 - 19th January 2005
4278===================================
4279 Fix clvmd lv_info_by_lvid open_count.
4280 Store snapshot and origin sizes separately.
4281 Update vgcreate man page.
4282
4283Version 2.01.00 - 17th January 2005
4284===================================
4285 Fix vgscan metadata auto-correction.
4286 Only ask libdevmapper for open_count when we need it.
4287 Adjust RHEL4 clvmd init script priority.
4288 Enable building of CMAN & GULM versions of clvmd into a single binary
4289
4290Version 2.00.33 - 7th January 2005
4291==================================
4292 pvcreate wipes first 4 sectors unless given --zero n.
4293 gulm clvmd now uses new ccsd key names.
4294 gulm clvmd now doesn't ignore the first node in cluster.conf
4295 Improve clvmd failure message if it's already running.
4296 Allow user to kill clvmd during initialisation.
4297 Fix off-by-one error in cluster_locking that could cause read hangs.
4298
4299Version 2.00.32 - 22nd December 2004
4300====================================
4301 Drop static/dl restriction for now.
4302 Fix an error fprintf.
4303 Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
4304 Fix device reference counting on re-opens.
4305 Ignore sysfs symlinks when DT_UNKNOWN.
4306 Add clvmd init script for RHEL4.
4307 Skip devices that are too small to be PVs.
4308 Fix pvchange -x segfault with lvm2-format orphan.
4309 Cope with empty msdos partition tables.
4310 Add CONTRIBUTORS file.
4311
4312Version 2.00.31 - 12th December 2004
4313====================================
4314 Reopen RO file descriptors RW if necessary.
4315
4316Version 2.00.30 - 10th December 2004
4317====================================
4318 Additional device-handling debug messages.
4319 Additional verbosity level -vvvv includes line numbers and backtraces.
4320 Verbose messages now go to stderr not stdout.
4321 Close any stray file descriptors before starting.
4322 Refine partitionable checks for certain device types.
4323 Allow devices/types to override built-ins.
4324 Fix lvreduce man page .i->.I
4325 Fix vgsplit man page title.
4326 Fix clvmd man makefile.
4327 Extend dev_open logging.
4328 Make clvmd_fix_conf.sh UNDOable.
4329
4330Version 2.00.29 - 27th November 2004
4331====================================
4332 xlate compilation fix.
4333
4334Version 2.00.28 - 27th November 2004
4335====================================
4336 Fix partition table & md signature detection.
4337 Minor configure/makefile tidy.
4338 Export version.h from tools for clvmd.
4339
4340Version 2.00.27 - 24th November 2004
4341====================================
4342 Trap large memory allocation requests.
4343 Fix to partition table detection code.
4344 Improve filter debug mesgs.
4345 Make clvmd_fix_conf.sh UNDOable
4346
4347Version 2.00.26 - 23rd November 2004
4348====================================
4349 Improve pool debugging stats.
4350 Detect partition table signature.
4351 pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
4352 Separate out md superblock detection code.
4353 Prevent snapshot origin resizing.
4354 Improve a vgremove error message.
4355 Update some man pages.
4356 Allow y/n with -ae args (exclusive activation).
4357 Fixes to lvcreate vgname parsing.
4358 Fix dm_name string size calculation.
4359 Improve clvmd error reporting during startup.
4360 Make clvmd cope with large gaps in node numbers IDs.
4361 Make clvmd initialisation cope better with debugging output.
4362 Tidy clvmd socket callbacks so all work happens outside main loop.
4363 clvmd -V now displays lvm version too.
4364 Add optional gulm build for clvmd
4365
4366Version 2.00.25 - 29th September 2004
4367=====================================
4368 Fix return code from rm_link for vgmknodes.
4369 Make clvmd LV hash table thread-safe.
4370 Fix clvmd locking so it will lock out multiple users on the same node.
4371 Fix clvmd VG locking to it can cope with multiple VG locks.
4372 Remove spurious trailing dot in lvreduce man page.
4373 Fix vgremove locking.
4374
4375Version 2.00.24 - 16th September 2004
4376=====================================
4377 Fix pool_empty so it really does empty the memory pool.
4378 Rename old segtypes files to segtype.
4379 Some fixes to memory debugging code.
4380 Exclude internal commands formats & segtypes from install.
4381
4382Version 2.00.23 - 15th September 2004
4383=====================================
4384 Export dm name build & split functions.
4385 Use O_NOATIME on devices if available.
4386 Write log message when each segtype/format gets initialised.
4387 New commands 'segtypes' and 'formats'.
4388 Suppress pvmove abort message in test mode.
4389 Improve pvcreate/remove device not found error message.
4390 Allow pvmove to move data within the same PV.
4391 Describe how pvmove works on man page.
4392 Test for incompatible format/segtype combinations in lv_extend.
4393 Fix lvchange example on man page.
4394
4395Version 2.00.22 - 3rd September 2004
4396====================================
4397 Fix /dev/vgname perms.
4398 Restructure xlate.h.
4399 Add clvmd man page.
4400
4401Version 2.00.21 - 19th August 2004
4402==================================
4403 Update cnxman-socket.h from cman.
4404 Recognise iseries/vd devices.
4405 Use 'make install_cluster' to install cluster extensions only.
4406 Cope with DT_UNKNOWN in sysfs.
4407 Fix extents_moved metadata size comment.
4408 Remove duplicate line in pvremove help text.
4409 Support variable mirror region size.
4410 Support PE ranges in pvmove source PV.
4411 Fixes to as-yet-unused LV segment splitting code.
4412 Change alloc_areas to pe_ranges and allow suppression of availability checks.
4413 Add dev_size column to pvs.
4414 Add report columns for in-kernel device number.
4415
4416Version 2.00.20 - 3 July 2004
4417=============================
4418 More autoconf fixes.
4419 Fix device number handling for 2.6 kernels.
4420
4421Version 2.00.19 - 29 June 2004
4422==============================
4423 Reduce severity of setlocale failure message.
4424 Recognise argv[0] "initrd-lvm" (pld-linux).
4425 Make -O2 configurable.
4426 Added --disable-selinux to configure script.
4427 LD_FLAGS->LDFLAGS & LD_DEPS->LDDEPS in configure script.
4428 Add init_debug to clvmd.
4429
4430Version 2.00.18 - 24 June 2004
4431==============================
4432 Fix vgchange activation.
4433 Add cluster support.
4434
4435Version 2.00.17 - 20 June 2004
4436==============================
4437 configure --enable-fsadm to try out fsadm. fsadm is not tested yet.
4438 Display all filtered devices, not just PVs, with pvs -a.
4439 Fix sync_dir() when no / in filename
4440 vgcfgbackup -f accepts template with %s for VG name.
4441 Extend hash functions to handle non-null-terminated data.
4442 Add local activation support.
4443 Tidy relative paths in makefile includes.
4444 fsadm support for fsck and resizing - needs testing.
4445 Add read-only GFS pool support.
4446 Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
4447 Fix rounding of large diplayed sizes.
4448 Suppress decimal point when using units of sectors/bytes.
4449 Additional kernel target checks before pvmove & snapshot creation.
4450 Add i2o_block.
4451
4452Version 2.00.16 - 24 May 2004
4453=============================
4454 Set area_count within alloc_lv_segment.
4455 Remove error labels from lvresize.
4456 Fix a pvs error path.
4457 xxchange -ae for exclusive activation.
4458 Don't return non-zero status if there aren't any volume groups.
4459 Add --alloc argument to tools.
4460 Rename allocation policies to contiguous, normal, anywhere, inherit.
4461 nextfree becomes normal; anywhere isn't implemented yet.
4462 LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
4463 Additional status character added to vgs to indicate allocation policy.
4464 Add reset_fn to external_locking.
4465 Ensure presence of virtual targets before attempting activating.
4466 Attempt to fix resizing of snapshot origins.
4467 Restructure lvresize, bringing it closer to lvcreate.
4468 A quick sanity check on vg_disk struct when read in. More checks needed.
4469 Only include visible LVs in active/open counts.
4470 Add virtual segment types, zero and error. A large sparse device can be
4471constructed as a writeable snapshot of a large zero segment.
4472 Add --type to lvcreate/resize.
4473 Push lv_create & alloc policy up to tool level.
4474 Fix pvdisplay return code.
4475 Detect invalid LV names in arg lists.
4476 Reporting uses line-at-a-time output.
4477 lvm2 format sets unlimited_vols format flag.
4478 Internal-only metadata flag support.
4479 Basic checking for presence of device-mapper targets.
4480 Separate out polldaemon.
4481 Revise internal locking semantics.
4482 Move find_pv_by_name to library.
4483 Rename move->copy.
4484 Add devices to segments report.
4485 Begin separating out segment code. There's a lot of change here.
4486 Compress any (obsolete) long LVM1 pvids encountered.
4487 Support for tagged config files.
4488 Don't abort operations if selinux present but disabled.
4489 Fix typo in configure which left HAVE_LIBDL unset.
4490
4491Version 2.00.15 - 19 Apr 2004
4492=============================
4493 configure --with-owner= --with-group= to avoid -o and -g args to 'install'
4494
4495Version 2.00.14 - 16 Apr 2004
4496=============================
4497 Use 64-bit file functions by default.
4498
4499Version 2.00.13 - 16 Apr 2004
4500=============================
4501 Set devices/md_component_detection = 1 to ignore devices containing md
4502 superblocks. [Luca Berra]
4503 Ignore error setting selinux file context if fs doesn't support it.
4504
4505Version 2.00.12 - 14 Apr 2004
4506=============================
4507 Install a default lvm.conf into /etc/lvm if there isn't one already.
4508 Allow different installation dir for lvm.static (configure --staticdir=)
4509 Fix inverted selinux error check.
4510 Recognise power2 in /proc/devices.
4511 Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
4512
4513Version 2.00.11 - 8 Apr 2004
4514============================
4515 Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
4516 to run lvm1 binaries if running a 2.4 kernel without device-mapper.
4517
4518Version 2.00.10 - 7 Apr 2004
4519============================
4520 More fixes for static build.
4521 Add basic selinux support.
4522 Fix sysfs detection.
4523
4524Version 2.00.09 - 31 Mar 2004
4525=============================
4526 Update copyright notices for Red Hat.
4527 Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
4528 Add LVM1-style colon output to vgdisplay.
4529 lvchange --refresh to reload active LVs.
4530 Add string display to memory leak dump.
4531 Add locking flags & memlock option.
4532 Add list_versions to library.
4533 Ignore open hidden LVs when checking if deactivation is OK.
4534 Suppress move percentage when device inactive.
4535 Add lv_info_by_lvid.
4536 Various tidy-ups to the build process.
4537 Rebaseline internal verbose level.
4538 Add --nolocking option for read operations if locking is failing.
4539 Add option to compile into a library.
4540 When compiled without libdevmapper, only print warning message once.
4541 Fix lvreduce PV extent calculations.
4542 Fix DESTDIR to work with configure path overrides.
4543 Always use / as config file separator & rename internal config file variables.
4544 Add support for tagging PV/VG/LVs and hosts.
4545 Fix rare bug in recognition of long cmdline argument forms.
4546 Add basic internationalisation infrastructure.
4547 Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
4548 Update autoconf files.
4549 Add sysfs block device filtering for 2.6 kernels.
4550 Update refs for move to sources.redhat.com.
4551
4552Friday 14th November 2003
4553=========================
4554Some bug fixes & minor enhancements, including:
4555 Backwards compatibility with LVM1 metadata improved.
4556 Missing man pages written.
4557 Tool error codes made more consistent.
4558 vgmknodes written.
4559 O_DIRECT can be turned off if it doesn't work in your kernel.
4560 dumpconfig to display the active configuration file
4561
4562You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
4563If your root filesystem is on an LV, you should run one of those two
4564commands to fix up the special files in /dev in your real root filesystem
4565after finishing with your initrd. Also, remember you can use
4566'vgchange --ignorelockingfailure' on your initrd if the tool fails because
4567it can't write a lock file to a read-only filesystem.
4568
4569Wednesday 30th April 2003
4570=========================
4571A pvmove implementation is now available for the new metadata format.
4572
4573When running a command that allocates space (e.g. lvcreate), you can now
4574restrict not only which disk(s) may be used but also the Physical Extents
4575on those disks. e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
4576
4577
4578Monday 18th November 2002
4579========================
4580
4581The new format of LVM metadata is ready for you to test!
4582 We expect it to be more efficient and more robust than the original format.
4583 It's more compact and supports transactional changes and replication.
4584 Should things go wrong on a system, it's human-readable (and editable).
4585
4586Please report any problems you find to the mailing list,
4587linux-lvm@sistina.com. The software has NOT yet been thoroughly
4588tested and so quite possibly there'll still be some bugs in it.
4589Be aware of the disclaimer in the COPYING file.
4590
4591While testing, we recommend turning logging on in the configuration file
4592to provide us with diagnostic information:
4593 log {
4594 file="/tmp/lvm2.log"
4595 level=7
4596 activation=1
4597 }
4598
4599You should schedule regular backups of your configuration file and
4600metadata backups and archives (normally kept under /etc/lvm).
4601
4602Please read docs/example.conf and "man lvm.conf" to find out more about
4603the configuration file.
4604
4605To convert an existing volume group called vg1 to the new format using
4606the default settings, use "vgconvert -M2 vg1". See "man vgconvert".
4607
4608-M (or --metadatatype in its long form) is a new flag to indicate which
4609format of metadata the command should use for anything it creates.
4610Currently, the valid types are "lvm1" and "lvm2" and they can be
4611abbreviated to "1" and "2" respectively. The default value for this
4612flag can be changed in the global section in the config file.
4613
4614Backwards-compatible support for the original LVM1 metadata format is
4615maintained, but it can be moved into a shared library or removed
4616completely with configure's --with-lvm1 option.
4617
4618Under LVM2, the basic unit of metadata is the volume group. Different
4619volume groups can use different formats of metadata - vg1 could use
4620the original LVM1 format while vg2 used the new format - but you can't
4621mix formats within a volume group. So to add a PV to an LVM2-format
4622volume group you must run "pvcreate -M2" on it, followed by "vgextend".
4623
4624With LVM2-format metadata, lvextend will let you specify striping
4625parameters. So an LV could consist of two or more "segments" - the
4626first segment could have 3 stripes while the second segment has just 2.
4627
4628LVM2 maintains a backup of the current metadata for each volume group
4629in /etc/lvm/backup, and puts copies of previous versions in
4630/etc/lvm/archive. "vgcfgbackup" and "vgcfgrestore" can be used to
4631create and restore from these files. If you fully understand what
4632you're doing, metadata can be changed by editing a copy of a current
4633backup file and using vgcfgrestore to reload it.
4634
4635Please read the pvcreate man page for more information on the new
4636format for metadata.
4637
4638All tools that can change things have a --test flag which can be used
4639to check the effect of a set of cmdline args without really making the
4640changes.
4641
4642
4643What's not finished?
4644====================
4645The internal cache. If you turn on debugging output you'll see lots of
4646repeated messages, many of which will eventually get optimised out.
4647
4648--test sometimes causes a command to fail (e.g. vgconvert --test) even
4649though the real command would work: again, fixing this is waiting for
4650the work on the cache.
4651
4652Several of the tools do not yet contain the logic to handle full
4653recovery: combinations of pvcreate and vgcfgrestore may sometimes be
4654needed to restore metadata if a tool gets interrupted or crashes or
4655finds something unexpected. This applies particularly to tools that
4656work on more than one volume group at once (e.g. vgsplit).
4657
4658Display output. Some metadata information cannot yet be displayed.
4659
4660Recovery tools to salvage "lost" metadata directly from the disks:
4661but we hope the new format will mean such tools are hardly ever needed!
4662\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0017001\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020307\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/daemon-log.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002505\013062740170\0022504\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4663 * Copyright (C) 2012 Red Hat, Inc.
4664 *
4665 * This file is part of LVM2.
4666 *
4667 * This copyrighted material is made available to anyone wishing to use,
4668 * modify, copy, or redistribute it subject to the terms and conditions
4669 * of the GNU Lesser General Public License v.2.1.
4670 *
4671 * You should have received a copy of the GNU Lesser General Public License
4672 * along with this program; if not, write to the Free Software Foundation,
4673 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4674 */
4675
4676#ifndef _LVM_DAEMON_LOG_H
4677#define _LVM_DAEMON_LOG_H
4678
4679enum { DAEMON_LOG_FATAL = 0 /* usually preceding daemon death */
4680 , DAEMON_LOG_ERROR = 1 /* something serious has happened */
4681 , DAEMON_LOG_WARN = 2 /* something unusual has happened */
4682 , DAEMON_LOG_INFO = 3 /* thought you might be interested */
4683 , DAEMON_LOG_WIRE = 4 /* dump traffic on client sockets */
4684 , DAEMON_LOG_DEBUG = 5 /* unsorted debug stuff */
4685};
4686
4687#define DEBUGLOG(s, x...) daemon_logf((s)->log, DAEMON_LOG_DEBUG, x)
4688#define DEBUGLOG_cft(s, i, n) daemon_log_cft((s)->log, DAEMON_LOG_DEBUG, i, n)
4689#define WARN(s, x...) daemon_logf((s)->log, DAEMON_LOG_WARN, x)
4690#define INFO(s, x...) daemon_logf((s)->log, DAEMON_LOG_INFO, x)
4691#define ERROR(s, x...) daemon_logf((s)->log, DAEMON_LOG_ERROR, x)
4692#define FATAL(s, x...) daemon_logf((s)->log, DAEMON_LOG_FATAL, x)
4693
4694#endif
4695\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/daemon-server.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000037112\013062740170\0023226\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
4696 * Copyright (C) 2011-2012 Red Hat, Inc.
4697 *
4698 * This copyrighted material is made available to anyone wishing to use,
4699 * modify, copy, or redistribute it subject to the terms and conditions
4700 * of the GNU Lesser General Public License v.2.1.
4701 *
4702 * You should have received a copy of the GNU Lesser General Public License
4703 * along with this program; if not, write to the Free Software Foundation,
4704 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4705 */
4706
4707#define _REENTRANT
4708
4709#include "tool.h"
4710
4711#include "daemon-io.h"
4712#include "daemon-server.h"
4713#include "daemon-log.h"
4714
4715#include <dlfcn.h>
4716#include <errno.h>
4717#include <pthread.h>
4718#include <sys/file.h>
4719#include <sys/stat.h>
4720#include <sys/wait.h>
4721#include <sys/time.h>
4722#include <sys/resource.h>
4723#include <netinet/in.h>
4724#include <sys/un.h>
4725#include <unistd.h>
4726#include <signal.h>
4727
4728#include <syslog.h> /* FIXME. For the global closelog(). */
4729
4730#if 0
4731/* Create a device monitoring thread. */
4732static int _pthread_create(pthread_t *t, void *(*fun)(void *), void *arg, int stacksize)
4733{
4734 pthread_attr_t attr;
4735 pthread_attr_init(&attr);
4736 /*
4737 * We use a smaller stack since it gets preallocated in its entirety
4738 */
4739 pthread_attr_setstacksize(&attr, stacksize);
4740 return pthread_create(t, &attr, fun, arg);
4741}
4742#endif
4743
4744static volatile sig_atomic_t _shutdown_requested = 0;
4745static int _systemd_activation = 0;
4746
4747static void _exit_handler(int sig __attribute__((unused)))
4748{
4749 _shutdown_requested = 1;
4750}
4751
4752#define EXIT_ALREADYRUNNING 13
4753
4754#ifdef __linux__
4755
4756#include <stddef.h>
4757
4758/*
4759 * Kernel version 2.6.36 and higher has
4760 * new OOM killer adjustment interface.
4761 */
4762# define OOM_ADJ_FILE_OLD "/proc/self/oom_adj"
4763# define OOM_ADJ_FILE "/proc/self/oom_score_adj"
4764
4765/* From linux/oom.h */
4766/* Old interface */
4767# define OOM_DISABLE (-17)
4768# define OOM_ADJUST_MIN (-16)
4769/* New interface */
4770# define OOM_SCORE_ADJ_MIN (-1000)
4771
4772/* Systemd on-demand activation support */
4773# define SD_ACTIVATION_ENV_VAR_NAME "SD_ACTIVATION"
4774# define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
4775# define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
4776# define SD_LISTEN_FDS_START 3
4777# define SD_FD_SOCKET_SERVER SD_LISTEN_FDS_START
4778
4779static int _is_idle(daemon_state s)
4780{
4781 return s.idle && s.idle->is_idle && !s.threads->next;
4782}
4783
4784static struct timeval *_get_timeout(daemon_state s)
4785{
4786 return s.idle ? s.idle->ptimeout : NULL;
4787}
4788
4789static void _reset_timeout(daemon_state s)
4790{
4791 if (s.idle) {
4792 s.idle->ptimeout->tv_sec = 1;
4793 s.idle->ptimeout->tv_usec = 0;
4794 }
4795}
4796
4797static unsigned _get_max_timeouts(daemon_state s)
4798{
4799 return s.idle ? s.idle->max_timeouts : 0;
4800}
4801
4802static int _set_oom_adj(const char *oom_adj_path, int val)
4803{
4804 FILE *fp;
4805
4806 if (!(fp = fopen(oom_adj_path, "w"))) {
4807 perror("oom_adj: fopen failed");
4808 return 0;
4809 }
4810
4811 fprintf(fp, "%i", val);
4812
4813 if (dm_fclose(fp))
4814 perror("oom_adj: fclose failed");
4815
4816 return 1;
4817}
4818
4819/*
4820 * Protection against OOM killer if kernel supports it
4821 */
4822static int _protect_against_oom_killer(void)
4823{
4824 struct stat st;
4825
4826 if (stat(OOM_ADJ_FILE, &st) == -1) {
4827 if (errno != ENOENT)
4828 perror(OOM_ADJ_FILE ": stat failed");
4829
4830 /* Try old oom_adj interface as a fallback */
4831 if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
4832 if (errno == ENOENT)
4833 perror(OOM_ADJ_FILE_OLD " not found");
4834 else
4835 perror(OOM_ADJ_FILE_OLD ": stat failed");
4836 return 1;
4837 }
4838
4839 return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) ||
4840 _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN);
4841 }
4842
4843 return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
4844}
4845
4846union sockaddr_union {
4847 struct sockaddr sa;
4848 struct sockaddr_un un;
4849};
4850
4851static int _handle_preloaded_socket(int fd, const char *path)
4852{
4853 struct stat st_fd;
4854 union sockaddr_union sockaddr = { .sa.sa_family = 0 };
4855 int type = 0;
4856 socklen_t len = sizeof(type);
4857 size_t path_len = strlen(path);
4858
4859 if (fd < 0)
4860 return 0;
4861
4862 if (fstat(fd, &st_fd) < 0 || !S_ISSOCK(st_fd.st_mode))
4863 return 0;
4864
4865 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0 ||
4866 len != sizeof(type) || type != SOCK_STREAM)
4867 return 0;
4868
4869 len = sizeof(sockaddr);
4870 if (getsockname(fd, &sockaddr.sa, &len) < 0 ||
4871 len < sizeof(sa_family_t) ||
4872 sockaddr.sa.sa_family != PF_UNIX)
4873 return 0;
4874
4875 if (!(len >= offsetof(struct sockaddr_un, sun_path) + path_len + 1 &&
4876 memcmp(path, sockaddr.un.sun_path, path_len) == 0))
4877 return 0;
4878
4879 return 1;
4880}
4881
4882static int _systemd_handover(struct daemon_state *ds)
4883{
4884 const char *e;
4885 char *p;
4886 unsigned long env_pid, env_listen_fds;
4887 int r = 0;
4888
4889 /* SD_ACTIVATION must be set! */
4890 if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1"))
4891 goto out;
4892
4893 /* LISTEN_PID must be equal to our PID! */
4894 if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
4895 goto out;
4896
4897 errno = 0;
4898 env_pid = strtoul(e, &p, 10);
4899 if (errno || !p || *p || env_pid <= 0 ||
4900 getpid() != (pid_t) env_pid)
4901 goto out;
4902
4903 /* LISTEN_FDS must be 1 and the fd must be a socket! */
4904 if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
4905 goto out;
4906
4907 errno = 0;
4908 env_listen_fds = strtoul(e, &p, 10);
4909 if (errno || !p || *p || env_listen_fds != 1)
4910 goto out;
4911
4912 /* Check and handle the socket passed in */
4913 if ((r = _handle_preloaded_socket(SD_FD_SOCKET_SERVER, ds->socket_path)))
4914 ds->socket_fd = SD_FD_SOCKET_SERVER;
4915
4916out:
4917 unsetenv(SD_ACTIVATION_ENV_VAR_NAME);
4918 unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
4919 unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
4920 return r;
4921}
4922
4923#endif
4924
4925static int _open_socket(daemon_state s)
4926{
4927 int fd;
4928 int file_created = 0;
4929 struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
4930 struct stat buf;
4931 mode_t old_mask;
4932
4933 (void) dm_prepare_selinux_context(s.socket_path, S_IFSOCK);
4934 old_mask = umask(0077);
4935
4936 /* Open local socket */
4937 fd = socket(PF_UNIX, SOCK_STREAM, 0);
4938 if (fd < 0) {
4939 perror("Can't create local socket.");
4940 goto error;
4941 }
4942
4943 /* Set non-blocking */
4944 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK))
4945 fprintf(stderr, "setting O_NONBLOCK on socket fd %d failed: %s\n", fd, strerror(errno));
4946
4947 fprintf(stderr, "[D] creating %s\n", s.socket_path);
4948 if (!dm_strncpy(sockaddr.sun_path, s.socket_path, sizeof(sockaddr.sun_path))) {
4949 fprintf(stderr, "%s: daemon socket path too long.\n", s.socket_path);
4950 goto error;
4951 }
4952
4953 if (bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
4954 if (errno != EADDRINUSE) {
4955 perror("can't bind local socket");
4956 goto error;
4957 }
4958
4959 /* Socket already exists. If it's stale, remove it. */
4960 if (lstat(sockaddr.sun_path, &buf)) {
4961 perror("stat failed");
4962 goto error;
4963 }
4964
4965 if (!S_ISSOCK(buf.st_mode)) {
4966 fprintf(stderr, "%s: not a socket\n", sockaddr.sun_path);
4967 goto error;
4968 }
4969
4970 if (buf.st_uid || (buf.st_mode & (S_IRWXG | S_IRWXO))) {
4971 fprintf(stderr, "%s: unrecognised permissions\n", sockaddr.sun_path);
4972 goto error;
4973 }
4974
4975 if (!connect(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
4976 fprintf(stderr, "Socket %s already in use\n", sockaddr.sun_path);
4977 goto error;
4978 }
4979
4980 fprintf(stderr, "removing stale socket %s\n", sockaddr.sun_path);
4981
4982 if (unlink(sockaddr.sun_path) && (errno != ENOENT)) {
4983 perror("unlink failed");
4984 goto error;
4985 }
4986
4987 if (bind(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
4988 perror("local socket bind failed after unlink");
4989 goto error;
4990 }
4991 }
4992
4993 file_created = 1;
4994
4995 if (listen(fd, 1) != 0) {
4996 perror("listen local");
4997 goto error;
4998 }
4999
5000out:
5001 umask(old_mask);
5002 (void) dm_prepare_selinux_context(NULL, 0);
5003 return fd;
5004
5005error:
5006 if (fd >= 0) {
5007 if (close(fd))
5008 perror("close failed");
5009 if (file_created && unlink(s.socket_path))
5010 perror("unlink failed");
5011 fd = -1;
5012 }
5013 goto out;
5014}
5015
5016static void _remove_lockfile(const char *file)
5017{
5018 if (unlink(file))
5019 perror("unlink failed");
5020}
5021
5022static void _daemonise(daemon_state s)
5023{
5024 int child_status;
5025 int fd;
5026 pid_t pid;
5027 struct rlimit rlim;
5028 struct timeval tval;
5029 sigset_t my_sigset;
5030
5031 sigemptyset(&my_sigset);
5032 if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
5033 fprintf(stderr, "Unable to restore signals.\n");
5034 exit(EXIT_FAILURE);
5035 }
5036 signal(SIGTERM, &_exit_handler);
5037
5038 switch (pid = fork()) {
5039 case -1:
5040 perror("fork failed:");
5041 exit(EXIT_FAILURE);
5042
5043 case 0: /* Child */
5044 break;
5045
5046 default:
5047 /* Wait for response from child */
5048 while (!waitpid(pid, &child_status, WNOHANG) && !_shutdown_requested) {
5049 tval.tv_sec = 0;
5050 tval.tv_usec = 250000; /* .25 sec */
5051 select(0, NULL, NULL, NULL, &tval);
5052 }
5053
5054 if (_shutdown_requested) /* Child has signaled it is ok - we can exit now */
5055 exit(0);
5056
5057 switch (WEXITSTATUS(child_status)) {
5058 case EXIT_ALREADYRUNNING:
5059 fprintf(stderr, "Failed to acquire lock on %s. Already running?\n", s.pidfile);
5060 break;
5061 default:
5062 /* Problem with child. Determine what it is by exit code */
5063 fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
5064 }
5065 exit(WEXITSTATUS(child_status));
5066 }
5067
5068 if (chdir("/"))
5069 exit(1);
5070
5071 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
5072 fd = 256; /* just have to guess */
5073 else
5074 fd = rlim.rlim_cur;
5075
5076 for (--fd; fd >= 0; fd--) {
5077#ifdef __linux__
5078 /* Do not close fds preloaded by systemd! */
5079 if (_systemd_activation && fd == SD_FD_SOCKET_SERVER)
5080 continue;
5081#endif
5082 (void) close(fd);
5083 }
5084
5085 if ((open("/dev/null", O_RDONLY) < 0) ||
5086 (open("/dev/null", O_WRONLY) < 0) ||
5087 (open("/dev/null", O_WRONLY) < 0))
5088 exit(1);
5089
5090 setsid();
5091}
5092
5093response daemon_reply_simple(const char *id, ...)
5094{
5095 va_list ap;
5096 response res = { .cft = NULL };
5097
5098 va_start(ap, id);
5099
5100 buffer_init(&res.buffer);
5101 if (!buffer_append_f(&res.buffer, "response = %s", id, NULL)) {
5102 res.error = ENOMEM;
5103 goto end;
5104 }
5105 if (!buffer_append_vf(&res.buffer, ap)) {
5106 res.error = ENOMEM;
5107 goto end;
5108 }
5109
5110end:
5111 va_end(ap);
5112 return res;
5113}
5114
5115static response _builtin_handler(daemon_state s, client_handle h, request r)
5116{
5117 const char *rq = daemon_request_str(r, "request", "NONE");
5118 response res = { .error = EPROTO };
5119
5120 if (!strcmp(rq, "hello")) {
5121 return daemon_reply_simple("OK", "protocol = %s", s.protocol ?: "default",
5122 "version = %" PRId64, (int64_t) s.protocol_version, NULL);
5123 }
5124
5125 buffer_init(&res.buffer);
5126 return res;
5127}
5128
5129static void *_client_thread(void *state)
5130{
5131 thread_state *ts = state;
5132 request req;
5133 response res;
5134
5135 buffer_init(&req.buffer);
5136
5137 while (1) {
5138 if (!buffer_read(ts->client.socket_fd, &req.buffer))
5139 goto fail;
5140
5141 req.cft = config_tree_from_string_without_dup_node_check(req.buffer.mem);
5142
5143 if (!req.cft)
5144 fprintf(stderr, "error parsing request:\n %s\n", req.buffer.mem);
5145 else
5146 daemon_log_cft(ts->s.log, DAEMON_LOG_WIRE, "<- ", req.cft->root);
5147
5148 res = _builtin_handler(ts->s, ts->client, req);
5149
5150 if (res.error == EPROTO) /* Not a builtin, delegate to the custom handler. */
5151 res = ts->s.handler(ts->s, ts->client, req);
5152
5153 if (!res.buffer.mem) {
5154 if (!dm_config_write_node(res.cft->root, buffer_line, &res.buffer))
5155 goto fail;
5156 if (!buffer_append(&res.buffer, "\n\n"))
5157 goto fail;
5158 dm_config_destroy(res.cft);
5159 }
5160
5161 if (req.cft)
5162 dm_config_destroy(req.cft);
5163 buffer_destroy(&req.buffer);
5164
5165 daemon_log_multi(ts->s.log, DAEMON_LOG_WIRE, "-> ", res.buffer.mem);
5166 buffer_write(ts->client.socket_fd, &res.buffer);
5167
5168 buffer_destroy(&res.buffer);
5169 }
5170fail:
5171 /* TODO what should we really do here? */
5172 if (close(ts->client.socket_fd))
5173 perror("close");
5174 buffer_destroy(&req.buffer);
5175 ts->active = 0;
5176 return NULL;
5177}
5178
5179static int handle_connect(daemon_state s)
5180{
5181 thread_state *ts;
5182 struct sockaddr_un sockaddr;
5183 client_handle client = { .thread_id = 0 };
5184 socklen_t sl = sizeof(sockaddr);
5185
5186 client.socket_fd = accept(s.socket_fd, (struct sockaddr *) &sockaddr, &sl);
5187 if (client.socket_fd < 0) {
5188 ERROR(&s, "Failed to accept connection errno %d.", errno);
5189 return 0;
5190 }
5191
5192 if (fcntl(client.socket_fd, F_SETFD, FD_CLOEXEC))
5193 WARN(&s, "setting CLOEXEC on client socket fd %d failed", client.socket_fd);
5194
5195 if (!(ts = dm_malloc(sizeof(thread_state)))) {
5196 if (close(client.socket_fd))
5197 perror("close");
5198 ERROR(&s, "Failed to allocate thread state");
5199 return 0;
5200 }
5201
5202 ts->next = s.threads->next;
5203 s.threads->next = ts;
5204
5205 ts->active = 1;
5206 ts->s = s;
5207 ts->client = client;
5208
5209 if (pthread_create(&ts->client.thread_id, NULL, _client_thread, ts)) {
5210 ERROR(&s, "Failed to create client thread errno %d.", errno);
5211 return 0;
5212 }
5213
5214 return 1;
5215}
5216
5217static void _reap(daemon_state s, int waiting)
5218{
5219 thread_state *last = s.threads, *ts = last->next;
5220 void *rv;
5221
5222 while (ts) {
5223 if (waiting || !ts->active) {
5224 if ((errno = pthread_join(ts->client.thread_id, &rv)))
5225 ERROR(&s, "pthread_join failed: %s", strerror(errno));
5226 last->next = ts->next;
5227 dm_free(ts);
5228 } else
5229 last = ts;
5230 ts = last->next;
5231 }
5232}
5233
5234void daemon_start(daemon_state s)
5235{
5236 int failed = 0;
5237 log_state _log = { { 0 } };
5238 thread_state _threads = { .next = NULL };
5239 unsigned timeout_count = 0;
5240 fd_set in;
5241
5242 /*
5243 * Switch to C locale to avoid reading large locale-archive file used by
5244 * some glibc (on some distributions it takes over 100MB). Some daemons
5245 * need to use mlockall().
5246 */
5247 if (setenv("LC_ALL", "C", 1))
5248 perror("Cannot set LC_ALL to C");
5249
5250#ifdef __linux__
5251 _systemd_activation = _systemd_handover(&s);
5252#endif
5253
5254 if (!s.foreground)
5255 _daemonise(s);
5256
5257 s.log = &_log;
5258 s.log->name = s.name;
5259 s.threads = &_threads;
5260
5261 /* Log important things to syslog by default. */
5262 daemon_log_enable(s.log, DAEMON_LOG_OUTLET_SYSLOG, DAEMON_LOG_FATAL, 1);
5263 daemon_log_enable(s.log, DAEMON_LOG_OUTLET_SYSLOG, DAEMON_LOG_ERROR, 1);
5264
5265 if (s.pidfile) {
5266 (void) dm_prepare_selinux_context(s.pidfile, S_IFREG);
5267
5268 /*
5269 * NB. Take care to not keep stale locks around. Best not exit(...)
5270 * after this point.
5271 */
5272 if (dm_create_lockfile(s.pidfile) == 0) {
5273 ERROR(&s, "Failed to acquire lock on %s. Already running?\n", s.pidfile);
5274 exit(EXIT_ALREADYRUNNING);
5275 }
5276
5277 (void) dm_prepare_selinux_context(NULL, 0);
5278 }
5279
5280 /* Set normal exit signals to request shutdown instead of dying. */
5281 signal(SIGINT, &_exit_handler);
5282 signal(SIGHUP, &_exit_handler);
5283 signal(SIGQUIT, &_exit_handler);
5284 signal(SIGTERM, &_exit_handler);
5285 signal(SIGALRM, &_exit_handler);
5286 signal(SIGPIPE, SIG_IGN);
5287
5288#ifdef __linux__
5289 /* Systemd has adjusted oom killer for us already */
5290 if (s.avoid_oom && !_systemd_activation && !_protect_against_oom_killer())
5291 ERROR(&s, "Failed to protect against OOM killer");
5292#endif
5293
5294 if (!_systemd_activation && s.socket_path) {
5295 s.socket_fd = _open_socket(s);
5296 if (s.socket_fd < 0)
5297 failed = 1;
5298 }
5299
5300 /* Set Close-on-exec */
5301 if (!failed && fcntl(s.socket_fd, F_SETFD, 1))
5302 ERROR(&s, "setting CLOEXEC on socket fd %d failed: %s\n", s.socket_fd, strerror(errno));
5303
5304 /* Signal parent, letting them know we are ready to go. */
5305 if (!s.foreground)
5306 kill(getppid(), SIGTERM);
5307
5308 /*
5309 * Use daemon_main for daemon-specific init and polling, or
5310 * use daemon_init for daemon-specific init and generic lib polling.
5311 */
5312
5313 if (s.daemon_main) {
5314 if (!s.daemon_main(&s))
5315 failed = 1;
5316 goto out;
5317 }
5318
5319 if (s.daemon_init)
5320 if (!s.daemon_init(&s))
5321 failed = 1;
5322
5323 while (!failed) {
5324 _reset_timeout(s);
5325 FD_ZERO(&in);
5326 FD_SET(s.socket_fd, &in);
5327 if (select(FD_SETSIZE, &in, NULL, NULL, _get_timeout(s)) < 0 && errno != EINTR)
5328 perror("select error");
5329 if (FD_ISSET(s.socket_fd, &in)) {
5330 timeout_count = 0;
5331 handle_connect(s);
5332 }
5333
5334 _reap(s, 0);
5335
5336 if (_shutdown_requested && !s.threads->next)
5337 break;
5338
5339 /* s.idle == NULL equals no shutdown on timeout */
5340 if (_is_idle(s)) {
5341 DEBUGLOG(&s, "timeout occured");
5342 if (++timeout_count >= _get_max_timeouts(s)) {
5343 INFO(&s, "Inactive for %d seconds. Exiting.", timeout_count);
5344 break;
5345 }
5346 }
5347 }
5348
5349 INFO(&s, "%s waiting for client threads to finish", s.name);
5350 _reap(s, 1);
5351out:
5352 /* If activated by systemd, do not unlink the socket - systemd takes care of that! */
5353 if (!_systemd_activation && s.socket_fd >= 0)
5354 if (unlink(s.socket_path))
5355 perror("unlink error");
5356
5357 if (s.socket_fd >= 0)
5358 if (close(s.socket_fd))
5359 perror("socket close");
5360
5361 if (s.daemon_fini)
5362 if (!s.daemon_fini(&s))
5363 failed = 1;
5364
5365 INFO(&s, "%s shutting down", s.name);
5366
5367 closelog(); /* FIXME */
5368 if (s.pidfile)
5369 _remove_lockfile(s.pidfile);
5370 if (failed)
5371 exit(1);
5372}
5373\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001336\013062740170\0022357\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
5374#
5375# This file is part of the device-mapper userspace tools.
5376#
5377# This copyrighted material is made available to anyone wishing to use,
5378# modify, copy, or redistribute it subject to the terms and conditions
5379# of the GNU Lesser General Public License v.2.1.
5380#
5381# You should have received a copy of the GNU Lesser General Public License
5382# along with this program; if not, write to the Free Software Foundation,
5383# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5384
5385srcdir = @srcdir@
5386top_srcdir = @top_srcdir@
5387top_builddir = @top_builddir@
5388
5389LIB_STATIC = libdaemonserver.a
5390SOURCES = daemon-server.c daemon-log.c
5391
5392include $(top_builddir)/make.tmpl
5393
5394LIBS += $(DAEMON_LIBS)
5395\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/daemon-server.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013376\013062740170\0023241\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5396 * Copyright (C) 2011-2012 Red Hat, Inc.
5397 *
5398 * This file is part of LVM2.
5399 *
5400 * This copyrighted material is made available to anyone wishing to use,
5401 * modify, copy, or redistribute it subject to the terms and conditions
5402 * of the GNU Lesser General Public License v.2.1.
5403 *
5404 * You should have received a copy of the GNU Lesser General Public License
5405 * along with this program; if not, write to the Free Software Foundation,
5406 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5407 */
5408
5409#ifndef _LVM_DAEMON_SERVER_H
5410#define _LVM_DAEMON_SERVER_H
5411
5412#include "daemon-client.h"
5413
5414typedef struct {
5415 int socket_fd; /* the fd we use to talk to the client */
5416 pthread_t thread_id;
5417 char *read_buf;
5418 void *private; /* this holds per-client state */
5419} client_handle;
5420
5421typedef struct {
5422 struct dm_config_tree *cft;
5423 struct buffer buffer;
5424} request;
5425
5426typedef struct {
5427 int error;
5428 struct dm_config_tree *cft;
5429 struct buffer buffer;
5430} response;
5431
5432struct timeval;
5433
5434/*
5435 * is_idle: daemon implementation sets it to true when no background task
5436 * is running
5437 * max_timeouts: how many seconds do daemon allow to be idle before it shutdowns
5438 * ptimeout: internal variable passed to select(). has to be reset to 1 second
5439 * before each select
5440 */
5441typedef struct {
5442 volatile unsigned is_idle;
5443 unsigned max_timeouts;
5444 struct timeval *ptimeout;
5445} daemon_idle;
5446
5447struct daemon_state;
5448
5449/*
5450 * Craft a simple reply, without the need to construct a config_tree. See
5451 * daemon_send_simple in daemon-client.h for the description of the parameters.
5452 */
5453response daemon_reply_simple(const char *id, ...);
5454
5455static inline int daemon_request_int(request r, const char *path, int def) {
5456 if (!r.cft)
5457 return def;
5458 return dm_config_find_int(r.cft->root, path, def);
5459}
5460
5461static inline const char *daemon_request_str(request r, const char *path, const char *def) {
5462 if (!r.cft)
5463 return def;
5464 return dm_config_find_str(r.cft->root, path, def);
5465}
5466
5467/*
5468 * The callback. Called once per request issued, in the respective client's
5469 * thread. It is presented by a parsed request (in the form of a config tree).
5470 * The output is a new config tree that is serialised and sent back to the
5471 * client. The client blocks until the request processing is done and reply is
5472 * sent.
5473 */
5474typedef response (*handle_request)(struct daemon_state s, client_handle h, request r);
5475
5476typedef struct {
5477 uint32_t log_config[32];
5478 void *backend_state[32];
5479 const char *name;
5480} log_state;
5481
5482struct thread_state;
5483
5484typedef struct daemon_state {
5485 /*
5486 * The maximal stack size for individual daemon threads. This is
5487 * essential for daemons that need to be locked into memory, since
5488 * pthread's default is 10M per thread.
5489 */
5490 int thread_stack_size;
5491
5492 /* Flags & attributes affecting the behaviour of the daemon. */
5493 unsigned avoid_oom:1;
5494 unsigned foreground:1;
5495 const char *name;
5496 const char *pidfile;
5497 const char *socket_path;
5498 const char *protocol;
5499 int protocol_version;
5500
5501 handle_request handler;
5502 int (*daemon_init)(struct daemon_state *st);
5503 int (*daemon_fini)(struct daemon_state *st);
5504 int (*daemon_main)(struct daemon_state *st);
5505
5506 /* Global runtime info maintained by the framework. */
5507 int socket_fd;
5508
5509 log_state *log;
5510 struct thread_state *threads;
5511
5512 /* suport for shutdown on idle */
5513 daemon_idle *idle;
5514
5515 void *private; /* the global daemon state */
5516} daemon_state;
5517
5518typedef struct thread_state {
5519 daemon_state s;
5520 client_handle client;
5521 struct thread_state *next;
5522 volatile int active;
5523} thread_state;
5524
5525/*
5526 * Start serving the requests. This does all the daemonisation, socket setup
5527 * work and so on. This function takes over the process, and upon failure, it
5528 * will terminate execution. It may be called at most once.
5529 */
5530void daemon_start(daemon_state s);
5531
5532/*
5533 * Take over from an already running daemon. This function handles connecting
5534 * to the running daemon and telling it we are going to take over. The takeover
5535 * request may be customised by passing in a non-NULL request.
5536 *
5537 * The takeover sequence: the old daemon stops accepting new clients, then it
5538 * waits until all current client connections are closed. When that happens, it
5539 * serializes its current state and sends that as a reply, which is then
5540 * returned by this function (therefore, this function won't return until the
5541 * previous instance has shut down).
5542 *
5543 * The daemon, after calling daemon_takeover is expected to set up its
5544 * daemon_state using the reply from this function and call daemon_start as
5545 * usual.
5546 */
5547daemon_reply daemon_takeover(daemon_info i, daemon_request r);
5548
5549/* Call this to request a clean shutdown of the daemon. Async safe. */
5550void daemon_stop(void);
5551
5552enum { DAEMON_LOG_OUTLET_SYSLOG = 1,
5553 DAEMON_LOG_OUTLET_STDERR = 2,
5554 DAEMON_LOG_OUTLET_SOCKET = 4 };
5555
5556/* Log a message of a given type. */
5557void daemon_log(log_state *s, int type, const char *message);
5558
5559/* Log a config (sub)tree, using a given message type, each line prefixed with "prefix". */
5560void daemon_log_cft(log_state *s, int type, const char *prefix,
5561 const struct dm_config_node *n);
5562
5563/* Log a multi-line block, prefixing each line with "prefix". */
5564void daemon_log_multi(log_state *s, int type, const char *prefix, const char *message);
5565
5566/* Log a formatted message as "type". See also daemon-log.h. */
5567void daemon_logf(log_state *s, int type, const char *format, ...)
5568 __attribute__ ((format(printf, 3, 4)));
5569
5570/*
5571 * Configure log_state to send messages of type "type" to the log outlet
5572 * "outlet", iff "enable" is true.
5573 */
5574void daemon_log_enable(log_state *s, int outlet, int type, int enable);
5575
5576/*
5577 * Set up logging on a given outlet using a list of message types (comma
5578 * separated) to log using that outlet. The list is expected to look like this,
5579 * "all,wire,debug". Returns 0 upon encountering an unknown message type.
5580 */
5581int daemon_log_parse(log_state *s, int outlet, const char *types, int enable);
5582
5583#endif
5584\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/server/daemon-log.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011054\013062740170\0022476\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5585 * Copyright (C) 2011-2012 Red Hat, Inc.
5586 *
5587 * This copyrighted material is made available to anyone wishing to use,
5588 * modify, copy, or redistribute it subject to the terms and conditions
5589 * of the GNU Lesser General Public License v.2.1.
5590 *
5591 * You should have received a copy of the GNU Lesser General Public License
5592 * along with this program; if not, write to the Free Software Foundation,
5593 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5594 */
5595
5596#define _REENTRANT
5597
5598#include "tool.h"
5599
5600#include "daemon-server.h"
5601#include "daemon-log.h"
5602
5603#include <syslog.h>
5604
5605struct backend {
5606 int id;
5607 void (*log)(log_state *s, void **state, int type, const char *message);
5608};
5609
5610static void log_syslog(log_state *s, void **state, int type, const char *message)
5611{
5612 int prio;
5613
5614 if (!*state) { /* initialize */
5615 *state = (void *)1;
5616 openlog(s->name, LOG_PID, LOG_DAEMON);
5617 }
5618
5619 switch (type) {
5620 case DAEMON_LOG_INFO: prio = LOG_INFO; break;
5621 case DAEMON_LOG_WARN: prio = LOG_WARNING; break;
5622 case DAEMON_LOG_ERROR: prio = LOG_ERR; break;
5623 case DAEMON_LOG_FATAL: prio = LOG_CRIT; break;
5624 default: prio = LOG_DEBUG; break;
5625 }
5626
5627 syslog(prio, "%s", message);
5628}
5629
5630static void log_stderr(log_state *s, void **state, int type, const char *message)
5631{
5632 const char *prefix;
5633
5634 switch (type) {
5635 case DAEMON_LOG_INFO: prefix = "I: "; break;
5636 case DAEMON_LOG_WARN: prefix = "W: " ; break;
5637 case DAEMON_LOG_ERROR: /* fall through */
5638 case DAEMON_LOG_FATAL: prefix = "E: " ; break;
5639 default: prefix = ""; break;
5640 }
5641
5642 fprintf(stderr, "%s%s\n", prefix, message);
5643}
5644
5645struct backend backend[] = {
5646 { DAEMON_LOG_OUTLET_SYSLOG, log_syslog },
5647 { DAEMON_LOG_OUTLET_STDERR, log_stderr },
5648 { 0, 0 }
5649};
5650
5651void daemon_log(log_state *s, int type, const char *message) {
5652 int i = 0;
5653 while ( backend[i].id ) {
5654 if ((int)(s->log_config[type] & backend[i].id) == backend[i].id )
5655 backend[i].log( s, &s->backend_state[i], type, message );
5656 ++ i;
5657 }
5658}
5659
5660static int _type_interesting(log_state *s, int type) {
5661 int i = 0;
5662 while ( backend[i].id ) {
5663 if ((int)(s->log_config[type] & backend[i].id) == backend[i].id )
5664 return 1;
5665 ++ i;
5666 }
5667 return 0;
5668}
5669
5670void daemon_logf(log_state *s, int type, const char *fmt, ...) {
5671 char *buf;
5672 va_list ap;
5673
5674 va_start(ap, fmt);
5675 if (dm_vasprintf(&buf, fmt, ap) >= 0) {
5676 daemon_log(s, type, buf);
5677 dm_free(buf);
5678 } /* else return_0 */
5679 va_end(ap);
5680}
5681
5682struct log_line_baton {
5683 log_state *s;
5684 int type;
5685 const char *prefix;
5686};
5687
5688static int _log_line(const char *line, void *baton) {
5689 struct log_line_baton *b = baton;
5690 daemon_logf(b->s, b->type, "%s%s", b->prefix, line);
5691 return 0;
5692}
5693
5694void daemon_log_cft(log_state *s, int type, const char *prefix, const struct dm_config_node *n)
5695{
5696 struct log_line_baton b = { .s = s, .type = type, .prefix = prefix };
5697
5698 if (!_type_interesting(s, type))
5699 return;
5700
5701 (void) dm_config_write_node(n, &_log_line, &b);
5702}
5703
5704void daemon_log_multi(log_state *s, int type, const char *prefix, const char *msg)
5705{
5706 struct log_line_baton b = { .s = s, .type = type, .prefix = prefix };
5707 char *buf;
5708 char *pos;
5709
5710 if (!_type_interesting(s, type))
5711 return;
5712
5713 buf = dm_strdup(msg);
5714 pos = buf;
5715
5716 if (!buf)
5717 return; /* _0 */
5718
5719 while (pos) {
5720 char *next = strchr(pos, '\n');
5721 if (next)
5722 *next = 0;
5723 _log_line(pos, &b);
5724 pos = next ? next + 1 : 0;
5725 }
5726 dm_free(buf);
5727}
5728
5729void daemon_log_enable(log_state *s, int outlet, int type, int enable)
5730{
5731 if (type >= 32)
5732 return;
5733
5734 if (enable)
5735 s->log_config[type] |= outlet;
5736 else
5737 s->log_config[type] &= ~outlet;
5738}
5739
5740static int _parse_one(log_state *s, int outlet, const char *type, int enable)
5741{
5742 int i;
5743 if (!strcmp(type, "all"))
5744 for (i = 0; i < 32; ++i)
5745 daemon_log_enable(s, outlet, i, enable);
5746 else if (!strcmp(type, "fatal"))
5747 daemon_log_enable(s, outlet, DAEMON_LOG_FATAL, enable);
5748 else if (!strcmp(type, "error"))
5749 daemon_log_enable(s, outlet, DAEMON_LOG_ERROR, enable);
5750 else if (!strcmp(type, "warn"))
5751 daemon_log_enable(s, outlet, DAEMON_LOG_WARN, enable);
5752 else if (!strcmp(type, "info"))
5753 daemon_log_enable(s, outlet, DAEMON_LOG_INFO, enable);
5754 else if (!strcmp(type, "wire"))
5755 daemon_log_enable(s, outlet, DAEMON_LOG_WIRE, enable);
5756 else if (!strcmp(type, "debug"))
5757 daemon_log_enable(s, outlet, DAEMON_LOG_DEBUG, enable);
5758
5759 return 1;
5760}
5761
5762int daemon_log_parse(log_state *s, int outlet, const char *types, int enable)
5763{
5764 char *buf;
5765 char *pos;
5766
5767 if (!types || !types[0])
5768 return 1;
5769
5770 if (!(buf = dm_strdup(types)))
5771 return 0;
5772
5773 pos = buf;
5774 while (pos) {
5775 char *next = strchr(pos, ',');
5776 if (next)
5777 *next = 0;
5778 if (!_parse_one(s, outlet, pos, enable)) {
5779 dm_free(buf);
5780 return 0;
5781 }
5782 pos = next ? next + 1 : 0;
5783 }
5784
5785 dm_free(buf);
5786
5787 return 1;
5788}
5789\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020257\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/daemon-io.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001345\013062740170\0022303\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5790 * Copyright (C) 2011-2012 Red Hat, Inc.
5791 *
5792 * This file is part of LVM2.
5793 *
5794 * This copyrighted material is made available to anyone wishing to use,
5795 * modify, copy, or redistribute it subject to the terms and conditions
5796 * of the GNU Lesser General Public License v.2.1.
5797 *
5798 * You should have received a copy of the GNU Lesser General Public License
5799 * along with this program; if not, write to the Free Software Foundation,
5800 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5801 */
5802
5803#ifndef _LVM_DAEMON_IO_H
5804#define _LVM_DAEMON_IO_H
5805
5806#include "config-util.h"
5807
5808/* TODO function names */
5809
5810int buffer_read(int fd, struct buffer *buffer);
5811int buffer_write(int fd, const struct buffer *buffer);
5812
5813#endif /* _LVM_DAEMON_IO_H */
5814\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/config-util.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004566\013062740170\0022663\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5815 * Copyright (C) 2011-2012 Red Hat, Inc.
5816 *
5817 * This file is part of LVM2.
5818 *
5819 * This copyrighted material is made available to anyone wishing to use,
5820 * modify, copy, or redistribute it subject to the terms and conditions
5821 * of the GNU Lesser General Public License v.2.1.
5822 *
5823 * You should have received a copy of the GNU Lesser General Public License
5824 * along with this program; if not, write to the Free Software Foundation,
5825 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5826 */
5827
5828#ifndef _LVM_DAEMON_CONFIG_UTIL_H
5829#define _LVM_DAEMON_CONFIG_UTIL_H
5830
5831struct buffer {
5832 int allocated;
5833 int used;
5834 char *mem;
5835};
5836
5837int buffer_append_vf(struct buffer *buf, va_list ap);
5838int buffer_append_f(struct buffer *buf, ...);
5839int buffer_append(struct buffer *buf, const char *string);
5840void buffer_init(struct buffer *buf);
5841void buffer_destroy(struct buffer *buf);
5842int buffer_realloc(struct buffer *buf, int needed);
5843
5844int buffer_line(const char *line, void *baton);
5845
5846int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
5847 const char *field, const char *flag, int want);
5848
5849void chain_node(struct dm_config_node *cn,
5850 struct dm_config_node *parent,
5851 struct dm_config_node *pre_sib);
5852
5853struct dm_config_node *make_config_node(struct dm_config_tree *cft,
5854 const char *key,
5855 struct dm_config_node *parent,
5856 struct dm_config_node *pre_sib);
5857
5858int compare_value(struct dm_config_value *a, struct dm_config_value *b);
5859int compare_config(struct dm_config_node *a, struct dm_config_node *b);
5860
5861struct dm_config_node *make_text_node(struct dm_config_tree *cft,
5862 const char *key,
5863 const char *value,
5864 struct dm_config_node *parent,
5865 struct dm_config_node *pre_sib);
5866
5867struct dm_config_node *make_int_node(struct dm_config_tree *cft,
5868 const char *key,
5869 int64_t value,
5870 struct dm_config_node *parent,
5871 struct dm_config_node *pre_sib);
5872
5873struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
5874 struct dm_config_node *parent,
5875 struct dm_config_node *pre_sib,
5876 va_list ap);
5877struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
5878 struct dm_config_node *parent,
5879 struct dm_config_node *pre_sib,
5880 ...);
5881
5882struct dm_config_tree *config_tree_from_string_without_dup_node_check(const char *config_settings);
5883
5884#endif /* _LVM_DAEMON_CONFIG_UTIL_H */
5885\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001323\013062740170\0022323\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
5886#
5887# This file is part of the device-mapper userspace tools.
5888#
5889# This copyrighted material is made available to anyone wishing to use,
5890# modify, copy, or redistribute it subject to the terms and conditions
5891# of the GNU Lesser General Public License v.2.1.
5892#
5893# You should have received a copy of the GNU Lesser General Public License
5894# along with this program; if not, write to the Free Software Foundation,
5895# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5896
5897srcdir = @srcdir@
5898top_srcdir = @top_srcdir@
5899top_builddir = @top_builddir@
5900
5901LIB_STATIC = libdaemonclient.a
5902SOURCES = daemon-io.c config-util.c daemon-client.c
5903
5904include $(top_builddir)/make.tmpl
5905\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/daemon-client.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007303\013062740170\0023152\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
5906 * Copyright (C) 2011-2012 Red Hat, Inc.
5907 *
5908 * This file is part of LVM2.
5909 *
5910 * This copyrighted material is made available to anyone wishing to use,
5911 * modify, copy, or redistribute it subject to the terms and conditions
5912 * of the GNU Lesser General Public License v.2.1.
5913 *
5914 * You should have received a copy of the GNU Lesser General Public License
5915 * along with this program; if not, write to the Free Software Foundation,
5916 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5917 */
5918
5919#ifndef _LVM_DAEMON_CLIENT_H
5920#define _LVM_DAEMON_CLIENT_H
5921
5922#include "config-util.h"
5923
5924typedef struct {
5925 int socket_fd; /* the fd we use to talk to the daemon */
5926 const char *protocol;
5927 int protocol_version; /* version of the protocol the daemon uses */
5928 int error;
5929} daemon_handle;
5930
5931typedef struct {
5932 const char *path; /* the binary of the daemon */
5933 const char *socket; /* path to the comms socket */
5934 unsigned autostart:1; /* start the daemon if not running? */
5935
5936 /*
5937 * If the following are not NULL/0, an attempt to talk to a daemon which
5938 * uses a different protocol or version will fail.
5939 */
5940 const char *protocol;
5941 int protocol_version;
5942} daemon_info;
5943
5944typedef struct {
5945 struct buffer buffer;
5946 /*
5947 * The request looks like this:
5948 * request = "id"
5949 * arg_foo = "something"
5950 * arg_bar = 3
5951 * arg_wibble {
5952 * something_special = "here"
5953 * amount = 75
5954 * knobs = [ "twiddle", "tweak" ]
5955 * }
5956 */
5957 struct dm_config_tree *cft;
5958} daemon_request;
5959
5960typedef struct {
5961 int error; /* 0 for success */
5962 struct buffer buffer;
5963 struct dm_config_tree *cft; /* parsed reply, if available */
5964} daemon_reply;
5965
5966/*
5967 * Open the communication channel to the daemon. If the daemon is not running,
5968 * it may be autostarted based on the binary path provided in the info (this
5969 * will only happen if autostart is set to true). If the call fails for any
5970 * reason, daemon_handle_valid(h) for the response will return false. Otherwise,
5971 * the connection is good to start serving requests.
5972 */
5973daemon_handle daemon_open(daemon_info i);
5974
5975/*
5976 * Send a request to the daemon, waiting for the reply. All communication with
5977 * the daemon is synchronous. The function handles the IO details and parses the
5978 * response, handling common error conditions. See "daemon_reply" for details.
5979 *
5980 * In case the request contains a non-NULL buffer pointer, this buffer is sent
5981 * *verbatim* to the server. In this case, the cft pointer may be NULL (but will
5982 * be ignored even if non-NULL). If the buffer is NULL, the cft is required to
5983 * be a valid pointer, and is used to build up the request.
5984 */
5985daemon_reply daemon_send(daemon_handle h, daemon_request rq);
5986
5987/*
5988 * A simple interface to daemon_send. This function just takes the command id
5989 * and possibly a list of parameters (of the form "name = %?", "value"). The
5990 * type (string, integer) of the value is indicated by a character substituted
5991 * for ? in %?: d for integer, s for string.
5992 */
5993daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...);
5994daemon_reply daemon_send_simple_v(daemon_handle h, const char *id, va_list ap);
5995
5996daemon_request daemon_request_make(const char *id);
5997int daemon_request_extend(daemon_request r, ...);
5998int daemon_request_extend_v(daemon_request r, va_list ap);
5999void daemon_request_destroy(daemon_request r);
6000
6001void daemon_reply_destroy(daemon_reply r);
6002
6003static inline int64_t daemon_reply_int(daemon_reply r, const char *path, int64_t def)
6004{
6005 return dm_config_find_int64(r.cft->root, path, def);
6006}
6007
6008static inline const char *daemon_reply_str(daemon_reply r, const char *path, const char *def)
6009{
6010 return dm_config_find_str_allow_empty(r.cft->root, path, def);
6011}
6012
6013/* Shut down the communication to the daemon. Compulsory. */
6014void daemon_close(daemon_handle h);
6015
6016#endif
6017\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/daemon-client.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012273\013062740170\0023147\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
6018 * Copyright (C) 2011-2012 Red Hat, Inc.
6019 *
6020 * This file is part of LVM2.
6021 *
6022 * This copyrighted material is made available to anyone wishing to use,
6023 * modify, copy, or redistribute it subject to the terms and conditions
6024 * of the GNU Lesser General Public License v.2.1.
6025 *
6026 * You should have received a copy of the GNU Lesser General Public License
6027 * along with this program; if not, write to the Free Software Foundation,
6028 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6029 */
6030
6031#define _REENTRANT
6032
6033#include "tool.h"
6034
6035#include "daemon-io.h"
6036#include "daemon-client.h"
6037#include "dm-logging.h"
6038
6039#include <sys/un.h>
6040#include <sys/socket.h>
6041
6042daemon_handle daemon_open(daemon_info i)
6043{
6044 daemon_handle h = { .error = 0 };
6045 daemon_reply r = { 0 };
6046 struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
6047
6048 log_debug("%s: Opening daemon socket to %s for protocol %s version %d.",
6049 i.socket, i.path, i.protocol, i.protocol_version);
6050
6051 if ((h.socket_fd = socket(PF_UNIX, SOCK_STREAM /* | SOCK_NONBLOCK */, 0)) < 0) {
6052 h.error = errno;
6053 log_sys_error("socket", i.socket);
6054 goto error;
6055 }
6056
6057 if (!dm_strncpy(sockaddr.sun_path, i.socket, sizeof(sockaddr.sun_path))) {
6058 log_error("%s: Daemon socket path too long.", i.socket);
6059 goto error;
6060 }
6061
6062 if (connect(h.socket_fd,(struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
6063 h.error = errno;
6064 log_sys_error("connect", i.socket);
6065 goto error;
6066 }
6067
6068 log_debug("Sending daemon %s: hello", i.path);
6069 r = daemon_send_simple(h, "hello", NULL);
6070 if (r.error || strcmp(daemon_reply_str(r, "response", "unknown"), "OK")) {
6071 h.error = r.error;
6072 log_error("Daemon %s returned error %d", i.path, r.error);
6073 goto error;
6074 }
6075
6076 /* Check protocol and version matches */
6077 h.protocol = daemon_reply_str(r, "protocol", NULL);
6078 if (h.protocol)
6079 h.protocol = dm_strdup(h.protocol); /* keep around */
6080 h.protocol_version = daemon_reply_int(r, "version", 0);
6081
6082 if (i.protocol && (!h.protocol || strcmp(h.protocol, i.protocol))) {
6083 log_error("Daemon %s: requested protocol %s != %s",
6084 i.path, i.protocol, h.protocol ? : "");
6085 goto error;
6086 }
6087 if (i.protocol_version && h.protocol_version != i.protocol_version) {
6088 log_error("Daemon %s: requested protocol version %d != %d",
6089 i.path, i.protocol_version, h.protocol_version);
6090 goto error;
6091 }
6092
6093 daemon_reply_destroy(r);
6094 return h;
6095
6096error:
6097 if (h.socket_fd >= 0 && close(h.socket_fd))
6098 log_sys_error("close", "daemon_open");
6099 h.socket_fd = -1;
6100
6101 if (r.cft)
6102 daemon_reply_destroy(r);
6103
6104 dm_free((char *)h.protocol);
6105 h.protocol = NULL;
6106
6107 return h;
6108}
6109
6110daemon_reply daemon_send(daemon_handle h, daemon_request rq)
6111{
6112 struct buffer buffer;
6113 daemon_reply reply = { 0 };
6114
6115 if (h.socket_fd < 0) {
6116 log_error(INTERNAL_ERROR "Daemon send: socket fd cannot be negative %d", h.socket_fd);
6117 reply.error = EINVAL;
6118 return reply;
6119 }
6120
6121 buffer = rq.buffer;
6122
6123 if (!buffer.mem)
6124 if (!dm_config_write_node(rq.cft->root, buffer_line, &buffer)) {
6125 reply.error = ENOMEM;
6126 return reply;
6127 }
6128
6129 if (!buffer.mem) {
6130 log_error(INTERNAL_ERROR "Daemon send: no memory available");
6131 reply.error = ENOMEM;
6132 return reply;
6133 }
6134
6135 if (!buffer_write(h.socket_fd, &buffer))
6136 reply.error = errno;
6137
6138 if (buffer_read(h.socket_fd, &reply.buffer)) {
6139 reply.cft = config_tree_from_string_without_dup_node_check(reply.buffer.mem);
6140 if (!reply.cft)
6141 reply.error = EPROTO;
6142 } else
6143 reply.error = errno;
6144
6145 if (buffer.mem != rq.buffer.mem)
6146 buffer_destroy(&buffer);
6147
6148 return reply;
6149}
6150
6151void daemon_reply_destroy(daemon_reply r)
6152{
6153 if (r.cft)
6154 dm_config_destroy(r.cft);
6155 buffer_destroy(&r.buffer);
6156}
6157
6158daemon_reply daemon_send_simple_v(daemon_handle h, const char *id, va_list ap)
6159{
6160 static const daemon_reply err = { .error = ENOMEM };
6161 daemon_request rq = { .cft = NULL };
6162 daemon_reply repl;
6163 va_list apc;
6164
6165 va_copy(apc, ap);
6166 if (!buffer_append_f(&rq.buffer, "request = %s", id, NULL) ||
6167 !buffer_append_vf(&rq.buffer, apc)) {
6168 va_end(apc);
6169 buffer_destroy(&rq.buffer);
6170 return err;
6171 }
6172 va_end(apc);
6173
6174 repl = daemon_send(h, rq);
6175 buffer_destroy(&rq.buffer);
6176
6177 return repl;
6178}
6179
6180daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...)
6181{
6182 daemon_reply r;
6183 va_list ap;
6184
6185 va_start(ap, id);
6186 r = daemon_send_simple_v(h, id, ap);
6187 va_end(ap);
6188
6189 return r;
6190}
6191
6192void daemon_close(daemon_handle h)
6193{
6194 if (h.socket_fd >= 0) {
6195 log_debug("Closing daemon socket (fd %d).", h.socket_fd);
6196 if (close(h.socket_fd))
6197 log_sys_error("close", "daemon_close");
6198 }
6199
6200 dm_free((char *)h.protocol);
6201}
6202
6203daemon_request daemon_request_make(const char *id)
6204{
6205 daemon_request r;
6206
6207 buffer_init(&r.buffer);
6208
6209 if (!(r.cft = dm_config_create()))
6210 goto_bad;
6211
6212 if (!(r.cft->root = make_text_node(r.cft, "request", id, NULL, NULL)))
6213 goto_bad;
6214
6215 return r;
6216bad:
6217 if (r.cft) {
6218 dm_config_destroy(r.cft);
6219 r.cft = NULL;
6220 }
6221
6222 return r;
6223}
6224
6225int daemon_request_extend_v(daemon_request r, va_list ap)
6226{
6227 int res;
6228 va_list apc;
6229
6230 if (!r.cft)
6231 return 0;
6232
6233 va_copy(apc, ap);
6234 res = config_make_nodes_v(r.cft, NULL, r.cft->root, apc) ? 1 : 0;
6235 va_end(apc);
6236
6237 return res;
6238}
6239
6240int daemon_request_extend(daemon_request r, ...)
6241{
6242 int res;
6243 va_list ap;
6244
6245 va_start(ap, r);
6246 res = daemon_request_extend_v(r, ap);
6247 va_end(ap);
6248
6249 return res;
6250}
6251
6252void daemon_request_destroy(daemon_request r)
6253{
6254 if (r.cft)
6255 dm_config_destroy(r.cft);
6256 buffer_destroy(&r.buffer);
6257}
6258\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/daemon-io.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005576\013062740170\0022310\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
6259 * Copyright (C) 2011-2013 Red Hat, Inc.
6260 *
6261 * This file is part of LVM2.
6262 *
6263 * This copyrighted material is made available to anyone wishing to use,
6264 * modify, copy, or redistribute it subject to the terms and conditions
6265 * of the GNU Lesser General Public License v.2.1.
6266 *
6267 * You should have received a copy of the GNU Lesser General Public License
6268 * along with this program; if not, write to the Free Software Foundation,
6269 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6270 */
6271
6272#define _REENTRANT
6273
6274#include "tool.h"
6275
6276#include "daemon-io.h"
6277
6278#include <errno.h>
6279
6280/*
6281 * Read a single message from a (socket) filedescriptor. Messages are delimited
6282 * by blank lines. This call will block until all of a message is received. The
6283 * memory will be allocated from heap. Upon error, all memory is freed and the
6284 * buffer pointer is set to NULL.
6285 *
6286 * See also write_buffer about blocking (read_buffer has identical behaviour).
6287 */
6288int buffer_read(int fd, struct buffer *buffer) {
6289 int result;
6290
6291 if (!buffer_realloc(buffer, 32)) /* ensure we have some space */
6292 return 0;
6293
6294 while (1) {
6295 result = read(fd, buffer->mem + buffer->used, buffer->allocated - buffer->used);
6296 if (result > 0) {
6297 buffer->used += result;
6298 if (buffer->used >= 4 && !strncmp((buffer->mem) + buffer->used - 4, "\n##\n", 4)) {
6299 buffer->used -= 4;
6300 buffer->mem[buffer->used] = 0;
6301 break; /* success, we have the full message now */
6302 }
6303 if ((buffer->allocated - buffer->used < 32) &&
6304 !buffer_realloc(buffer, 1024))
6305 return 0;
6306 } else if (result == 0) {
6307 errno = ECONNRESET;
6308 return 0; /* we should never encounter EOF here */
6309 } else if (result < 0 && (errno == EAGAIN ||
6310 (EWOULDBLOCK != EAGAIN && errno == EWOULDBLOCK) ||
6311 errno == EINTR || errno == EIO)) {
6312 fd_set in;
6313 FD_ZERO(&in);
6314 FD_SET(fd, &in);
6315 /* ignore the result, this is just a glorified sleep */
6316 select(FD_SETSIZE, &in, NULL, NULL, NULL);
6317 } else if (result < 0)
6318 return 0;
6319 }
6320
6321 return 1;
6322}
6323
6324/*
6325 * Write a buffer to a filedescriptor. Keep trying. Blocks (even on
6326 * SOCK_NONBLOCK) until all of the write went through.
6327 */
6328int buffer_write(int fd, const struct buffer *buffer) {
6329 static const struct buffer _terminate = { .mem = (char *) "\n##\n", .used = 4 };
6330 const struct buffer *use;
6331 int done, written, result;
6332
6333 for (done = 0; done < 2; ++done) {
6334 use = (done == 0) ? buffer : &_terminate;
6335 for (written = 0; written < use->used;) {
6336 result = write(fd, use->mem + written, use->used - written);
6337 if (result > 0)
6338 written += result;
6339 else if (result < 0 && (errno == EAGAIN ||
6340 (EWOULDBLOCK != EAGAIN && errno == EWOULDBLOCK) ||
6341 errno == EINTR || errno == EIO)) {
6342 fd_set out;
6343 FD_ZERO(&out);
6344 FD_SET(fd, &out);
6345 /* ignore the result, this is just a glorified sleep */
6346 select(FD_SETSIZE, NULL, &out, NULL, NULL);
6347 } else if (result < 0)
6348 return 0; /* too bad */
6349 }
6350 }
6351
6352 return 1;
6353}
6354\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/client/config-util.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000022024\013062740170\0022643\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
6355 * Copyright (C) 2011-2012 Red Hat, Inc.
6356 *
6357 * This file is part of LVM2.
6358 *
6359 * This copyrighted material is made available to anyone wishing to use,
6360 * modify, copy, or redistribute it subject to the terms and conditions
6361 * of the GNU Lesser General Public License v.2.1.
6362 *
6363 * You should have received a copy of the GNU Lesser General Public License
6364 * along with this program; if not, write to the Free Software Foundation,
6365 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6366 */
6367
6368#define _REENTRANT
6369
6370#include "tool.h"
6371
6372#include "daemon-io.h"
6373#include "dm-logging.h"
6374
6375#include <math.h> /* fabs() */
6376#include <float.h> /* DBL_EPSILON */
6377
6378int buffer_append_vf(struct buffer *buf, va_list ap)
6379{
6380 char *append;
6381 char *next;
6382 int keylen;
6383 int64_t value;
6384 char *string;
6385 char *block;
6386
6387 while ((next = va_arg(ap, char *))) {
6388 append = NULL;
6389 if (!strchr(next, '=')) {
6390 log_error(INTERNAL_ERROR "Bad format string at '%s'", next);
6391 goto fail;
6392 }
6393 keylen = strchr(next, '=') - next;
6394 if (strstr(next, "%d")) {
6395 /* Use of plain %d is prohibited, use FMTd64 */
6396 log_error(INTERNAL_ERROR "Do not use %%d and use correct 64bit form");
6397 goto fail;
6398 }
6399 if (strstr(next, FMTd64)) {
6400 value = va_arg(ap, int64_t);
6401 if (dm_asprintf(&append, "%.*s= %" PRId64 "\n", keylen, next, value) < 0)
6402 goto fail;
6403 } else if (strstr(next, "%s")) {
6404 string = va_arg(ap, char *);
6405 if (dm_asprintf(&append, "%.*s= \"%s\"\n", keylen, next, string) < 0)
6406 goto fail;
6407 } else if (strstr(next, "%b")) {
6408 if (!(block = va_arg(ap, char *)))
6409 continue;
6410 if (dm_asprintf(&append, "%.*s%s", keylen, next, block) < 0)
6411 goto fail;
6412 } else if (dm_asprintf(&append, "%s", next) < 0)
6413 goto fail;
6414
6415 if (!append ||
6416 !buffer_append(buf, append))
6417 goto fail;
6418
6419 dm_free(append);
6420 }
6421
6422 return 1;
6423fail:
6424 dm_free(append);
6425 return 0;
6426}
6427
6428int buffer_append_f(struct buffer *buf, ...)
6429{
6430 int res;
6431 va_list ap;
6432
6433 va_start(ap, buf);
6434 res = buffer_append_vf(buf, ap);
6435 va_end(ap);
6436
6437 return res;
6438}
6439
6440int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,
6441 const char *field, const char *flag, int want)
6442{
6443 struct dm_config_value *value = NULL, *pred = NULL;
6444 struct dm_config_node *node = dm_config_find_node(parent->child, field);
6445 struct dm_config_value *new;
6446
6447 if (node)
6448 value = node->v;
6449
6450 while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) {
6451 pred = value;
6452 value = value->next;
6453 }
6454
6455 if (value && want)
6456 return 1;
6457
6458 if (!value && !want)
6459 return 1;
6460
6461 if (value && !want) {
6462 if (pred) {
6463 pred->next = value->next;
6464 } else if (value == node->v && value->next) {
6465 node->v = value->next;
6466 } else {
6467 node->v->type = DM_CFG_EMPTY_ARRAY;
6468 }
6469 }
6470
6471 if (!value && want) {
6472 if (!node) {
6473 if (!(node = dm_config_create_node(cft, field)))
6474 return 0;
6475 node->sib = parent->child;
6476 if (!(node->v = dm_config_create_value(cft)))
6477 return 0;
6478 node->v->type = DM_CFG_EMPTY_ARRAY;
6479 node->parent = parent;
6480 parent->child = node;
6481 }
6482 if (!(new = dm_config_create_value(cft))) {
6483 /* FIXME error reporting */
6484 return 0;
6485 }
6486 new->type = DM_CFG_STRING;
6487 new->v.str = flag;
6488 new->next = node->v;
6489 node->v = new;
6490 }
6491
6492 return 1;
6493}
6494
6495void chain_node(struct dm_config_node *cn,
6496 struct dm_config_node *parent,
6497 struct dm_config_node *pre_sib)
6498{
6499 cn->parent = parent;
6500 cn->sib = NULL;
6501
6502 if (parent && parent->child && !pre_sib) { /* find the last one */
6503 pre_sib = parent->child;
6504 while (pre_sib && pre_sib->sib)
6505 pre_sib = pre_sib->sib;
6506 }
6507
6508 if (parent && !parent->child)
6509 parent->child = cn;
6510 if (pre_sib) {
6511 cn->sib = pre_sib->sib;
6512 pre_sib->sib = cn;
6513 }
6514
6515}
6516
6517struct dm_config_tree *config_tree_from_string_without_dup_node_check(const char *config_settings)
6518{
6519 struct dm_config_tree *cft;
6520
6521 if (!(cft = dm_config_create()))
6522 return_NULL;
6523
6524 if (!dm_config_parse_without_dup_node_check(cft, config_settings, config_settings + strlen(config_settings))) {
6525 dm_config_destroy(cft);
6526 return_NULL;
6527 }
6528
6529 return cft;
6530}
6531
6532struct dm_config_node *make_config_node(struct dm_config_tree *cft,
6533 const char *key,
6534 struct dm_config_node *parent,
6535 struct dm_config_node *pre_sib)
6536{
6537 struct dm_config_node *cn;
6538
6539 if (!(cn = dm_config_create_node(cft, key)))
6540 return NULL;
6541
6542 cn->v = NULL;
6543 cn->child = NULL;
6544
6545 chain_node(cn, parent, pre_sib);
6546
6547 return cn;
6548}
6549
6550struct dm_config_node *make_text_node(struct dm_config_tree *cft,
6551 const char *key,
6552 const char *value,
6553 struct dm_config_node *parent,
6554 struct dm_config_node *pre_sib)
6555{
6556 struct dm_config_node *cn;
6557
6558 if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
6559 !(cn->v = dm_config_create_value(cft)))
6560 return NULL;
6561
6562 cn->v->type = DM_CFG_STRING;
6563 cn->v->v.str = value;
6564 return cn;
6565}
6566
6567struct dm_config_node *make_int_node(struct dm_config_tree *cft,
6568 const char *key,
6569 int64_t value,
6570 struct dm_config_node *parent,
6571 struct dm_config_node *pre_sib)
6572{
6573 struct dm_config_node *cn;
6574
6575 if (!(cn = make_config_node(cft, key, parent, pre_sib)) ||
6576 !(cn->v = dm_config_create_value(cft)))
6577 return NULL;
6578
6579 cn->v->type = DM_CFG_INT;
6580 cn->v->v.i = value;
6581 return cn;
6582}
6583
6584/*
6585 * FIXME: return 1 even if VA list is empty and return the
6586 * dm_config_node* result as output parameter
6587 */
6588struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,
6589 struct dm_config_node *parent,
6590 struct dm_config_node *pre_sib,
6591 va_list ap)
6592{
6593 const char *next;
6594 struct dm_config_node *first = NULL;
6595 struct dm_config_node *cn;
6596 const char *fmt;
6597 char *key;
6598
6599 while ((next = va_arg(ap, char *))) {
6600 cn = NULL;
6601 fmt = strchr(next, '=');
6602
6603 if (!fmt) {
6604 log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
6605 return NULL;
6606 }
6607
6608 if (!(key = dm_pool_strdup(cft->mem, next))) {
6609 log_error("Failed to duplicate node key.");
6610 return NULL;
6611 }
6612
6613 key[fmt - next] = '\0';
6614 fmt += 2;
6615
6616 if (!strcmp(fmt, "%d") || !strcmp(fmt, FMTd64)) {
6617 int64_t value = va_arg(ap, int64_t);
6618 if (!(cn = make_int_node(cft, key, value, parent, pre_sib)))
6619 return 0;
6620 } else if (!strcmp(fmt, "%s")) {
6621 char *value = va_arg(ap, char *);
6622 if (!(cn = make_text_node(cft, key, value, parent, pre_sib)))
6623 return 0;
6624 } else if (!strcmp(fmt, "%t")) {
6625 struct dm_config_tree *tree = va_arg(ap, struct dm_config_tree *);
6626 cn = dm_config_clone_node(cft, tree->root, 1);
6627 if (!cn)
6628 return 0;
6629 cn->key = key;
6630 chain_node(cn, parent, pre_sib);
6631 } else {
6632 log_error(INTERNAL_ERROR "Bad format string '%s'", fmt);
6633 return NULL;
6634 }
6635 if (!first)
6636 first = cn;
6637 if (cn)
6638 pre_sib = cn;
6639 }
6640
6641 return first;
6642}
6643
6644struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,
6645 struct dm_config_node *parent,
6646 struct dm_config_node *pre_sib,
6647 ...)
6648{
6649 struct dm_config_node *res;
6650 va_list ap;
6651
6652 va_start(ap, pre_sib);
6653 res = config_make_nodes_v(cft, parent, pre_sib, ap);
6654 va_end(ap);
6655
6656 return res;
6657}
6658
6659/* Test if the doubles are close enough to be considered equal */
6660static int close_enough(double d1, double d2)
6661{
6662 return fabs(d1 - d2) < DBL_EPSILON;
6663}
6664
6665int compare_value(struct dm_config_value *a, struct dm_config_value *b)
6666{
6667 int r = 0;
6668
6669 if (a->type > b->type)
6670 return 1;
6671 if (a->type < b->type)
6672 return -1;
6673
6674 switch (a->type) {
6675 case DM_CFG_STRING: r = strcmp(a->v.str, b->v.str); break;
6676 case DM_CFG_FLOAT: r = close_enough(a->v.f, b->v.f) ? 0 : (a->v.f > b->v.f) ? 1 : -1; break;
6677 case DM_CFG_INT: r = (a->v.i == b->v.i) ? 0 : (a->v.i > b->v.i) ? 1 : -1; break;
6678 case DM_CFG_EMPTY_ARRAY: return 0;
6679 }
6680
6681 if (r == 0 && a->next && b->next)
6682 r = compare_value(a->next, b->next);
6683 return r;
6684}
6685
6686int compare_config(struct dm_config_node *a, struct dm_config_node *b)
6687{
6688 int result = 0;
6689 if (a->v && b->v)
6690 result = compare_value(a->v, b->v);
6691 if (a->v && !b->v)
6692 result = 1;
6693 if (!a->v && b->v)
6694 result = -1;
6695 if (a->child && b->child)
6696 result = compare_config(a->child, b->child);
6697
6698 if (result) {
6699 // DEBUGLOG("config inequality at %s / %s", a->key, b->key);
6700 return result;
6701 }
6702
6703 if (a->sib && b->sib)
6704 result = compare_config(a->sib, b->sib);
6705 if (a->sib && !b->sib)
6706 result = 1;
6707 if (!a->sib && b->sib)
6708 result = -1;
6709
6710 return result;
6711}
6712
6713int buffer_realloc(struct buffer *buf, int needed)
6714{
6715 char *new;
6716 int alloc = buf->allocated;
6717 if (alloc < needed)
6718 alloc = needed;
6719
6720 buf->allocated += alloc;
6721 new = dm_realloc(buf->mem, buf->allocated);
6722 if (new)
6723 buf->mem = new;
6724 else { /* utter failure */
6725 dm_free(buf->mem);
6726 buf->mem = 0;
6727 buf->allocated = buf->used = 0;
6728 return 0;
6729 }
6730 return 1;
6731}
6732
6733int buffer_append(struct buffer *buf, const char *string)
6734{
6735 int len = strlen(string);
6736
6737 if ((!buf->mem || (buf->allocated - buf->used <= len)) &&
6738 !buffer_realloc(buf, len + 1))
6739 return 0;
6740
6741 strcpy(buf->mem + buf->used, string);
6742 buf->used += len;
6743 return 1;
6744}
6745
6746int buffer_line(const char *line, void *baton)
6747{
6748 struct buffer *buf = baton;
6749 if (!buffer_append(buf, line))
6750 return 0;
6751 if (!buffer_append(buf, "\n"))
6752 return 0;
6753 return 1;
6754}
6755
6756void buffer_destroy(struct buffer *buf)
6757{
6758 dm_free(buf->mem);
6759 buffer_init(buf);
6760}
6761
6762void buffer_init(struct buffer *buf)
6763{
6764 buf->allocated = buf->used = 0;
6765 buf->mem = 0;
6766}
6767\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/libdaemon/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001516\013062740170\0021051\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
6768# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
6769#
6770# This file is part of LVM2.
6771#
6772# This copyrighted material is made available to anyone wishing to use,
6773# modify, copy, or redistribute it subject to the terms and conditions
6774# of the GNU General Public License v.2.
6775#
6776# You should have received a copy of the GNU General Public License
6777# along with this program; if not, write to the Free Software Foundation,
6778# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6779
6780srcdir = @srcdir@
6781top_srcdir = @top_srcdir@
6782top_builddir = @top_builddir@
6783
6784.PHONY: client server
6785
6786SUBDIRS += client
6787
6788ifeq (@BUILD_LVMETAD@,yes)
6789 SUBDIRS += server
6790server: client
6791else ifeq (@BUILD_LVMPOLLD@,yes)
6792 SUBDIRS += server
6793server: client
6794endif
6795
6796ifeq ($(MAKECMDGOALS),distclean)
6797 SUBDIRS = client server
6798endif
6799
6800include $(top_builddir)/make.tmpl
6801\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/aclocal.m4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000046132\013062740170\0016715\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# generated automatically by aclocal 1.15 -*- Autoconf -*-
6802
6803# Copyright (C) 1996-2014 Free Software Foundation, Inc.
6804
6805# This file is free software; the Free Software Foundation
6806# gives unlimited permission to copy and/or distribute it,
6807# with or without modifications, as long as this notice is preserved.
6808
6809# This program is distributed in the hope that it will be useful,
6810# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
6811# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6812# PARTICULAR PURPOSE.
6813
6814m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
6815# ===========================================================================
6816# http://www.gnu.org/software/autoconf-archive/ax_python_module.html
6817# ===========================================================================
6818#
6819# SYNOPSIS
6820#
6821# AX_PYTHON_MODULE(modname[, fatal, python])
6822#
6823# DESCRIPTION
6824#
6825# Checks for Python module.
6826#
6827# If fatal is non-empty then absence of a module will trigger an error.
6828# The third parameter can either be "python" for Python 2 or "python3" for
6829# Python 3; defaults to Python 3.
6830#
6831# LICENSE
6832#
6833# Copyright (c) 2008 Andrew Collier
6834#
6835# Copying and distribution of this file, with or without modification, are
6836# permitted in any medium without royalty provided the copyright notice
6837# and this notice are preserved. This file is offered as-is, without any
6838# warranty.
6839
6840#serial 8
6841
6842AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
6843AC_DEFUN([AX_PYTHON_MODULE],[
6844 if test -z $PYTHON;
6845 then
6846 if test -z "$3";
6847 then
6848 PYTHON="python3"
6849 else
6850 PYTHON="$3"
6851 fi
6852 fi
6853 PYTHON_NAME=`basename $PYTHON`
6854 AC_MSG_CHECKING($PYTHON_NAME module: $1)
6855 $PYTHON -c "import $1" 2>/dev/null
6856 if test $? -eq 0;
6857 then
6858 AC_MSG_RESULT(yes)
6859 eval AS_TR_CPP(HAVE_PYMOD_$1)=yes
6860 else
6861 AC_MSG_RESULT(no)
6862 eval AS_TR_CPP(HAVE_PYMOD_$1)=no
6863 #
6864 if test -n "$2"
6865 then
6866 AC_MSG_ERROR(failed to find required module $1)
6867 exit 1
6868 fi
6869 fi
6870])
6871
6872# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
6873# serial 1 (pkg-config-0.24)
6874#
6875# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
6876#
6877# This program is free software; you can redistribute it and/or modify
6878# it under the terms of the GNU General Public License as published by
6879# the Free Software Foundation; either version 2 of the License, or
6880# (at your option) any later version.
6881#
6882# This program is distributed in the hope that it will be useful, but
6883# WITHOUT ANY WARRANTY; without even the implied warranty of
6884# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6885# General Public License for more details.
6886#
6887# You should have received a copy of the GNU General Public License
6888# along with this program; if not, write to the Free Software
6889# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6890#
6891# As a special exception to the GNU General Public License, if you
6892# distribute this file as part of a program that contains a
6893# configuration script generated by Autoconf, you may include it under
6894# the same distribution terms that you use for the rest of that program.
6895
6896# PKG_PROG_PKG_CONFIG([MIN-VERSION])
6897# ----------------------------------
6898AC_DEFUN([PKG_PROG_PKG_CONFIG],
6899[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
6900m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
6901m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
6902AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
6903AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
6904AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
6905
6906if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
6907 AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
6908fi
6909if test -n "$PKG_CONFIG"; then
6910 _pkg_min_version=m4_default([$1], [0.9.0])
6911 AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
6912 if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
6913 AC_MSG_RESULT([yes])
6914 else
6915 AC_MSG_RESULT([no])
6916 PKG_CONFIG=""
6917 fi
6918fi[]dnl
6919])# PKG_PROG_PKG_CONFIG
6920
6921# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
6922#
6923# Check to see whether a particular set of modules exists. Similar
6924# to PKG_CHECK_MODULES(), but does not set variables or print errors.
6925#
6926# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
6927# only at the first occurence in configure.ac, so if the first place
6928# it's called might be skipped (such as if it is within an "if", you
6929# have to call PKG_CHECK_EXISTS manually
6930# --------------------------------------------------------------
6931AC_DEFUN([PKG_CHECK_EXISTS],
6932[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
6933if test -n "$PKG_CONFIG" && \
6934 AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
6935 m4_default([$2], [:])
6936m4_ifvaln([$3], [else
6937 $3])dnl
6938fi])
6939
6940# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
6941# ---------------------------------------------
6942m4_define([_PKG_CONFIG],
6943[if test -n "$$1"; then
6944 pkg_cv_[]$1="$$1"
6945 elif test -n "$PKG_CONFIG"; then
6946 PKG_CHECK_EXISTS([$3],
6947 [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
6948 test "x$?" != "x0" && pkg_failed=yes ],
6949 [pkg_failed=yes])
6950 else
6951 pkg_failed=untried
6952fi[]dnl
6953])# _PKG_CONFIG
6954
6955# _PKG_SHORT_ERRORS_SUPPORTED
6956# -----------------------------
6957AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
6958[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
6959if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
6960 _pkg_short_errors_supported=yes
6961else
6962 _pkg_short_errors_supported=no
6963fi[]dnl
6964])# _PKG_SHORT_ERRORS_SUPPORTED
6965
6966
6967# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
6968# [ACTION-IF-NOT-FOUND])
6969#
6970#
6971# Note that if there is a possibility the first call to
6972# PKG_CHECK_MODULES might not happen, you should be sure to include an
6973# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
6974#
6975#
6976# --------------------------------------------------------------
6977AC_DEFUN([PKG_CHECK_MODULES],
6978[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
6979AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
6980AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
6981
6982pkg_failed=no
6983AC_MSG_CHECKING([for $1])
6984
6985_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
6986_PKG_CONFIG([$1][_LIBS], [libs], [$2])
6987
6988m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
6989and $1[]_LIBS to avoid the need to call pkg-config.
6990See the pkg-config man page for more details.])
6991
6992if test $pkg_failed = yes; then
6993 AC_MSG_RESULT([no])
6994 _PKG_SHORT_ERRORS_SUPPORTED
6995 if test $_pkg_short_errors_supported = yes; then
6996 $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
6997 else
6998 $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
6999 fi
7000 # Put the nasty error message in config.log where it belongs
7001 echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
7002
7003 m4_default([$4], [AC_MSG_ERROR(
7004[Package requirements ($2) were not met:
7005
7006$$1_PKG_ERRORS
7007
7008Consider adjusting the PKG_CONFIG_PATH environment variable if you
7009installed software in a non-standard prefix.
7010
7011_PKG_TEXT])[]dnl
7012 ])
7013elif test $pkg_failed = untried; then
7014 AC_MSG_RESULT([no])
7015 m4_default([$4], [AC_MSG_FAILURE(
7016[The pkg-config script could not be found or is too old. Make sure it
7017is in your PATH or set the PKG_CONFIG environment variable to the full
7018path to pkg-config.
7019
7020_PKG_TEXT
7021
7022To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
7023 ])
7024else
7025 $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
7026 $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
7027 AC_MSG_RESULT([yes])
7028 $3
7029fi[]dnl
7030])# PKG_CHECK_MODULES
7031
7032
7033# PKG_INSTALLDIR(DIRECTORY)
7034# -------------------------
7035# Substitutes the variable pkgconfigdir as the location where a module
7036# should install pkg-config .pc files. By default the directory is
7037# $libdir/pkgconfig, but the default can be changed by passing
7038# DIRECTORY. The user can override through the --with-pkgconfigdir
7039# parameter.
7040AC_DEFUN([PKG_INSTALLDIR],
7041[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
7042m4_pushdef([pkg_description],
7043 [pkg-config installation directory @<:@]pkg_default[@:>@])
7044AC_ARG_WITH([pkgconfigdir],
7045 [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
7046 [with_pkgconfigdir=]pkg_default)
7047AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
7048m4_popdef([pkg_default])
7049m4_popdef([pkg_description])
7050]) dnl PKG_INSTALLDIR
7051
7052
7053# PKG_NOARCH_INSTALLDIR(DIRECTORY)
7054# -------------------------
7055# Substitutes the variable noarch_pkgconfigdir as the location where a
7056# module should install arch-independent pkg-config .pc files. By
7057# default the directory is $datadir/pkgconfig, but the default can be
7058# changed by passing DIRECTORY. The user can override through the
7059# --with-noarch-pkgconfigdir parameter.
7060AC_DEFUN([PKG_NOARCH_INSTALLDIR],
7061[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
7062m4_pushdef([pkg_description],
7063 [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
7064AC_ARG_WITH([noarch-pkgconfigdir],
7065 [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
7066 [with_noarch_pkgconfigdir=]pkg_default)
7067AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
7068m4_popdef([pkg_default])
7069m4_popdef([pkg_description])
7070]) dnl PKG_NOARCH_INSTALLDIR
7071
7072
7073# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
7074# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
7075# -------------------------------------------
7076# Retrieves the value of the pkg-config variable for the given module.
7077AC_DEFUN([PKG_CHECK_VAR],
7078[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
7079AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
7080
7081_PKG_CONFIG([$1], [variable="][$3]["], [$2])
7082AS_VAR_COPY([$1], [pkg_cv_][$1])
7083
7084AS_VAR_IF([$1], [""], [$5], [$4])dnl
7085])# PKG_CHECK_VAR
7086
7087# Copyright (C) 1999-2014 Free Software Foundation, Inc.
7088#
7089# This file is free software; the Free Software Foundation
7090# gives unlimited permission to copy and/or distribute it,
7091# with or without modifications, as long as this notice is preserved.
7092
7093
7094# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
7095# ---------------------------------------------------------------------------
7096# Adds support for distributing Python modules and packages. To
7097# install modules, copy them to $(pythondir), using the python_PYTHON
7098# automake variable. To install a package with the same name as the
7099# automake package, install to $(pkgpythondir), or use the
7100# pkgpython_PYTHON automake variable.
7101#
7102# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
7103# locations to install python extension modules (shared libraries).
7104# Another macro is required to find the appropriate flags to compile
7105# extension modules.
7106#
7107# If your package is configured with a different prefix to python,
7108# users will have to add the install directory to the PYTHONPATH
7109# environment variable, or create a .pth file (see the python
7110# documentation for details).
7111#
7112# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
7113# cause an error if the version of python installed on the system
7114# doesn't meet the requirement. MINIMUM-VERSION should consist of
7115# numbers and dots only.
7116AC_DEFUN([AM_PATH_PYTHON],
7117 [
7118 dnl Find a Python interpreter. Python versions prior to 2.0 are not
7119 dnl supported. (2.0 was released on October 16, 2000).
7120 m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
7121[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
7122 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
7123
7124 AC_ARG_VAR([PYTHON], [the Python interpreter])
7125
7126 m4_if([$1],[],[
7127 dnl No version check is needed.
7128 # Find any Python interpreter.
7129 if test -z "$PYTHON"; then
7130 AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
7131 fi
7132 am_display_PYTHON=python
7133 ], [
7134 dnl A version check is needed.
7135 if test -n "$PYTHON"; then
7136 # If the user set $PYTHON, use it and don't search something else.
7137 AC_MSG_CHECKING([whether $PYTHON version is >= $1])
7138 AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
7139 [AC_MSG_RESULT([yes])],
7140 [AC_MSG_RESULT([no])
7141 AC_MSG_ERROR([Python interpreter is too old])])
7142 am_display_PYTHON=$PYTHON
7143 else
7144 # Otherwise, try each interpreter until we find one that satisfies
7145 # VERSION.
7146 AC_CACHE_CHECK([for a Python interpreter with version >= $1],
7147 [am_cv_pathless_PYTHON],[
7148 for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
7149 test "$am_cv_pathless_PYTHON" = none && break
7150 AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
7151 done])
7152 # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
7153 if test "$am_cv_pathless_PYTHON" = none; then
7154 PYTHON=:
7155 else
7156 AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
7157 fi
7158 am_display_PYTHON=$am_cv_pathless_PYTHON
7159 fi
7160 ])
7161
7162 if test "$PYTHON" = :; then
7163 dnl Run any user-specified action, or abort.
7164 m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
7165 else
7166
7167 dnl Query Python for its version number. Getting [:3] seems to be
7168 dnl the best way to do this; it's what "site.py" does in the standard
7169 dnl library.
7170
7171 AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
7172 [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
7173 AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
7174
7175 dnl Use the values of $prefix and $exec_prefix for the corresponding
7176 dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
7177 dnl distinct variables so they can be overridden if need be. However,
7178 dnl general consensus is that you shouldn't need this ability.
7179
7180 AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
7181 AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
7182
7183 dnl At times (like when building shared libraries) you may want
7184 dnl to know which OS platform Python thinks this is.
7185
7186 AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
7187 [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
7188 AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
7189
7190 # Just factor out some code duplication.
7191 am_python_setup_sysconfig="\
7192import sys
7193# Prefer sysconfig over distutils.sysconfig, for better compatibility
7194# with python 3.x. See automake bug#10227.
7195try:
7196 import sysconfig
7197except ImportError:
7198 can_use_sysconfig = 0
7199else:
7200 can_use_sysconfig = 1
7201# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
7202# <https://github.com/pypa/virtualenv/issues/118>
7203try:
7204 from platform import python_implementation
7205 if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
7206 can_use_sysconfig = 0
7207except ImportError:
7208 pass"
7209
7210 dnl Set up 4 directories:
7211
7212 dnl pythondir -- where to install python scripts. This is the
7213 dnl site-packages directory, not the python standard library
7214 dnl directory like in previous automake betas. This behavior
7215 dnl is more consistent with lispdir.m4 for example.
7216 dnl Query distutils for this directory.
7217 AC_CACHE_CHECK([for $am_display_PYTHON script directory],
7218 [am_cv_python_pythondir],
7219 [if test "x$prefix" = xNONE
7220 then
7221 am_py_prefix=$ac_default_prefix
7222 else
7223 am_py_prefix=$prefix
7224 fi
7225 am_cv_python_pythondir=`$PYTHON -c "
7226$am_python_setup_sysconfig
7227if can_use_sysconfig:
7228 sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
7229else:
7230 from distutils import sysconfig
7231 sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
7232sys.stdout.write(sitedir)"`
7233 case $am_cv_python_pythondir in
7234 $am_py_prefix*)
7235 am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
7236 am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
7237 ;;
7238 *)
7239 case $am_py_prefix in
7240 /usr|/System*) ;;
7241 *)
7242 am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
7243 ;;
7244 esac
7245 ;;
7246 esac
7247 ])
7248 AC_SUBST([pythondir], [$am_cv_python_pythondir])
7249
7250 dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
7251 dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
7252 dnl more consistent with the rest of automake.
7253
7254 AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
7255
7256 dnl pyexecdir -- directory for installing python extension modules
7257 dnl (shared libraries)
7258 dnl Query distutils for this directory.
7259 AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
7260 [am_cv_python_pyexecdir],
7261 [if test "x$exec_prefix" = xNONE
7262 then
7263 am_py_exec_prefix=$am_py_prefix
7264 else
7265 am_py_exec_prefix=$exec_prefix
7266 fi
7267 am_cv_python_pyexecdir=`$PYTHON -c "
7268$am_python_setup_sysconfig
7269if can_use_sysconfig:
7270 sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
7271else:
7272 from distutils import sysconfig
7273 sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
7274sys.stdout.write(sitedir)"`
7275 case $am_cv_python_pyexecdir in
7276 $am_py_exec_prefix*)
7277 am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
7278 am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
7279 ;;
7280 *)
7281 case $am_py_exec_prefix in
7282 /usr|/System*) ;;
7283 *)
7284 am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
7285 ;;
7286 esac
7287 ;;
7288 esac
7289 ])
7290 AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
7291
7292 dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
7293
7294 AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
7295
7296 dnl Run any user-specified action.
7297 $2
7298 fi
7299
7300])
7301
7302
7303# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
7304# ---------------------------------------------------------------------------
7305# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
7306# Run ACTION-IF-FALSE otherwise.
7307# This test uses sys.hexversion instead of the string equivalent (first
7308# word of sys.version), in order to cope with versions such as 2.2c1.
7309# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
7310AC_DEFUN([AM_PYTHON_CHECK_VERSION],
7311 [prog="import sys
7312# split strings by '.' and convert to numeric. Append some zeros
7313# because we need at least 4 digits for the hex conversion.
7314# map returns an iterator in Python 3.0 and a list in 2.x
7315minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
7316minverhex = 0
7317# xrange is not present in Python 3.0 and range returns an iterator
7318for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
7319sys.exit(sys.hexversion < minverhex)"
7320 AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
7321
7322# Copyright (C) 2001-2014 Free Software Foundation, Inc.
7323#
7324# This file is free software; the Free Software Foundation
7325# gives unlimited permission to copy and/or distribute it,
7326# with or without modifications, as long as this notice is preserved.
7327
7328# AM_RUN_LOG(COMMAND)
7329# -------------------
7330# Run COMMAND, save the exit status in ac_status, and log it.
7331# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
7332AC_DEFUN([AM_RUN_LOG],
7333[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
7334 ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
7335 ac_status=$?
7336 echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
7337 (exit $ac_status); }])
7338
7339m4_include([acinclude.m4])
7340\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/COPYING.LIB\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000063504\013062740170\0016517\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 GNU LESSER GENERAL PUBLIC LICENSE
7341 Version 2.1, February 1999
7342
7343 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
7344 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7345 Everyone is permitted to copy and distribute verbatim copies
7346 of this license document, but changing it is not allowed.
7347
7348[This is the first released version of the Lesser GPL. It also counts
7349 as the successor of the GNU Library Public License, version 2, hence
7350 the version number 2.1.]
7351
7352 Preamble
7353
7354 The licenses for most software are designed to take away your
7355freedom to share and change it. By contrast, the GNU General Public
7356Licenses are intended to guarantee your freedom to share and change
7357free software--to make sure the software is free for all its users.
7358
7359 This license, the Lesser General Public License, applies to some
7360specially designated software packages--typically libraries--of the
7361Free Software Foundation and other authors who decide to use it. You
7362can use it too, but we suggest you first think carefully about whether
7363this license or the ordinary General Public License is the better
7364strategy to use in any particular case, based on the explanations below.
7365
7366 When we speak of free software, we are referring to freedom of use,
7367not price. Our General Public Licenses are designed to make sure that
7368you have the freedom to distribute copies of free software (and charge
7369for this service if you wish); that you receive source code or can get
7370it if you want it; that you can change the software and use pieces of
7371it in new free programs; and that you are informed that you can do
7372these things.
7373
7374 To protect your rights, we need to make restrictions that forbid
7375distributors to deny you these rights or to ask you to surrender these
7376rights. These restrictions translate to certain responsibilities for
7377you if you distribute copies of the library or if you modify it.
7378
7379 For example, if you distribute copies of the library, whether gratis
7380or for a fee, you must give the recipients all the rights that we gave
7381you. You must make sure that they, too, receive or can get the source
7382code. If you link other code with the library, you must provide
7383complete object files to the recipients, so that they can relink them
7384with the library after making changes to the library and recompiling
7385it. And you must show them these terms so they know their rights.
7386
7387 We protect your rights with a two-step method: (1) we copyright the
7388library, and (2) we offer you this license, which gives you legal
7389permission to copy, distribute and/or modify the library.
7390
7391 To protect each distributor, we want to make it very clear that
7392there is no warranty for the free library. Also, if the library is
7393modified by someone else and passed on, the recipients should know
7394that what they have is not the original version, so that the original
7395author's reputation will not be affected by problems that might be
7396introduced by others.
7397\f
7398 Finally, software patents pose a constant threat to the existence of
7399any free program. We wish to make sure that a company cannot
7400effectively restrict the users of a free program by obtaining a
7401restrictive license from a patent holder. Therefore, we insist that
7402any patent license obtained for a version of the library must be
7403consistent with the full freedom of use specified in this license.
7404
7405 Most GNU software, including some libraries, is covered by the
7406ordinary GNU General Public License. This license, the GNU Lesser
7407General Public License, applies to certain designated libraries, and
7408is quite different from the ordinary General Public License. We use
7409this license for certain libraries in order to permit linking those
7410libraries into non-free programs.
7411
7412 When a program is linked with a library, whether statically or using
7413a shared library, the combination of the two is legally speaking a
7414combined work, a derivative of the original library. The ordinary
7415General Public License therefore permits such linking only if the
7416entire combination fits its criteria of freedom. The Lesser General
7417Public License permits more lax criteria for linking other code with
7418the library.
7419
7420 We call this license the "Lesser" General Public License because it
7421does Less to protect the user's freedom than the ordinary General
7422Public License. It also provides other free software developers Less
7423of an advantage over competing non-free programs. These disadvantages
7424are the reason we use the ordinary General Public License for many
7425libraries. However, the Lesser license provides advantages in certain
7426special circumstances.
7427
7428 For example, on rare occasions, there may be a special need to
7429encourage the widest possible use of a certain library, so that it becomes
7430a de-facto standard. To achieve this, non-free programs must be
7431allowed to use the library. A more frequent case is that a free
7432library does the same job as widely used non-free libraries. In this
7433case, there is little to gain by limiting the free library to free
7434software only, so we use the Lesser General Public License.
7435
7436 In other cases, permission to use a particular library in non-free
7437programs enables a greater number of people to use a large body of
7438free software. For example, permission to use the GNU C Library in
7439non-free programs enables many more people to use the whole GNU
7440operating system, as well as its variant, the GNU/Linux operating
7441system.
7442
7443 Although the Lesser General Public License is Less protective of the
7444users' freedom, it does ensure that the user of a program that is
7445linked with the Library has the freedom and the wherewithal to run
7446that program using a modified version of the Library.
7447
7448 The precise terms and conditions for copying, distribution and
7449modification follow. Pay close attention to the difference between a
7450"work based on the library" and a "work that uses the library". The
7451former contains code derived from the library, whereas the latter must
7452be combined with the library in order to run.
7453\f
7454 GNU LESSER GENERAL PUBLIC LICENSE
7455 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7456
7457 0. This License Agreement applies to any software library or other
7458program which contains a notice placed by the copyright holder or
7459other authorized party saying it may be distributed under the terms of
7460this Lesser General Public License (also called "this License").
7461Each licensee is addressed as "you".
7462
7463 A "library" means a collection of software functions and/or data
7464prepared so as to be conveniently linked with application programs
7465(which use some of those functions and data) to form executables.
7466
7467 The "Library", below, refers to any such software library or work
7468which has been distributed under these terms. A "work based on the
7469Library" means either the Library or any derivative work under
7470copyright law: that is to say, a work containing the Library or a
7471portion of it, either verbatim or with modifications and/or translated
7472straightforwardly into another language. (Hereinafter, translation is
7473included without limitation in the term "modification".)
7474
7475 "Source code" for a work means the preferred form of the work for
7476making modifications to it. For a library, complete source code means
7477all the source code for all modules it contains, plus any associated
7478interface definition files, plus the scripts used to control compilation
7479and installation of the library.
7480
7481 Activities other than copying, distribution and modification are not
7482covered by this License; they are outside its scope. The act of
7483running a program using the Library is not restricted, and output from
7484such a program is covered only if its contents constitute a work based
7485on the Library (independent of the use of the Library in a tool for
7486writing it). Whether that is true depends on what the Library does
7487and what the program that uses the Library does.
7488
7489 1. You may copy and distribute verbatim copies of the Library's
7490complete source code as you receive it, in any medium, provided that
7491you conspicuously and appropriately publish on each copy an
7492appropriate copyright notice and disclaimer of warranty; keep intact
7493all the notices that refer to this License and to the absence of any
7494warranty; and distribute a copy of this License along with the
7495Library.
7496
7497 You may charge a fee for the physical act of transferring a copy,
7498and you may at your option offer warranty protection in exchange for a
7499fee.
7500\f
7501 2. You may modify your copy or copies of the Library or any portion
7502of it, thus forming a work based on the Library, and copy and
7503distribute such modifications or work under the terms of Section 1
7504above, provided that you also meet all of these conditions:
7505
7506 a) The modified work must itself be a software library.
7507
7508 b) You must cause the files modified to carry prominent notices
7509 stating that you changed the files and the date of any change.
7510
7511 c) You must cause the whole of the work to be licensed at no
7512 charge to all third parties under the terms of this License.
7513
7514 d) If a facility in the modified Library refers to a function or a
7515 table of data to be supplied by an application program that uses
7516 the facility, other than as an argument passed when the facility
7517 is invoked, then you must make a good faith effort to ensure that,
7518 in the event an application does not supply such function or
7519 table, the facility still operates, and performs whatever part of
7520 its purpose remains meaningful.
7521
7522 (For example, a function in a library to compute square roots has
7523 a purpose that is entirely well-defined independent of the
7524 application. Therefore, Subsection 2d requires that any
7525 application-supplied function or table used by this function must
7526 be optional: if the application does not supply it, the square
7527 root function must still compute square roots.)
7528
7529These requirements apply to the modified work as a whole. If
7530identifiable sections of that work are not derived from the Library,
7531and can be reasonably considered independent and separate works in
7532themselves, then this License, and its terms, do not apply to those
7533sections when you distribute them as separate works. But when you
7534distribute the same sections as part of a whole which is a work based
7535on the Library, the distribution of the whole must be on the terms of
7536this License, whose permissions for other licensees extend to the
7537entire whole, and thus to each and every part regardless of who wrote
7538it.
7539
7540Thus, it is not the intent of this section to claim rights or contest
7541your rights to work written entirely by you; rather, the intent is to
7542exercise the right to control the distribution of derivative or
7543collective works based on the Library.
7544
7545In addition, mere aggregation of another work not based on the Library
7546with the Library (or with a work based on the Library) on a volume of
7547a storage or distribution medium does not bring the other work under
7548the scope of this License.
7549
7550 3. You may opt to apply the terms of the ordinary GNU General Public
7551License instead of this License to a given copy of the Library. To do
7552this, you must alter all the notices that refer to this License, so
7553that they refer to the ordinary GNU General Public License, version 2,
7554instead of to this License. (If a newer version than version 2 of the
7555ordinary GNU General Public License has appeared, then you can specify
7556that version instead if you wish.) Do not make any other change in
7557these notices.
7558\f
7559 Once this change is made in a given copy, it is irreversible for
7560that copy, so the ordinary GNU General Public License applies to all
7561subsequent copies and derivative works made from that copy.
7562
7563 This option is useful when you wish to copy part of the code of
7564the Library into a program that is not a library.
7565
7566 4. You may copy and distribute the Library (or a portion or
7567derivative of it, under Section 2) in object code or executable form
7568under the terms of Sections 1 and 2 above provided that you accompany
7569it with the complete corresponding machine-readable source code, which
7570must be distributed under the terms of Sections 1 and 2 above on a
7571medium customarily used for software interchange.
7572
7573 If distribution of object code is made by offering access to copy
7574from a designated place, then offering equivalent access to copy the
7575source code from the same place satisfies the requirement to
7576distribute the source code, even though third parties are not
7577compelled to copy the source along with the object code.
7578
7579 5. A program that contains no derivative of any portion of the
7580Library, but is designed to work with the Library by being compiled or
7581linked with it, is called a "work that uses the Library". Such a
7582work, in isolation, is not a derivative work of the Library, and
7583therefore falls outside the scope of this License.
7584
7585 However, linking a "work that uses the Library" with the Library
7586creates an executable that is a derivative of the Library (because it
7587contains portions of the Library), rather than a "work that uses the
7588library". The executable is therefore covered by this License.
7589Section 6 states terms for distribution of such executables.
7590
7591 When a "work that uses the Library" uses material from a header file
7592that is part of the Library, the object code for the work may be a
7593derivative work of the Library even though the source code is not.
7594Whether this is true is especially significant if the work can be
7595linked without the Library, or if the work is itself a library. The
7596threshold for this to be true is not precisely defined by law.
7597
7598 If such an object file uses only numerical parameters, data
7599structure layouts and accessors, and small macros and small inline
7600functions (ten lines or less in length), then the use of the object
7601file is unrestricted, regardless of whether it is legally a derivative
7602work. (Executables containing this object code plus portions of the
7603Library will still fall under Section 6.)
7604
7605 Otherwise, if the work is a derivative of the Library, you may
7606distribute the object code for the work under the terms of Section 6.
7607Any executables containing that work also fall under Section 6,
7608whether or not they are linked directly with the Library itself.
7609\f
7610 6. As an exception to the Sections above, you may also combine or
7611link a "work that uses the Library" with the Library to produce a
7612work containing portions of the Library, and distribute that work
7613under terms of your choice, provided that the terms permit
7614modification of the work for the customer's own use and reverse
7615engineering for debugging such modifications.
7616
7617 You must give prominent notice with each copy of the work that the
7618Library is used in it and that the Library and its use are covered by
7619this License. You must supply a copy of this License. If the work
7620during execution displays copyright notices, you must include the
7621copyright notice for the Library among them, as well as a reference
7622directing the user to the copy of this License. Also, you must do one
7623of these things:
7624
7625 a) Accompany the work with the complete corresponding
7626 machine-readable source code for the Library including whatever
7627 changes were used in the work (which must be distributed under
7628 Sections 1 and 2 above); and, if the work is an executable linked
7629 with the Library, with the complete machine-readable "work that
7630 uses the Library", as object code and/or source code, so that the
7631 user can modify the Library and then relink to produce a modified
7632 executable containing the modified Library. (It is understood
7633 that the user who changes the contents of definitions files in the
7634 Library will not necessarily be able to recompile the application
7635 to use the modified definitions.)
7636
7637 b) Use a suitable shared library mechanism for linking with the
7638 Library. A suitable mechanism is one that (1) uses at run time a
7639 copy of the library already present on the user's computer system,
7640 rather than copying library functions into the executable, and (2)
7641 will operate properly with a modified version of the library, if
7642 the user installs one, as long as the modified version is
7643 interface-compatible with the version that the work was made with.
7644
7645 c) Accompany the work with a written offer, valid for at
7646 least three years, to give the same user the materials
7647 specified in Subsection 6a, above, for a charge no more
7648 than the cost of performing this distribution.
7649
7650 d) If distribution of the work is made by offering access to copy
7651 from a designated place, offer equivalent access to copy the above
7652 specified materials from the same place.
7653
7654 e) Verify that the user has already received a copy of these
7655 materials or that you have already sent this user a copy.
7656
7657 For an executable, the required form of the "work that uses the
7658Library" must include any data and utility programs needed for
7659reproducing the executable from it. However, as a special exception,
7660the materials to be distributed need not include anything that is
7661normally distributed (in either source or binary form) with the major
7662components (compiler, kernel, and so on) of the operating system on
7663which the executable runs, unless that component itself accompanies
7664the executable.
7665
7666 It may happen that this requirement contradicts the license
7667restrictions of other proprietary libraries that do not normally
7668accompany the operating system. Such a contradiction means you cannot
7669use both them and the Library together in an executable that you
7670distribute.
7671\f
7672 7. You may place library facilities that are a work based on the
7673Library side-by-side in a single library together with other library
7674facilities not covered by this License, and distribute such a combined
7675library, provided that the separate distribution of the work based on
7676the Library and of the other library facilities is otherwise
7677permitted, and provided that you do these two things:
7678
7679 a) Accompany the combined library with a copy of the same work
7680 based on the Library, uncombined with any other library
7681 facilities. This must be distributed under the terms of the
7682 Sections above.
7683
7684 b) Give prominent notice with the combined library of the fact
7685 that part of it is a work based on the Library, and explaining
7686 where to find the accompanying uncombined form of the same work.
7687
7688 8. You may not copy, modify, sublicense, link with, or distribute
7689the Library except as expressly provided under this License. Any
7690attempt otherwise to copy, modify, sublicense, link with, or
7691distribute the Library is void, and will automatically terminate your
7692rights under this License. However, parties who have received copies,
7693or rights, from you under this License will not have their licenses
7694terminated so long as such parties remain in full compliance.
7695
7696 9. You are not required to accept this License, since you have not
7697signed it. However, nothing else grants you permission to modify or
7698distribute the Library or its derivative works. These actions are
7699prohibited by law if you do not accept this License. Therefore, by
7700modifying or distributing the Library (or any work based on the
7701Library), you indicate your acceptance of this License to do so, and
7702all its terms and conditions for copying, distributing or modifying
7703the Library or works based on it.
7704
7705 10. Each time you redistribute the Library (or any work based on the
7706Library), the recipient automatically receives a license from the
7707original licensor to copy, distribute, link with or modify the Library
7708subject to these terms and conditions. You may not impose any further
7709restrictions on the recipients' exercise of the rights granted herein.
7710You are not responsible for enforcing compliance by third parties with
7711this License.
7712\f
7713 11. If, as a consequence of a court judgment or allegation of patent
7714infringement or for any other reason (not limited to patent issues),
7715conditions are imposed on you (whether by court order, agreement or
7716otherwise) that contradict the conditions of this License, they do not
7717excuse you from the conditions of this License. If you cannot
7718distribute so as to satisfy simultaneously your obligations under this
7719License and any other pertinent obligations, then as a consequence you
7720may not distribute the Library at all. For example, if a patent
7721license would not permit royalty-free redistribution of the Library by
7722all those who receive copies directly or indirectly through you, then
7723the only way you could satisfy both it and this License would be to
7724refrain entirely from distribution of the Library.
7725
7726If any portion of this section is held invalid or unenforceable under any
7727particular circumstance, the balance of the section is intended to apply,
7728and the section as a whole is intended to apply in other circumstances.
7729
7730It is not the purpose of this section to induce you to infringe any
7731patents or other property right claims or to contest validity of any
7732such claims; this section has the sole purpose of protecting the
7733integrity of the free software distribution system which is
7734implemented by public license practices. Many people have made
7735generous contributions to the wide range of software distributed
7736through that system in reliance on consistent application of that
7737system; it is up to the author/donor to decide if he or she is willing
7738to distribute software through any other system and a licensee cannot
7739impose that choice.
7740
7741This section is intended to make thoroughly clear what is believed to
7742be a consequence of the rest of this License.
7743
7744 12. If the distribution and/or use of the Library is restricted in
7745certain countries either by patents or by copyrighted interfaces, the
7746original copyright holder who places the Library under this License may add
7747an explicit geographical distribution limitation excluding those countries,
7748so that distribution is permitted only in or among countries not thus
7749excluded. In such case, this License incorporates the limitation as if
7750written in the body of this License.
7751
7752 13. The Free Software Foundation may publish revised and/or new
7753versions of the Lesser General Public License from time to time.
7754Such new versions will be similar in spirit to the present version,
7755but may differ in detail to address new problems or concerns.
7756
7757Each version is given a distinguishing version number. If the Library
7758specifies a version number of this License which applies to it and
7759"any later version", you have the option of following the terms and
7760conditions either of that version or of any later version published by
7761the Free Software Foundation. If the Library does not specify a
7762license version number, you may choose any version ever published by
7763the Free Software Foundation.
7764\f
7765 14. If you wish to incorporate parts of the Library into other free
7766programs whose distribution conditions are incompatible with these,
7767write to the author to ask for permission. For software which is
7768copyrighted by the Free Software Foundation, write to the Free
7769Software Foundation; we sometimes make exceptions for this. Our
7770decision will be guided by the two goals of preserving the free status
7771of all derivatives of our free software and of promoting the sharing
7772and reuse of software generally.
7773
7774 NO WARRANTY
7775
7776 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
7777WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
7778EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
7779OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
7780KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
7781IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7782PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
7783LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
7784THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
7785
7786 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
7787WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
7788AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
7789FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
7790CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
7791LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
7792RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
7793FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
7794SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
7795DAMAGES.
7796
7797 END OF TERMS AND CONDITIONS
7798\f
7799 How to Apply These Terms to Your New Libraries
7800
7801 If you develop a new library, and you want it to be of the greatest
7802possible use to the public, we recommend making it free software that
7803everyone can redistribute and change. You can do so by permitting
7804redistribution under these terms (or, alternatively, under the terms of the
7805ordinary General Public License).
7806
7807 To apply these terms, attach the following notices to the library. It is
7808safest to attach them to the start of each source file to most effectively
7809convey the exclusion of warranty; and each file should have at least the
7810"copyright" line and a pointer to where the full notice is found.
7811
7812 <one line to give the library's name and a brief idea of what it does.>
7813 Copyright (C) <year> <name of author>
7814
7815 This library is free software; you can redistribute it and/or
7816 modify it under the terms of the GNU Lesser General Public
7817 License as published by the Free Software Foundation; either
7818 version 2.1 of the License, or (at your option) any later version.
7819
7820 This library is distributed in the hope that it will be useful,
7821 but WITHOUT ANY WARRANTY; without even the implied warranty of
7822 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7823 Lesser General Public License for more details.
7824
7825 You should have received a copy of the GNU Lesser General Public
7826 License along with this library; if not, write to the Free Software
7827 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7828
7829Also add information on how to contact you by electronic and paper mail.
7830
7831You should also get your employer (if you work as a programmer) or your
7832school, if any, to sign a "copyright disclaimer" for the library, if
7833necessary. Here is a sample; alter the names:
7834
7835 Yoyodyne, Inc., hereby disclaims all copyright interest in the
7836 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
7837
7838 <signature of Ty Coon>, 1 April 1990
7839 Ty Coon, President of Vice
7840
7841That's all there is to it!
7842
7843
7844\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/reports/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0016545\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/reports/stylesheet.css\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002077\013062740170\0021456\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/* Styles for main page */
7845#banner {
7846 background: #9c9;
7847 padding-top: 5px;
7848 padding-bottom: 5px;
7849 border-bottom: 2px solid;
7850 font: small-caps 20px/20px "Times New Roman", serif;
7851 color: #282;
7852 text-align: center;
7853}
7854
7855#banner img {
7856 float: left;
7857}
7858
7859#main {
7860 margin-left: 0em;
7861 padding-top: 4ex;
7862 padding-left: 2em;
7863 background: white;
7864}
7865
7866h1 {
7867 font: 150% sans-serif;
7868 color: #226;
7869 border-bottom: 3px dotted #77d;
7870}
7871
7872body {
7873 font: normal 75% verdana,arial,helvetica;
7874 color:#000000;
7875}
7876
7877table tr td, table tr th {
7878 font-size: 75%;
7879}
7880
7881table.stripes tr th {
7882 font-weight: bold;
7883 text-align: left;
7884 background: #a0a0a0;
7885}
7886
7887table.stripes tr td {
7888 background: #ccccc0;
7889}
7890
7891td.pass {
7892 color: green;
7893}
7894
7895td.fail {
7896 color: red;
7897 font-weight: bold;
7898}
7899
7900#main {
7901 padding-left: 0em;
7902}
7903
7904#controls {
7905 float: left;
7906 padding-top: 1em;
7907 padding-left: 1em;
7908 padding-right: 1em;
7909 padding-bottom: 1em;
7910 width: 14em;
7911 border-right: 2px solid;
7912}
7913
7914#body {
7915 margin-left: 16em;
7916 padding-top: 4ex;
7917 padding-left: 2em;
7918 background: white;
7919 border-left: 2px solid;
7920}
7921\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020531\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0021277\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/report_templates.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002241\013062740170\0025214\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
7922#
7923# This copyrighted material is made available to anyone wishing to use,
7924# modify, copy, or redistribute it subject to the terms and conditions
7925# of the GNU General Public License v.2.
7926#
7927# You should have received a copy of the GNU General Public License
7928# along with this program; if not, write to the Free Software Foundation,
7929# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7930
7931# Policy for the location of report templates
7932require 'string-store'
7933
7934class TemplateStringStore < StringStore
7935 def initialize()
7936 super(['report-generators/templates'])
7937 end
7938end
7939
7940module ReportTemplates
7941 def generate_report(report, bs, dest_path = nil)
7942 include Reports
7943 reports = ReportRegister.new
7944 template_store = TemplateStringStore.new
7945 report = reports.get_report(report)
7946 erb = ERB.new(template_store.lookup(report.template))
7947 body = erb.result(bs)
7948 title = report.short_desc
7949
7950 erb = ERB.new(template_store.lookup("boiler_plate.rhtml"))
7951 txt = erb.result(binding)
7952
7953 dest_path = dest_path.nil? ? report.path : dest_path
7954 dest_path.open("w") do |out|
7955 out.puts txt
7956 end
7957 end
7958end
7959\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/schedule_file.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002576\013062740170\0024431\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
7960#
7961# This copyrighted material is made available to anyone wishing to use,
7962# modify, copy, or redistribute it subject to the terms and conditions
7963# of the GNU General Public License v.2.
7964#
7965# You should have received a copy of the GNU General Public License
7966# along with this program; if not, write to the Free Software Foundation,
7967# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7968
7969# Parses the simple colon delimited test schedule files.
7970
7971ScheduledTest = Struct.new(:desc, :command_line, :status, :output)
7972
7973class Schedule
7974 attr_reader :dir, :schedules
7975
7976 def initialize(dir, ss)
7977 @dir = dir
7978 @schedules = ss
7979 end
7980
7981 def run
7982 Dir::chdir(@dir.to_s) do
7983 @schedules.each do |s|
7984 reader, writer = IO.pipe
7985 print "#{s.desc} ... "
7986 pid = spawn(s.command_line, [ STDERR, STDOUT ] => writer)
7987 writer.close
7988 _, s.status = Process::waitpid2(pid)
7989 puts (s.status.success? ? "pass" : "fail")
7990 s.output = reader.read
7991 end
7992 end
7993 end
7994
7995 def self.read(dir, io)
7996 ss = Array.new
7997
7998 io.readlines.each do |line|
7999 case line.strip
8000 when /^\#.*/
8001 next
8002
8003 when /([^:]+):(.*)/
8004 ss << ScheduledTest.new($1.strip, $2.strip)
8005
8006 else
8007 raise RuntimeError, "badly formatted schedule line"
8008 end
8009 end
8010
8011 Schedule.new(dir, ss)
8012 end
8013end
8014
8015\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/reports.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003233\013062740170\0023323\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8016#
8017# This copyrighted material is made available to anyone wishing to use,
8018# modify, copy, or redistribute it subject to the terms and conditions
8019# of the GNU General Public License v.2.
8020#
8021# You should have received a copy of the GNU General Public License
8022# along with this program; if not, write to the Free Software Foundation,
8023# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8024
8025# Data about the various reports we support
8026require 'log'
8027require 'pathname'
8028
8029module Reports
8030 Report = Struct.new(:short_desc, :desc, :path, :template)
8031
8032 class ReportRegister
8033 attr_reader :reports
8034
8035 private
8036 def add_report(sym, *args)
8037 @reports[sym] = Report.new(*args)
8038 end
8039
8040 public
8041 def initialize()
8042 @reports = Hash.new
8043
8044 add_report(:unit_test,
8045 "Unit Tests",
8046 "unit tests",
8047 Pathname.new("reports/unit.html"),
8048 Pathname.new("unit_test.rhtml"))
8049
8050 add_report(:memcheck,
8051 "Memory Tests",
8052 "unit tests with valgrind memory checking",
8053 Pathname.new("reports/memcheck.html"),
8054 Pathname.new("memcheck.rhtml"))
8055
8056 add_report(:unit_detail,
8057 "Unit Test Detail",
8058 "unit test detail",
8059 Pathname.new("reports/unit_detail.html"), # FIXME replace this with a lambda
8060 Pathname.new("unit_detail.rhtml"))
8061 end
8062
8063 def get_report(sym)
8064 raise RuntimeError, "unknown report '#{sym}'" unless @reports.member?(sym)
8065 @reports[sym]
8066 end
8067
8068 def each(&block)
8069 @reports.each(&block)
8070 end
8071 end
8072end
8073\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/string-store.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002043\013062740170\0024263\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8074#
8075# This copyrighted material is made available to anyone wishing to use,
8076# modify, copy, or redistribute it subject to the terms and conditions
8077# of the GNU General Public License v.2.
8078#
8079# You should have received a copy of the GNU General Public License
8080# along with this program; if not, write to the Free Software Foundation,
8081# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8082
8083# Provides a simple way of accessing the contents of files by a symbol
8084# name. Useful for erb templates.
8085
8086require 'pathname'
8087
8088class StringStore
8089 attr_accessor :path
8090
8091 def initialize(p)
8092 @paths = p.nil? ? Array.new : p # FIXME: do we need to copy p ?
8093 end
8094
8095 def lookup(sym)
8096 files = expansions(sym)
8097
8098 @paths.each do |p|
8099 files.each do |f|
8100 pn = Pathname.new("#{p}/#{f}")
8101 if pn.file?
8102 return pn.read
8103 end
8104 end
8105 end
8106
8107 raise RuntimeError, "unknown string entry: #{sym}"
8108 end
8109
8110 private
8111 def expansions(sym)
8112 ["#{sym}", "#{sym}.txt"]
8113 end
8114end
8115\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/lib/log.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001507\013062740170\0022410\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8116#
8117# This copyrighted material is made available to anyone wishing to use,
8118# modify, copy, or redistribute it subject to the terms and conditions
8119# of the GNU General Public License v.2.
8120#
8121# You should have received a copy of the GNU General Public License
8122# along with this program; if not, write to the Free Software Foundation,
8123# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8124
8125# Merely wraps the logger library with a bit of standard policy.
8126require 'logger'
8127
8128module Log
8129 $log = Logger.new(STDERR)
8130
8131 def init(io_)
8132 $log = Logger.new(io_)
8133 end
8134end
8135
8136def fatal(*args)
8137 $log.fatal(*args)
8138end
8139
8140def error(*args)
8141 $log.error(*args)
8142end
8143
8144def info(*args)
8145 $log.info(*args)
8146end
8147
8148def warning(*args)
8149 $log.warn(*args)
8150end
8151
8152def debug(*args)
8153 $log.debug(*args)
8154end
8155\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/title_page.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002105\013062740170\0023171\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8156#
8157# This copyrighted material is made available to anyone wishing to use,
8158# modify, copy, or redistribute it subject to the terms and conditions
8159# of the GNU General Public License v.2.
8160#
8161# You should have received a copy of the GNU General Public License
8162# along with this program; if not, write to the Free Software Foundation,
8163# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8164
8165# This generates the index for the reports, including generation
8166# times.
8167
8168require 'log'
8169require 'string-store'
8170require 'reports'
8171require 'erb'
8172require 'report_templates'
8173
8174include Reports
8175
8176reports = ReportRegister.new
8177
8178def safe_mtime(r)
8179 r.path.file? ? r.path.mtime.to_s : "not generated"
8180end
8181
8182template_store = TemplateStringStore.new
8183
8184# FIXME: use generate_report() method
8185erb = ERB.new(template_store.lookup("index.rhtml"))
8186body = erb.result(binding)
8187title = "Generation times"
8188
8189erb = ERB.new(template_store.lookup("boiler_plate.rhtml"))
8190txt = erb.result(binding)
8191
8192Pathname.new("reports/index.html").open("w") do |f|
8193 f.puts txt
8194end
8195
8196
8197\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0021510\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/tc_schedule_file.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002200\013062740170\0025310\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8198#
8199# This copyrighted material is made available to anyone wishing to use,
8200# modify, copy, or redistribute it subject to the terms and conditions
8201# of the GNU General Public License v.2.
8202#
8203# You should have received a copy of the GNU General Public License
8204# along with this program; if not, write to the Free Software Foundation,
8205# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8206
8207require 'test/unit'
8208require 'pathname'
8209require 'schedule_file'
8210
8211class TestScheduleFile < Test::Unit::TestCase
8212 def test_reading
8213 p = Pathname.new("report-generators/test/example.schedule")
8214 p.open do |f|
8215 s = Schedule.read(p.dirname, f)
8216
8217 assert_equal(3, s.schedules.size)
8218 assert_equal(s.schedules[2].desc, "this comment is prefixed with whitespace")
8219 assert_equal(s.schedules[0].command_line, "$TEST_TOOL ls")
8220 end
8221 end
8222
8223 def test_running
8224 p = Pathname.new("report-generators/test/example.schedule")
8225 p.open do |f|
8226 s = Schedule.read(p.dirname, f)
8227 s.run
8228
8229 s.schedules.each do |t|
8230 assert(t.status.success?)
8231 end
8232 end
8233 end
8234end
8235\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/strings/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0023201\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/strings/more_strings/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0025714\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/strings/more_strings/test3.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000006\013062740170\0027513\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lorem
8236\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/strings/test1.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000016\013062740170\0024777\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Hello, world!
8237\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/strings/test2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000015\013062740170\0024161\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0one
8238two
8239three\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/tc_string_store.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001703\013062740170\0025246\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8240#
8241# This copyrighted material is made available to anyone wishing to use,
8242# modify, copy, or redistribute it subject to the terms and conditions
8243# of the GNU General Public License v.2.
8244#
8245# You should have received a copy of the GNU General Public License
8246# along with this program; if not, write to the Free Software Foundation,
8247# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8248
8249require 'string-store'
8250require 'test/unit'
8251
8252class TestStringStore < Test::Unit::TestCase
8253 def setup
8254 @ss = StringStore.new(['report-generators/test/strings',
8255 'report-generators/test/strings/more_strings'])
8256 end
8257
8258 def test_lookup
8259 assert_equal("Hello, world!\n", @ss.lookup(:test1))
8260 assert_equal("one\ntwo\nthree", @ss.lookup(:test2))
8261 assert_equal("lorem\n", @ss.lookup(:test3))
8262
8263 assert_raises(RuntimeError) do
8264 @ss.lookup(:unlikely_name)
8265 end
8266 end
8267end
8268\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/tc_log.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001625\013062740170\0023310\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8269#
8270# This copyrighted material is made available to anyone wishing to use,
8271# modify, copy, or redistribute it subject to the terms and conditions
8272# of the GNU General Public License v.2.
8273#
8274# You should have received a copy of the GNU General Public License
8275# along with this program; if not, write to the Free Software Foundation,
8276# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8277
8278require 'test/unit'
8279require 'stringio'
8280require 'log'
8281
8282class TestLog < Test::Unit::TestCase
8283 include Log
8284
8285 private
8286 def remove_timestamps(l)
8287 l.gsub(/\[[^\]]*\]/, '')
8288 end
8289
8290 public
8291 def test_log
8292 StringIO.open do |out|
8293 init(out)
8294
8295 info("msg1")
8296 warning("msg2")
8297 debug("msg3")
8298
8299 assert_equal("I, INFO -- : msg1\nW, WARN -- : msg2\nD, DEBUG -- : msg3\n",
8300 remove_timestamps(out.string))
8301 end
8302 end
8303end
8304\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/example.schedule\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000223\013062740170\0024656\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# This is a comment
8305description number 1:$TEST_TOOL ls
8306foo bar: $TEST_TOOL du -hs .
8307 this comment is prefixed with whitespace: $TEST_TOOL date\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/test/ts.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001014\013062740170\0022457\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8308#
8309# This copyrighted material is made available to anyone wishing to use,
8310# modify, copy, or redistribute it subject to the terms and conditions
8311# of the GNU General Public License v.2.
8312#
8313# You should have received a copy of the GNU General Public License
8314# along with this program; if not, write to the Free Software Foundation,
8315# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8316
8317require 'tc_log'
8318require 'tc_string_store'
8319require 'tc_schedule_file'
8320\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/memcheck.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004335\013062740170\0022637\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8321#
8322# This copyrighted material is made available to anyone wishing to use,
8323# modify, copy, or redistribute it subject to the terms and conditions
8324# of the GNU General Public License v.2.
8325#
8326# You should have received a copy of the GNU General Public License
8327# along with this program; if not, write to the Free Software Foundation,
8328# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8329
8330# Reads the schedule files given on the command line. Runs them and
8331# generates the reports.
8332
8333# FIXME: a lot of duplication with unit_test.rb
8334
8335require 'schedule_file'
8336require 'pathname'
8337require 'reports'
8338require 'erb'
8339require 'report_templates'
8340
8341include ReportTemplates
8342
8343schedules = ARGV.map do |f|
8344 p = Pathname.new(f)
8345 Schedule.read(p.dirname, p)
8346end
8347
8348total_passed = 0
8349total_failed = 0
8350
8351# We need to make sure the lvm shared libs are in the LD_LIBRARY_PATH
8352ENV['LD_LIBRARY_PATH'] = `pwd`.strip + "/libdm:" + (ENV['LD_LIBRARY_PATH'] || '')
8353
8354ENV['TEST_TOOL'] = "valgrind --leak-check=full --show-reachable=yes"
8355
8356schedules.each do |s|
8357 s.run
8358
8359 s.schedules.each do |t|
8360 if t.status.success?
8361 total_passed += 1
8362 else
8363 total_failed += 1
8364 end
8365 end
8366end
8367
8368def mangle(txt)
8369 txt.gsub(/\s+/, '_')
8370end
8371
8372MemcheckStats = Struct.new(:definitely_lost, :indirectly_lost, :possibly_lost, :reachable)
8373
8374def format(bytes, blocks)
8375 "#{bytes} bytes, #{blocks} blocks"
8376end
8377
8378# Examines the output for details of leaks
8379def extract_stats(t)
8380 d = i = p = r = '-'
8381
8382 t.output.split("\n").each do |l|
8383 case l
8384 when /==\d+== definitely lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
8385 d = format($1, $2)
8386 when /==\d+== indirectly lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
8387 i = format($1, $2)
8388 when /==\d+== possibly lost: ([0-9,]+) bytes in ([0-9,]+) blocks/
8389 p = format($1, $2)
8390 when /==\d+== still reachable: ([0-9,]+) bytes in ([0-9,]+) blocks/
8391 r = format($1, $2)
8392 end
8393 end
8394
8395 MemcheckStats.new(d, i, p, r)
8396end
8397
8398generate_report(:memcheck, binding)
8399
8400# now we generate a detail report for each schedule
8401schedules.each do |s|
8402 s.schedules.each do |t|
8403 generate_report(:unit_detail, binding, Pathname.new("reports/memcheck_#{mangle(t.desc)}.html"))
8404 end
8405end
8406\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0022527\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/unit_test.rhtml\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001325\013062740170\0025616\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8407 <tr><th>Tests passed</th><th>Tests failed</th></tr>
8408 <tr><td class="pass"><%= total_passed %></td><td <%= total_failed == 0 ? "" : "class=\"fail\""%>><%= total_failed %></td></tr>
8409</table>
8410
8411<% schedules.each do |s| %>
8412<h3><%= s.dir.sub('./unit-tests/', '') %></h3>
8413<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8414<tr><th>Test</th><th>Result</th></tr>
8415<% s.schedules.each do |t| %>
8416<tr>
8417 <td>
8418 <a href="detail_<%= mangle(t.desc) %>.html"><%= t.desc %></a>
8419 </td>
8420 <% if t.status.success? %>
8421 <td class="pass">pass</td>
8422 <% else %>
8423 <td class="fail">fail</td>
8424 <% end %>
8425</tr>
8426<% end %>
8427</table>
8428<% end %>
8429\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/index.rhtml\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000673\013062740170\0024714\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8430<tr><th>Report</th><th>Generation time</th></tr>
8431<% [:unit_test, :memcheck].each do |sym| %>
8432<% r = reports.get_report(sym) %>
8433<tr>
8434 <td>
8435 <% if r.path.file? %>
8436 <a href="<%= r.path.to_s.gsub(/^reports\//, '') %>"><%= r.short_desc %></a>
8437 <% else %>
8438 <%= r.short_desc %>
8439 <% end %>
8440 </td>
8441 <td><%= safe_mtime(r) %></td>
8442</tr>
8443<% end %>
8444</table>
8445
8446\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/boiler_plate.rhtml\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001075\013062740170\0026243\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<html>
8447<head>
8448<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
8449<title><%= title %></title>
8450<link title="Style" type="text/css" rel="stylesheet" href="stylesheet.css">
8451</head>
8452
8453<body>
8454<div id="banner">
8455<h2><%= title %></h2>
8456</div>
8457<div id="main">
8458 <div id="controls">
8459 <table>
8460 <tr><td><a href="index.html">Generation times</a></td></tr>
8461 <tr><td><a href="unit.html">Unit tests</a></td></tr>
8462 <tr><td><a href="memcheck.html">Memory tests</a></td></tr>
8463 </table>
8464 </div>
8465
8466 <div id="body">
8467 <%= body %>
8468 </div>
8469</div>
8470</body>
8471\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/memcheck.rhtml\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001760\013062740170\0025357\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8472 <tr><th>Tests passed</th><th>Tests failed</th></tr>
8473 <tr><td class="pass"><%= total_passed %></td><td <%= total_failed == 0 ? "" : "class=\"fail\""%>><%= total_failed %></td></tr>
8474</table>
8475
8476<% schedules.each do |s| %>
8477<h3><%= s.dir.sub('./unit-tests/', '') %></h3>
8478<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8479<tr><th>Test</th><th>Result</th><th>Definitely lost</th><th>indirectly lost</th><th>possibly lost</th><th>still reachable</th><tr>
8480
8481<% s.schedules.each do |t| %>
8482<tr>
8483 <td>
8484 <a href="memcheck_<%= mangle(t.desc) %>.html"><%= t.desc %></a>
8485 </td>
8486 <% if t.status.success? %>
8487 <td class="pass">pass</td>
8488 <% else %>
8489 <td class="fail">fail</td>
8490 <% end %>
8491
8492 <% stats = extract_stats(t) %>
8493 <td><%= stats.definitely_lost %></td>
8494 <td><%= stats.indirectly_lost %></td>
8495 <td><%= stats.possibly_lost %></td>
8496 <td><%= stats.reachable %></td>
8497</tr>
8498<% end %>
8499</table>
8500<% end %>
8501\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/templates/unit_detail.rhtml\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001200\013062740170\0026071\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8502<tr><th>Test</th><th>Result</th></tr>
8503<tr>
8504 <td>
8505 <%= t.desc %>
8506 </td>
8507 <% if t.status.success? %>
8508 <td class="pass">pass</td>
8509 <% else %>
8510 <td class="fail">fail</td>
8511 <% end %>
8512</tr>
8513</table>
8514
8515<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8516<tr><th>Command line</th></tr>
8517<tr>
8518 <td>
8519 <pre>
8520<%= t.command_line %>
8521 </pre>
8522 </td>
8523</tr>
8524</table>
8525
8526
8527<table width="95%" cellspacing="2" cellpadding="5" border="0" class="stripes">
8528<tr><th>Output</th></tr>
8529<tr>
8530 <td>
8531 <pre>
8532<%= t.output %>
8533 </pre>
8534 </td>
8535</tr>
8536</table>
8537
8538\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/report-generators/unit_test.rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002566\013062740170\0023105\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
8539#
8540# This copyrighted material is made available to anyone wishing to use,
8541# modify, copy, or redistribute it subject to the terms and conditions
8542# of the GNU General Public License v.2.
8543#
8544# You should have received a copy of the GNU General Public License
8545# along with this program; if not, write to the Free Software Foundation,
8546# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8547
8548# Reads the schedule files given on the command line. Runs them and
8549# generates the reports.
8550
8551require 'schedule_file'
8552require 'pathname'
8553require 'reports'
8554require 'erb'
8555require 'report_templates'
8556
8557include ReportTemplates
8558
8559schedules = ARGV.map do |f|
8560 p = Pathname.new(f)
8561 Schedule.read(p.dirname, p)
8562end
8563
8564total_passed = 0
8565total_failed = 0
8566
8567# We need to make sure the lvm shared libs are in the LD_LIBRARY_PATH
8568ENV['LD_LIBRARY_PATH'] = `pwd`.strip + "/libdm:" + (ENV['LD_LIBRARY_PATH'] || '')
8569
8570schedules.each do |s|
8571 s.run
8572
8573 s.schedules.each do |t|
8574 if t.status.success?
8575 total_passed += 1
8576 else
8577 total_failed += 1
8578 end
8579 end
8580end
8581
8582def mangle(txt)
8583 txt.gsub(/\s+/, '_')
8584end
8585
8586generate_report(:unit_test, binding)
8587
8588# now we generate a detail report for each schedule
8589schedules.each do |s|
8590 s.schedules.each do |t|
8591 generate_report(:unit_detail, binding, Pathname.new("reports/detail_#{mangle(t.desc)}.html"))
8592 end
8593end
8594\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/WHATS_NEW_DM\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000174205\013062740170\0016762\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Version 1.02.137 - 30th November 2016
8595=====================================
8596 Document raid status values.
8597 Always exit dmsetup with success when asked to display help/version.
8598
8599Version 1.02.136 - 5th November 2016
8600====================================
8601 Log failure of raid device with log_error level.
8602 Use dm_log_with_errno and translate runtime to dm_log only when needed.
8603 Make log messages from dm and lvm library different from dmeventd.
8604 Notice and Info messages are again logged from dmeventd and its plugins.
8605 Dmeventd now also respects DM_ABORT_ON_INTERNAL_ERRORS as libdm based tool.
8606 Report as non default dm logging also when logging with errno was changed.
8607 Use log_level() macro to consistently decode message log level in dmeventd.
8608 Still produce output when dmsetup dependency tree building finds dev missing.
8609 Check and report pthread_sigmask() failure in dmeventd.
8610 Check mem alloc fail in _canonicalize_field_ids().
8611 Use unsigned math when checking more then 31 legs of raid.
8612 Fix 'dmstats delete' with dmsetup older than v1.02.129
8613 Fix stats walk segfault with dmsetup older than v1.02.129
8614
8615Version 1.02.135 - 26th September 2016
8616======================================
8617 Fix man entry for dmsetup status.
8618 Introduce new dm_config_parse_without_dup_node_check().
8619 Don't omit last entry in dmstats list --group.
8620
8621Version 1.02.134 - 7th September 2016
8622=====================================
8623 Improve explanation of udev fallback in libdevmapper.h.
8624
8625Version 1.02.133 - 10th August 2016
8626===================================
8627 Add dm_report_destroy_rows/dm_report_group_output_and_pop_all for lvm shell.
8628 Adjust group handling and json production for lvm shell.
8629
8630Version 1.02.132 - 28th July 2016
8631=================================
8632 Fix json reporting to escape '"' character that may appear in reported string.
8633
8634Version 1.02.131 - 15th July 2016
8635=================================
8636 Disable queueing on mpath devs in blk-availability systemd service/initscript.
8637 Add new -m|--mpathoption disablequeueing to blkdeactivate.
8638 Automatically group regions with 'create --segments' unless --nogroup.
8639 Fix resource leak when deleting the first member of a group.
8640 Allow --bounds with 'create --filemap' for dmstats.
8641 Enable creation of filemap regions with histograms.
8642 Enable histogram aggregation for regions with more than one area.
8643 Enable histogram aggregation for groups of regions.
8644 Add a --filemap option to 'dmstats create' to allow mapping of files.
8645 Add dm_stats_create_regions_from_fd() to map file extents to regions.
8646
8647Version 1.02.130 - 6th July 2016
8648================================
8649 Minor fixes from coverity.
8650
8651Version 1.02.129 - 6th July 2016
8652================================
8653 Update default dmstats field selections for groups.
8654 Add 'obj_type', 'group_id', and 'statsname' fields to dmstats reports.
8655 Add --area, --region, and --group to dmstats to control object selection.
8656 Add --alias, --groupid, --regions to dmstats for group creation and deletion.
8657 Add 'group' and 'ungroup' commands to dmstats.
8658 Allow dm_stats_delete_group() to optionally delete all group members.
8659 Add dm_stats_get_object_type() to return the type of object present.
8660 Add dm_stats_walk_init() allowing control of objects visited by walks.
8661 Add dm_stats_get_group_descriptor() to return the member list as a string.
8662 Introduce dm_stats_get_nr_groups() and dm_stats_group_present().
8663 Add dm_stats_{get,set}_alias() to set and retrieve alias names for groups.
8664 Add dm_stats_get_group_id() to return the group ID for a given region.
8665 Add dm_stats_{create,delete}_group() to allow grouping of stats regions.
8666 Add enum-driven dm_stats_get_{metric,counter}() interfaces.
8667 Add dm_bitset_parse_list() to parse a string representation of a bitset.
8668 Thin dmeventd plugin umounts lvm2 volume only when pool is 95% or more.
8669
8670Version 1.02.128 - 25th June 2016
8671=================================
8672 Recognize 'all' keyword used in selection as synonym for "" (no selection).
8673 Add dm_report_set_selection to set selection for multiple output of report.
8674 Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
8675 Move field width handling/sort init from dm_report_object to dm_report_output.
8676 Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
8677 Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
8678 Introduce DM_REPORT_GROUP_BASIC for report group with basic report output.
8679 Introduce DM_REPORT_GROUP_SINGLE for report group having single report only.
8680 Add dm_report_group_{create,push,pop,destroy} to support report grouping.
8681
8682Version 1.02.127 - 11th June 2016
8683=================================
8684 Fix blkdeactivate regression causing skipping of dm + md devices. (1.02.126)
8685
8686Version 1.02.126 - 3rd June 2016
8687================================
8688 Report passthrough caching mode when parsing cache mode.
8689
8690Version 1.02.125 - 14th May 2016
8691================================
8692 Show library version in message even if dm driver version is unavailable.
8693
8694Version 1.02.124 - 30th April 2016
8695==================================
8696 Add dm_udev_wait_immediate to libdevmapper for waiting outside the library.
8697
8698Version 1.02.123 - 23rd April 2016
8699==================================
8700 Do not strip LVM- when debug reporting not found uuid.
8701
8702Version 1.02.122 - 9th April 2016
8703=================================
8704 Change log_debug ioctl flags from single characters into words.
8705
8706Version 1.02.121 - 26th March 2016
8707==================================
8708 Adjust raid status function.
8709
8710Version 1.02.120 - 11th March 2016
8711==================================
8712 Improve parsing of cache status and report Fail, Error, needs_check, ro.
8713
8714Version 1.02.119 - 4th March 2016
8715=================================
8716 Fix dm_config_write_node and variants to return error on subsection failures.
8717 Remove 4096 char limit due to buffer size if writing dm_config_node.
8718
8719Version 1.02.118 - 26th February 2016
8720=====================================
8721 Fix string boundary check in _get_canonical_field_name().
8722 Always initialized hist struct in _stats_parse_histogram().
8723
8724Version 1.02.117 - 21st February 2016
8725=====================================
8726 Improve status parsing for thin-pool and thin devices.
8727
8728Version 1.02.116 - 15th February 2016
8729=====================================
8730 Use fully aligned allocations for dm_pool_strdup/strndup() (1.02.64).
8731 Fix thin-pool table parameter feature order to match kernel output.
8732
8733Version 1.02.115 - 25th January 2016
8734====================================
8735 Fix man page for dmsetup udevcreatecookie.
8736
8737Version 1.02.114 - 14th December 2015
8738=====================================
8739 Better support for dmsetup static linkage.
8740 Extend validity checks on dmeventd client socket.
8741
8742Version 1.02.113 - 5th December 2015
8743====================================
8744 Mirror plugin in dmeventd uses dm_get_status_mirror().
8745 Add dm_get_status_mirror() for parsing mirror status line.
8746
8747Version 1.02.112 - 28th November 2015
8748=====================================
8749 Show error message when trying to create unsupported raid type.
8750 Improve preloading sequence of an active thin-pool target.
8751 Drop extra space from cache target line to fix unneded table reloads.
8752
8753Version 1.02.111 - 23rd November 2015
8754=====================================
8755 Extend dm_hash to support multiple values with the same key.
8756 Add missing check for allocation inside dm_split_lvm_name().
8757 Test dm_task_get_message_response for !NULL in dm_stats_print_region().
8758 Add checks for failing dm_stats_create() in dmsetup.
8759 Add missing fifo close when failed to initialize client connection.
8760
8761Version 1.02.110 - 30th October 2015
8762====================================
8763 Disable thin monitoring plugin when it fails too often (>10 times).
8764 Fix/restore parsing of empty field '-' when processing dmeventd event.
8765 Enhance dm_tree_node_size_changed() to recognize size reduction.
8766 Support exit on idle for dmenventd (1 hour).
8767 Add support to allow unmonitor device from plugin itself.
8768 New design for thread co-operation in dmeventd.
8769 Dmeventd read device status with 'noflush'.
8770 Dmeventd closes control device when no device is monitored.
8771 Thin plugin for dmeventd improved percentage usage.
8772 Snapshot plugin for dmeventd improved percentage usage.
8773 Add dm_hold_control_dev to allow holding of control device open.
8774 Add dm_report_compact_given_fields to remove given empty fields from report.
8775 Use libdm status parsing and local mem raid dmeventd plugin.
8776 Use local mem pool and lock only lvm2 execution for mirror dmeventd plugin.
8777 Lock protect only lvm2 execution for snapshot and thin dmeventd plugin.
8778 Use local mempool for raid and mirror plugins.
8779 Reworked thread initialization for dmeventd plugins.
8780 Dmeventd handles snapshot overflow for now equally as invalid.
8781 Convert dmeventd to use common logging macro system from libdm.
8782 Return -ENOMEM when device registration fails instead of 0 (=success).
8783 Enforce writethrough mode for cleaner policy.
8784 Add support for recognition and deactivation of MD devices to blkdeactivate.
8785 Move target status functions out of libdm-deptree.
8786 Correct use of max_write_behind parameter when generating raid target line.
8787 Fix dm-event systemd service to make sure it is executed before mounting.
8788
8789Version 1.02.109 - 22nd September 2015
8790======================================
8791 Update man pages for dmsetup and dmstats.
8792 Improve help text for dmsetup.
8793 Use --noflush and --nolockfs when removing device with --force.
8794 Parse new Overflow status string for snapshot target.
8795 Check dir path components are valid if using dm_create_dir, error out if not.
8796 Fix /dev/mapper handling to remove dangling entries if symlinks are found.
8797 Make it possible to use blank value as selection for string list report field.
8798
8799Version 1.02.108 - 15th September 2015
8800======================================
8801 Do not check for full thin pool when activating without messages (1.02.107).
8802
8803Version 1.02.107 - 5th September 2015
8804=====================================
8805 Parse thin-pool status with one single routine internally.
8806 Add --histogram to select default histogram fields for list and report.
8807 Add report fields for displaying latency histogram configuration and data.
8808 Add dmstats --bounds to specify histogram boundaries for a new region.
8809 Add dm_histogram_to_string() to format histogram data in string form.
8810 Add public methods to libdm to access numerical histogram config and data.
8811 Parse and store histogram data in dm_stats_list() and dm_stats_populate().
8812 Add an argument to specify histogram bounds to dm_stats_create_region().
8813 Add dm_histogram_bounds_from_{string,uint64_t}() to parse histogram bounds.
8814 Add dm_histogram handle type to represent a latency histogram and its bounds.
8815 Fix devmapper.pc pkgconfig file to not reference non-existent rt.pc file.
8816 Reinstate dm_task_get_info@Base to libdevmapper exports. (1.02.106)
8817
8818Version 1.02.106 - 26th August 2015
8819===================================
8820 Add 'precise' column to statistics reports.
8821 Add --precise switch to 'dmstats create' to request nanosecond counters.
8822 Add precise argument to dm_stats_create_region().
8823 Add support to libdm-stats for precise_timestamps
8824
8825Version 1.02.105 - 17th August 2015
8826===================================
8827 Fix 'dmstats list -o all' segfault.
8828 Separate dmstats statistics fields from region information fields.
8829 Add interval and interval_ns fields to dmstats reports.
8830 Do not include internal glibc headers in libdm-timestamp.c (1.02.104)
8831 Exit immediately if no device is supplied to dmsetup wipe_table.
8832 Suppress dmsetup report headings when no data is output. (1.02.104)
8833 Adjust dmsetup usage/help output selection to match command invoked.
8834 Fix dmsetup -o all to select correct fields in splitname report.
8835 Restructure internal dmsetup argument handling across all commands.
8836 Add dm_report_is_empty() to indicate there is no data awaiting output.
8837 Add more arg validation for dm_tree_node_add_cache_target().
8838 Add --alldevices switch to replace use of --force for stats create / delete.
8839
8840Version 1.02.104 - 10th August 2015
8841===================================
8842 Add dmstats.8 man page
8843 Add dmstats --segments switch to create one region per device segment.
8844 Add dmstats --regionid, --allregions to specify a single / all stats regions.
8845 Add dmstats --allprograms for stats commands that filter by program ID.
8846 Add dmstats --auxdata and --programid args to specify aux data and program ID.
8847 Add report stats sub-command to provide repeating stats reports.
8848 Add clear, delete, list, and print stats sub-commands.
8849 Add create stats sub-command and --start, --length, --areas and --areasize.
8850 Recognize 'dmstats' as an alias for 'dmsetup stats' when run with this name.
8851 Add a 'stats' command to dmsetup to configure, manage and report stats data.
8852 Add statistics fields to dmsetup -o.
8853 Add libdm-stats library to allow management of device-mapper statistics.
8854 Add --nosuffix to suppress dmsetup unit suffixes in report output.
8855 Add --units to control dmsetup report field output units.
8856 Add support to redisplay column headings for repeating column reports.
8857 Fix report header and row resource leaks.
8858 Report timestamps of ioctls with dmsetup -vvv.
8859 Recognize report field name variants without any underscores too.
8860 Add dmsetup --interval and --count to repeat reports at specified intervals.
8861 Add dm_timestamp functions to libdevmapper.
8862 Recognise vg/lv name format in dmsetup.
8863 Move size display code to libdevmapper as dm_size_to_string.
8864
8865Version 1.02.103 - 24th July 2015
8866=================================
8867 Introduce libdevmapper wrappers for all malloc-related functions.
8868
8869Version 1.02.102 - 7th July 2015
8870================================
8871 Include tool.h for default non-library use.
8872 Introduce format macros with embedded % such as FMTu64.
8873
8874Version 1.02.101 - 3rd July 2015
8875================================
8876 Add experimental support to passing messages in suspend tree.
8877 Add dm_report_value_cache_{set,get} to support caching during report/select.
8878 Add dm_report_reserved_handler to handle report reserved value actions.
8879 Support dynamic value in select: DM_REPORT_FIELD_RESERVED_VALUE_DYNAMIC_VALUE.
8880 Support fuzzy names in select: DM_REPORT_FIELD_RESERVED_VALUE_FUZZY_NAMES.
8881 Thin pool trace messages show a device name and major:minor.
8882
8883Version 1.02.100 - 30th June 2015
8884=================================
8885 Add since, after, until and before time operators to be used in selection.
8886 Add support for time in reports and selection: DM_REPORT_FIELD_TYPE_TIME.
8887 Support report reserved value ranges: DM_REPORT_FIELD_RESERVED_VALUE_RANGE.
8888 Support report reserved value names: DM_REPORT_FIELD_RESERVED_VALUE_NAMED.
8889 Add DM_CONFIG_VALUE_FMT_{INT_OCTAL,STRING_NO_QUOTES} config value format flag.
8890 Add DM_CONFIG_VALUE_FMT_COMMON_{ARRAY,EXTRA_SPACE} config value format flag.
8891 Add dm_config_value_{get,set}_format_flags to get and set config value format.
8892
8893Version 1.02.99 - 20th June 2015
8894================================
8895 New dm_tree_node_set_thin_pool_read_only(DM_1_02_99) for read-only thin pool.
8896 Enhance error message when thin-pool message fails.
8897 Fix dmeventd logging to avoid threaded use of static variable.
8898 Remove redundant dmeventd SIGALRM coded.
8899
8900Version 1.02.98 - 12th June 2015
8901================================
8902 Add dm_task_get_errno() to return any unexpected errno from a dm ioctl call.
8903 Use copy of errno made after each dm ioctl call in case errno changes later.
8904
8905Version 1.02.97 - 15th May 2015
8906===============================
8907 New dm_task_get_info(DM_1_02_97) supports internal_suspend state.
8908 New symbols are versioned and comes with versioned symbol name (DM_1_02_97).
8909
8910Version 1.02.96 - 2nd May 2015
8911==============================
8912 Fix selection to not match if using reserved value in criteria with >,<,>=,<.
8913 Fix selection to not match reserved values for size fields if using >,<,>=,<.
8914 Include uuid or device number in log message after ioctl failure.
8915 Add DM_INTERNAL_SUSPEND_FLAG to dm-ioctl.h.
8916 Install blkdeactivate script and its man page with make install_device-mapper.
8917
8918Version 1.02.95 - 15th March 2015
8919=================================
8920 Makefile regenerated.
8921
8922Version 1.02.94 - 4th March 2015
8923================================
8924 Add dm_report_object_is_selected for generalized interface for report/select.
8925
8926Version 1.02.93 - 21st January 2015
8927===================================
8928 Reduce severity of ioctl error message when dmeventd waitevent is interrupted.
8929 Report 'unknown version' when incompatible version numbers were not obtained.
8930 Report more info from thin pool status (out of data, metadata-ro, fail).
8931 Support error_if_no_space for thin pool target.
8932 Fix segfault while using selection with regex and unbuffered reporting.
8933 Add dm_report_compact_fields to remove empty fields from report output.
8934 Remove unimplemented dm_report_set_output_selection from libdevmapper.h.
8935
8936Version 1.02.92 - 24th November 2014
8937====================================
8938 Fix memory corruption with sorting empty string lists (1.02.86).
8939 Fix man dmsetup.8 syntax warning of Groff
8940 Accept unquoted strings and / in place of {} when parsing configs.
8941
8942Version 1.02.91 - 11th November 2014
8943====================================
8944 Update cache creation and dm_config_node to pass policy.
8945 Allow activation of any thin-pool if transaction_id supplied is 0.
8946 Don't print uninitialized stack bytes when non-root uses dm_check_version().
8947 Fix selection criteria to not match reserved values when using >, <, >=, <.
8948 Add DM_LIST_HEAD_INIT macro to libdevmapper.h.
8949 Fix dm_is_dm_major to not issue error about missing /proc lines for dm module.
8950
8951Version 1.02.90 - 1st September 2014
8952====================================
8953 Restore proper buffer size for parsing mountinfo line (1.02.89)
8954
8955Version 1.02.89 - 26th August 2014
8956==================================
8957 Improve libdevmapper-event select() error handling.
8958 Add extra check for matching transation_id after message submitting.
8959 Add dm_report_field_string_list_unsorted for str. list report without sorting.
8960 Support --deferred with dmsetup remove to defer removal of open devices.
8961 Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
8962 Add support for selection to match string list subset, recognize { } operator.
8963 Fix string list selection with '[value]' to not match list that's superset.
8964 Fix string list selection to match whole words only, not prefixes.
8965
8966Version 1.02.88 - 5th August 2014
8967=================================
8968 Add dm_tree_set_optional_uuid_suffixes to handle upgrades.
8969
8970Version 1.02.87 - 23rd July 2014
8971================================
8972 Fix dm_report_field_string_list to handle delimiter with multiple chars.
8973 Add dm_report_field_reserved_value for per-field reserved value definition.
8974
8975Version 1.02.86 - 23rd June 2014
8976================================
8977 Make "help" and "?" reporting fields implicit.
8978 Recognize implicit "selected" field if using dm_report_init_with_selection.
8979 Add support for implicit reporting fields which are predefined in libdm.
8980 Add DM_REPORT_FIELD_TYPE_PERCENT: separate number and percent fields.
8981 Add dm_percent_range_t,dm_percent_to_float,dm_make_percent to libdm for reuse.
8982 Add dm_report_reserved_value to libdevmapper for reserved value definition.
8983 Also display field types when listing all fields in selection help.
8984 Recognize "help" keyword in selection string to show brief help for selection.
8985 Always order items reported as string list field lexicographically.
8986 Add dm_report_field_string_list to libdevmapper for direct string list report.
8987 Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
8988 Add dm_str_list to libdevmapper for string list type definition and its reuse.
8989 Add dmsetup -S/--select to define selection criteria for dmsetup reports.
8990 Add dm_report_init_with_selection to intialize report with selection criteria.
8991 Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
8992 Use RemoveOnStop for dm-event.socket systemd unit.
8993 Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.
8994 Warn user about incorrect use of cookie with 'dmsetup remove --force'.
8995 Also recognize 'help'/'?' as reserved sort key name to show help.
8996 Add dm_units_to_factor for size unit parsing.
8997 Increase bitset size for minors for thin dmeventd plugin.
8998
8999Version 1.02.85 - 10th April 2014
9000=================================
9001 Check for sprintf error when building internal device path.
9002 Check for sprintf error when creating path for dm control node.
9003 When buffer for dm_get_library_version() is too small, return error code.
9004 Always reinitialize _name_mangling_mode in dm_lib_init().
9005 Add tracking flag about implicitly added devices into dm_tree.
9006 Stop timeout thread immediately when the last worker thread is finished.
9007 Fix dmeventd logging with parallel wait event processing.
9008 Reuse _node_send_messages() for validation of transaction_id in preload.
9009 Transaction_id could be lower by one only when messages are prepared.
9010 Do not call callback when preload fails.
9011 Wrap is_selinux_enabled() to be called just once.
9012 Use correctly signed 64b constant when working with raid volumes.
9013 Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request.
9014 Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol.
9015 Do not use systemd's reload for dmeventd restart, use dmeventd -R instead.
9016 Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them.
9017
9018Version 1.02.84 - 20th January 2014
9019===================================
9020 Revert activation of activated nodes if a node preload callback fails.
9021 Avoid busy looping on CPU when dmeventd reads event DM_WAIT_RETRY.
9022 Ensure global mutex is held when working with dmeventd thread.
9023 Drop taking timeout mutex for un/registering dmeventd monitor.
9024 Allow section names in config file data to be quoted strings.
9025 Close fifos before exiting in dmeventd restart() error path.
9026 Move printf format string directly into dm_asprintf args list.
9027 Catch invalid use of string sort values when reporting numerical fields.
9028
9029Version 1.02.83 - 13th November 2013
9030====================================
9031 Consistently report on stderr when device is not found for dmsetup info.
9032 Skip race errors when non-udev dmsetup build runs on udev-enabled system.
9033 Skip error message when holders are not present in sysfs.
9034 Use __linux__ instead of linux define to make libdevmapper.h C compliant.
9035 Use mutex to avoid possible race while creating/destroying memory pools.
9036 Require libpthread to build now.
9037
9038Version 1.02.82 - 4th October 2013
9039==================================
9040 Define symbolic names for subsystem udev flags in libdevmapper for easier use.
9041 Make subsystem udev rules responsible for importing DM_SUBSYSTEM_UDEV_FLAG*.
9042
9043Version 1.02.81 - 23rd September 2013
9044=====================================
9045 Tidy dmeventd fifo initialisation.
9046
9047Version 1.02.80 - 20th September 2013
9048=====================================
9049 Detect invalid sector supplied to 'dmsetup message'.
9050 Free any previously-set string if a dm_task_set_* function is called again.
9051 Do not allow passing empty new name for dmsetup rename.
9052 Display any output returned by 'dmsetup message'.
9053 Add dm_task_get_message_response to libdevmapper.
9054
9055Version 1.02.79 - 13th August 2013
9056==================================
9057 Create dmeventd timeout threads as "detached" so exit status is freed.
9058 Add DM_ABORT_ON_INTERNAL_ERRORS env var support to abort on internal errors.
9059
9060Version 1.02.78 - 24th July 2013
9061================================
9062 Process thin messages once to active thin pool target for dm_tree.
9063 Optimize out setting the same value or read_ahead.
9064 Add DM_ARRAY_SIZE public macro.
9065 Move syslog code out of signal handle in dmeventd.
9066 Add DM_TO_STRING public macro.
9067 Always return success on dmeventd -V command call.
9068 Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
9069 Add dm_get_status_snapshot() for parsing snapshot status.
9070 Detecte mounted fs also via reading /proc/self/mountinfo.
9071 Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
9072 Report error for nonexisting devices in dmeventd communication.
9073 Prevent double free error after dmeventd call of _fill_device_data().
9074 Update dmevent structure message_data to simplify/fix error path handling.
9075 Validate passed params to dm_get_status_raid/thin/thin_pool().
9076 Fix 'dmsetup splitname -o' to not fail if used without '-c' switch (1.02.68).
9077 Add dm_config_write_{node_out/one_node_out} for enhanced config output.
9078 Add dm_config_value_is_bool to check for boolean value in supported formats.
9079 Fix config node lookup inside empty sections to not return the section itself.
9080 Append discards and read-only fields to exported struct dm_status_thin_pool.
9081 Fix segfault for truncated string token in config file after the first '"'.
9082 Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
9083 Fix resource leak in error path of dmeventd's umount of thin volume.
9084 Automatically deactivate failed preloaded dm tree node.
9085 Add DM_DISABLE_UDEV environment variable to manage dev nodes by libdm only.
9086 Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
9087
9088Version 1.02.77 - 15th October 2012
9089===================================
9090 Support unmount of thin volumes from pool above thin pool threshold.
9091 Update man page to reflect that dm UUIDs are being mangled as well.
9092 Apply 'dmsetup mangle' for dm UUIDs besides dm names.
9093 Add 'mangled_uuid' and 'unmangled_uuid' fields to dmsetup info -c -o.
9094 Mangle device UUID on dm_task_set_uuid/newuuid call if necessary.
9095 Add dm_task_get_uuid_mangled/unmangled to libdevmapper.
9096 Always reset delay_resume_if_new flag when stacking thin pool over anything.
9097 Don't create value for dm_config_node and require dm_config_create_value call.
9098 Check for existing new_name for dmsetup rename.
9099 Fix memory leak in dmsetup _get_split_name() error path.
9100
9101Version 1.02.76 - 7th August 2012
9102=================================
9103 Add dm_vasprintf to libdevmapper.
9104 Allow --noflush with dmsetup status and wait (for thin target).
9105 Add dm_config_write_one_node to libdevmapper.
9106 Support thin pool message release/reserve_metadata_snap in libdevmapper.
9107 Support thin pool discards and external origin features in libdevmapper.
9108 Add configure --enable-udev-rule-exec-detection to detect exec path in rules.
9109 Use sbindir in udev rules by default and remove executable path detection.
9110 Remove hard-coded paths for dmeventd fifos and use default-dm-run-dir.
9111 Add configure --with-lvmetad-pidfile to remove hard-coded value.
9112 Add configure --with-default-pid-dir for common directory with pid files.
9113 Add configure --with-default-dm-run-dir to set run directory for dm tools.
9114 Detect kernel_send() errors in cmirrord.
9115 Add __attribute__ instrumentation to libdevmapper.h.
9116 Print clean_bits instead of sync_bits in pull_state in cmirrord.
9117 Add tests for errors from closedir(), close() in cmirrord.
9118 Add documentation references in systemd units.
9119 Remove veritysetup. Now maintained with cryptsetup.
9120
9121Version 1.02.75 - 8th June 2012
9122===============================
9123 Upstream source repo now fedorahosted.org git not sources.redhat.com CVS.
9124 Remove unsupported udev_get_dev_path libudev call used for checking udev dir.
9125 Set delay_resume_if_new on deptree snapshot origin.
9126 Log value chosen in _find_config_bool like other variable types do.
9127 Wait for dmeventd to exit after sending it DM_EVENT_CMD_DIE when restarting.
9128 Append 'Used' to {Blk}DevNames/DevNos dmsetup report headers for clarity.
9129 Add configure --with-veritysetup for independent veritysetup tool.
9130 Properly support supplied dmevent path in dm_event_register_handler().
9131 Remove dmeventd fifos on exit if they are not managed by systemd.
9132 Use SD_ACTIVATION environment variable in systemd units to detect systemd.
9133 Only start a new dmeventd instance on restart if one was already running.
9134 Extend the time waited for input from dmeventd fifo to 5 secs. (1.02.73)
9135
9136Version 1.02.74 - 6th March 2012
9137================================
9138 Check for multiply-mangled names in auto mangling mode.
9139 Fix dm_task_get_name_unmangled to not unmangle already unmangled name.
9140 Check whether device names are properly mangled on ioctl return.
9141 Deactivation of failed thin check on thin pool returns success.
9142
9143Version 1.02.73 - 3rd March 2012
9144================================
9145 Test _thread_registry list with holding mutex in dmeventd.
9146 Add dm_tree_node_set_callback() for preload and deactivation hooks.
9147 Drop unsupported TRIM message for thin pool.
9148 Improve logging for fifo startup in dmeventd.
9149 Better detection of missing dmeventd fifo connection (1.02.71).
9150 Add a few pointer validations in dmsetup.
9151 Support dm_task_get_driver_version() query without version string.
9152 Log failure of pthread_join when cleaning unused threads in dmeventd.
9153 Fix empty string warning logic in _find_config_str. (1.02.68)
9154 Fix dm_task_set_name to properly resolve path to dm name (1.02.71).
9155 Add dm_strncpy() function as a faster strncpy() replacement.
9156
9157Version 1.02.72 - 23rd February 2012
9158====================================
9159 Avoid memory reallocation for dm_asprintf.
9160
9161Version 1.02.71 - 20th February 2012
9162====================================
9163 Switch to using built-in blkid in 13-dm-disk.rules.
9164 Add "watch" rule to 13-dm-disk.rules.
9165 Detect failing fifo and skip 20s retry communication period.
9166 Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
9167 Add dm_lib_init to automatically initialise device-mapper library on load.
9168 Replace any '\' char with '\\' in dm table specification on input.
9169 Add mangle command to dmsetup to provide renaming to correct mangled form.
9170 Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
9171 Add --manglename option to dmsetup to select the name mangling mode.
9172 Add dm_task_get_name_mangled/unmangled to libdevmapper.
9173 Mangle device name on dm_task_set_name/newname call if necessary.
9174 Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper.
9175 Add configure --with-default-name-mangling for udev-friendly dev name charset.
9176 Test for parsed words in _umount() dmeventd snapshot plugin.
9177 Fix memory leak in fail path of parse_loop_device_name() in dmsetup.
9178 Check for missing reply_uuid in dm_event_get_registered_device().
9179 Check for allocation failure in dmeventd restart().
9180 Add few missing allocation failures tests in dmsetup.
9181 Fix potential risk of writing in front of buffer in _sysfs_get_dm_name().
9182
9183Version 1.02.70 - 12th February 2012
9184====================================
9185 Fix dm_event_get_version() check.
9186 Add pointer test for dependency check in _add_dev().
9187 Validate name and uuid params of dm_tree_add_new_dev_with_udev_flags().
9188 Do not crash for dm_report_init() sort_key == NULL and behave like "".
9189 Return error for failing allocation in dm_asprintf().
9190 Add missing test for failing allocation in dm_realloc() code.
9191 Add test for memory allocation failures in regex matcher code.
9192 Simplify dm_task_set_geometry() and use dm_asprintf().
9193 Set all parameters to 0 for dm_get_next_target() for NULL return.
9194 Fix fd resource leak in error path for _udev_notify_sem_create().
9195 Leave space for '\0' for readline() call in _sysfs_get_kernel_name().
9196
9197Version 1.02.69 - 1st February 2012
9198===================================
9199 Clean up dmeventd systemd unit ordering and requirements.
9200
9201Version 1.02.68 - 26th January 2012
9202===================================
9203 Reset all members of info struct in dm_tree_add_new_dev_with_udev_flags.
9204 Add dmsetup wipe_table to replace table with one that uses error target.
9205 Add 'blkdevname' and 'blkdevs_used' fields to dmsetup info -c -o.
9206 Add 'blkdevname' option to dmsetup ls --tree to see block device names.
9207 Add -o devno/blkdevname/devname to dmsetup deps and ls.
9208 Add dm_device_get_name to get map name or block device name for given devno.
9209 Remove empty devices when clearing left-over inactive tables in deptree.
9210 Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix.
9211 Improve dmsetup man page description of readahead parameter.
9212 Use sysfs to set/get readahead if possible.
9213 Fix lvm2-monitor init script to use normalized output when using vgs.
9214 Add test for max length (DM_MAX_TYPE_NAME) of target type name.
9215 Include a copy of kernel DM documentation in doc/kernel.
9216 Improve man page style for dmsetup and mention more targets.
9217 Fix _get_proc_number to be tolerant of malformed /proc/misc entries.
9218 Fix missing thread list manipulation protection in dmeventd.
9219 Add ExecReload to dm-event.service for systemd to reload dmeventd properly.
9220 Add dm_config_tree_find_str_allow_empty and dm_config_find_str_allow_empty.
9221 Fix compile-time pool memory locking with DEBUG_MEM.
9222 Fix valgrind error reports in free of pool chunks with DEBUG_MEM.
9223 Align size of structure chunk for fast pool allocator to 8 bytes.
9224 Simplify some pointer operations in dm_free_aux() debug code.
9225 Remove unused dbg_malloc.h file from source tree.
9226 Cleanup backtraces for _create_and_load_v4().
9227 Fix alignment warning in bitcount calculation for raid segment.
9228 Allocate dm_tree structure from dm_tree pool.
9229 Update debug logging for _resume_node.
9230 Add functions to support thin provisioning target.
9231 Improve libdm-config error path reporting.
9232 Update dmsetup resume man with --addnodeonresume/create options.
9233 Add dependency for dm man pages to man subdirectory make all target.
9234 Add dm_tree_retry_remove to use retry logic for device removal in a dm_tree.
9235 Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.
9236 Add dm_device_has_holders fn to to check use of the device by another device.
9237 Add dm_sysfs_dir to libdevmapper to retrieve sysfs location set.
9238 Add dm_set_sysfs_dir to libdevmapper to set sysfs location.
9239 Add --retry option for dmsetup remove to retry removal if not successful.
9240 Add dm_task_retry_remove fn to use retry logic for device removal.
9241 Remove unused passed parameters for _mirror_emit_segment_line().
9242 Add dm_config and string character escaping functions to libdevmapper.
9243 Mark unreleased memory pools as internal error.
9244
9245Version 1.02.67 - 19th August 2011
9246==================================
9247 Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked.
9248
9249Version 1.02.66 - 12th August 2011
9250==================================
9251 Release geometry buffer in dm_task_destroy.
9252 Update udev rules to skip DM flags decoding for removed devices.
9253 Add compile-time pool memory locking options (to debug shared VG structs).
9254 Remove device name prefix from dmsetup line output if -j & -m or -u supplied.
9255 Remove support for the original version 1 dm ioctls.
9256 Add missing check for allocation failure _create_dir_recursive().
9257 Add support for systemd file descriptor handover in dmeventd.
9258 Fix memory leak in dmsetup _message() memory allocation error path.
9259 Use new oom killer adjustment interface (oom_score_adj) when available.
9260 Add systemd unit files for dmeventd.
9261 Fix read-only identical table reload supression.
9262
9263Version 1.02.65 - 8th July 2011
9264===============================
9265 Remove dev name prefix from dmsetup line output if exactly one dev requested.
9266 Report internal error if suspending a device using an already-suspended dev.
9267 Report error if a table load requiring target parameters has none supplied.
9268 Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
9269 Add age_in_minutes parameter to dmsetup udevcomplete_all.
9270 Return immediately from dm_lib_exit() if called more than once.
9271 Disable udev fallback by default and add --verifyudev option to dmsetup.
9272 Report internal error if any table is loaded while any dev is known suspended.
9273 Add dm_get_suspended_counter() for number of devs in suspended state by lib.
9274 Fix "all" report field prefix matching to include label fields with pv_all.
9275 Delay resuming new preloaded mirror devices with core logs in deptree code.
9276 Accept new kernel version 3 uname formats in initialisation.
9277
9278Version 1.02.64 - 29th April 2011
9279==================================
9280 Require libudev >= 143 when compiling with udev support.
9281 Use word alignment for dm_pool_strdup() and dm_pool_strndup().
9282 Use dm_snprintf() to fix signedness warning in dm_set_dev_dir().
9283 Use unsigned loop counter to fix signedness warning in _other_node_ops().
9284 Fix const cast in dmsetup calls of dm_report_field_string().
9285 Streamline /dev/mapper/control node code for common cases.
9286 Use hard-coded dm control node device number for 2.6.36 kernels and above.
9287 Improve stack debug reporting in dm_task_create().
9288 Fallback to control node creation only if node doesn't exist yet.
9289 Change dm_hash binary functions to take void *key instead of char *.
9290 Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
9291 Lower severity of selabel_lookup and matchpathcon failure to log_debug.
9292 Add test for failed allocation from dm_task_set_uuid() in dmeventd.
9293 Add dm_event_get_version to dmeventd for use with -R.
9294 Avoid dmeventd core dumps when handling request with unknown command ID.
9295 Have dmeventd -R start up even when no existing copy is running.
9296 Accept multiple mapped device names on many dmsetup command lines.
9297 Fix dm_udev_wait calls in dmsetup to occur before readahead display not after.
9298 Include an implicit dm_task_update_nodes() within dm_udev_wait().
9299 Fix _create_and_load_v4 not to lose the --addnodeoncreate setting (1.02.62).
9300 Add inactive table query support for kernel driver >= 4.11.6 (RHEL 5.7).
9301 Log debug open_count in _node_has_closed_parents().
9302 Add a const to dm_report_field_string() data parameter.
9303
9304Version 1.02.63 - 9th February 2011
9305===================================
9306 Reinstate DEBUG_MEM as it's part of the API. (1.02.62)
9307
9308Version 1.02.62 - 4th February 2011
9309===================================
9310 Add configure --with-device-nodes-on=create for previous behaviour.
9311 Move creation of device nodes from 'create' to 'resume'.
9312 Add --addnodeonresume and --addnodeoncreate options to dmsetup.
9313 Add dm_task_set_add_node to libdevmapper to control dev node creation time.
9314 Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
9315 Log debug message when expected uevent is not generated.
9316 Only compile memory debugging code when DEBUG_MEM is set.
9317 Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
9318 Begin a new pool object for each row in _output_as_rows() correctly.
9319
9320Version 1.02.61 - 10th January 2011
9321===================================
9322 Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
9323 Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control.
9324
9325Version 1.02.60 - 20th December 2010
9326====================================
9327 Check for unlink failure in remove_lockfile() in dmeventd.
9328 Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
9329 Use char* arithmetic in _process_all() & _targets() in dmsetup.
9330 Change dm_regex_create() API to accept const char * const *patterns.
9331 Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
9332 Detect existence of new SELinux selabel interface during configure.
9333
9334Version 1.02.59 - 6th December 2010
9335===================================
9336 Add backtraces to _process_mapper_dir and _create_and_load_v4 error paths.
9337 Remove superfluous checks for NULL before calling dm_free.
9338
9339Version 1.02.58 - 22nd November 2010
9340====================================
9341 Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57)
9342
9343Version 1.02.57 - 8th November 2010
9344===================================
9345 Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
9346 Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
9347 Fix memory leak of field_id in _output_field function.
9348 Allocate buffer for reporting functions dynamically to support long outputs.
9349
9350Version 1.02.56 - 25th October 2010
9351===================================
9352 Return const pointer from dm_basename() in libdevmapper.
9353 Implement dmeventd -R to restart without state loss.
9354 Add dm_zalloc and use it and dm_pool_zalloc throughout.
9355 Add --setuuid to dmsetup rename.
9356 Add dm_task_set_newuuid to set uuid of mapped device post-creation.
9357
9358Version 1.02.55 - 24th September 2010
9359=====================================
9360 Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
9361 Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
9362
9363Version 1.02.54 - 18th August 2010
9364==================================
9365 Fix dm-mod autoloading logic to not assume control node is set correctly.
9366 Add dmeventd/executable to lvm.conf to test alternative dmeventd.
9367 Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
9368 Generate libdevmapper-event exported symbols.
9369 Remove superfluous NULL pointer tests before dm_free from dmeventd.
9370 Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
9371 Fix udev rules to support udev database content generated by older rules.
9372 Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
9373 Fix regex ttree off-by-one error.
9374 Add --enable-valgrind-pool to configure.
9375 Fix segfault in regex matcher with characters of ordinal value > 127.
9376 Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c.
9377 Wait for node creation before displaying debug info in dmsetup.
9378 Fix return status 0 for "dmsetup info -c -o help".
9379 Add check for kernel semaphore support and disable udev_sync if not available.
9380
9381Version 1.02.53 - 28th July 2010
9382================================
9383 Revert failed table load preparation after "create, load and resume".
9384 Switch dmeventd to use dm_create_lockfile and drop duplicate code.
9385 Add dm_create_lockfile to libdm to handle pidfiles for all daemons.
9386 Replace lookup with next in struct dfa_state & calculate states on demand.
9387 Improve the regex matcher, reducing the number of charset nodes used.
9388 Add dm_regex_fingerprint to facilitate regex testing.
9389 Skip ffs(0) in _test_word in bitset functions.
9390 Use "nowatch" udev rule for inappropriate devices.
9391
9392Version 1.02.52 - 6th July 2010
9393===============================
9394 Fix dmlosetup snprintf %llu compiler warning.
9395 Add parentheses to some libdevmapper.h macro arguments.
9396 Add printf format attributes to dm_{sn,as}printf and fix a caller.
9397 Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50)
9398
9399Version 1.02.51 - 30th June 2010
9400================================
9401 Generate libdevmapper exported symbols from header file.
9402
9403Version 1.02.50 - 23rd June 2010
9404================================
9405 Fix INTERNAL_ERROR typo in ioctl iface unknown task message.
9406 Fix udev rules to handle spurious events properly.
9407 Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified.
9408 Allow use of devmapper header file in C++ mode (extern "C" and __typeof__).
9409 Add dmeventd man page.
9410
9411Version 1.02.49 - 4th June 2010
9412===============================
9413 Support autoloading of dm-mod module for kernels from 2.6.35.
9414 Document 'clear' in dmsetup man page.
9415 Fix semctl parameter (union) to avoid misaligned parameter on some arches.
9416 Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
9417 Initial support for replicator target.
9418
9419Version 1.02.48 - 17th May 2010
9420================================
9421 Use -d to control level of messages sent to syslog by dmeventd.
9422 Change -d to -f to run dmeventd in foreground.
9423 Do not print encryption key in message debug output (cryptsetup luksResume).
9424 Fix dmeventd static build library dependencies.
9425 Fix udev flags on remove in create_and_load error path.
9426
9427Version 1.02.47 - 30th April 2010
9428=================================
9429 Add support for new IMPORT{db} udev rule.
9430 Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
9431 Also include udev libs in libdevmapper.pc when udev_sync is enabled.
9432 Cache bitset locations to speed up _calc_states.
9433 Add a regex optimisation pass for shared prefixes and suffixes.
9434 Add dm_bit_and and dm_bitset_equal to libdevmapper.
9435 Simplify dm_bitset_create.
9436 Speed up dm_bit_get_next with ffs().
9437
9438Version 1.02.46 - 14th April 2010
9439=================================
9440 Change dm_tree_deactivate_children to fail if device is open.
9441 Wipe memory buffers for dm-ioctl parameters before releasing.
9442 Strictly require libudev if udev_sync is used.
9443 Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
9444
9445Version 1.02.45 - 9th March 2010
9446================================
9447 Add --showkeys parameter description to dmsetup man page.
9448 Add --help option as synonym for help command.
9449
9450Version 1.02.44 - 15th February 2010
9451====================================
9452 Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
9453 Export dm_udev_create_cookie function to create new cookies on demand.
9454 Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
9455 Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
9456
9457Version 1.02.43 - 21st January 2010
9458===================================
9459 Remove bitset, hash and pool headers superceded by libdevmapper.h.
9460 Fix off-by-one error causing bad cluster mirror table construction.
9461
9462Version 1.02.42 - 14th January 2010
9463===================================
9464 Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
9465 Introduce a third activation_priority level in dm_tree_activate_children.
9466
9467Version 1.02.41 - 12th January 2010
9468===================================
9469 If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
9470 Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
9471 Add --noudevrules option for dmsetup to disable /dev node management by udev.
9472 Fix 'dmsetup info -c -o all' to show all fields.
9473 Return errors if dm_tree_*_children functions fail.
9474 Fix coredump and memory leak for 'dmsetup help -c'.
9475 Disable udev rules for change events with DISK_RO set.
9476
9477Version 1.02.40 - 19th November 2009
9478====================================
9479 Fix install_device-mapper Makefile target to not build dmeventd plugins.
9480 Support udev flags even when udev_sync is disabled or not compiled in.
9481 Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
9482 Add dmsetup --inactive support.
9483 Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
9484 Fix hash lookup segfault when keys compared are different lengths.
9485
9486Version 1.02.39 - 26th October 2009
9487===================================
9488 Remove strict default permissions for DM devices from 95-dm-notify.rules.
9489 Add dmsetup udevflags command to decode udev flags in given cookie value.
9490 Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
9491 Make libdm ABI consistent when built with/without selinux support.
9492
9493Version 1.02.38 - 25th September 2009
9494=====================================
9495 Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
9496 Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
9497 Add several examples to 12-dm-permissions.rules.
9498 Add splitname and --yes to dmsetup man page.
9499 Fix _mirror_emit_segment_line return code.
9500 Fix dmeventd _temporary_log_fn parameters. (2.02.50)
9501
9502Version 1.02.37 - 15th September 2009
9503=====================================
9504 Add dmsetup manpage entries for udevcomplete_all and udevcookies.
9505 Check udev is running when processing cookies and retain state internally.
9506 Add y|--yes option to dmsetup for default 'yes' answer to prompts.
9507 Fix tools Makefile to process dmsetup sources separately.
9508 Restore umask when device node creation fails.
9509 Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
9510 Add dm-log-userspace.h to tree for cmirrord builds.
9511
9512Version 1.02.36 - 6th August 2009
9513=================================
9514 Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
9515 Add libdevmapper functions to support synchronisation with udev.
9516
9517Version 1.02.35 - 28th July 2009
9518================================
9519 Add LOG_LINE_WITH_ERRNO macro.
9520 Use log_error macro consistently throughout in place of log_err.
9521
9522Version 1.02.34 - 15th July 2009
9523================================
9524 Use _exit() not exit() after forking to avoid flushing libc buffers twice.
9525 Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
9526 Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
9527 Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
9528 Fix whitespace in linear target line to fix identical table line detection.
9529 Add device number to more log messages during activation.
9530
9531Version 1.02.33 - 30th June 2009
9532================================
9533 Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
9534 Do not fork daemon when dmeventd cannot be found.
9535 Add crypt target handling to libdevmapper tree nodes.
9536 Add splitname command to dmsetup.
9537 Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
9538 Make mempool optional in dm_split_lvm_name().
9539
9540Version 1.02.32 - 21st May 2009
9541===============================
9542 Only generate libdevmapper.a when configured to link statically.
9543 Export dm_tree_node_size_changed() from libdevmapper.
9544 Propagate the table size_changed property up the dm device tree.
9545 Detect failure to free memory pools when releasing the library.
9546 Fix segfault when getopt processes dmsetup -U, -G and -M options.
9547
9548Version 1.02.31 - 3rd March 2009
9549================================
9550 If kernel supports only one dm major number, use in place of any supplied.
9551
9552Version 1.02.30 - 26th January 2009
9553====================================
9554 Add "all" field to reports expanding to all fields of report type.
9555 Enforce device name length and character limitations in libdm.
9556 Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
9557
9558Version 1.02.29 - 10th November 2008
9559====================================
9560 Merge device-mapper into the LVM2 tree.
9561 Split out dm-logging.h from log.h.
9562 Use lvm-types.h.
9563 Add usrsbindir to configure.
9564
9565Version 1.02.28 - 18th September 2008
9566=====================================
9567 Only resume devices in dm_tree_preload_children if size changes.
9568 Extend deptree buffers so the largest possible device numbers fit.
9569 Generate versioned libdevmapper-event.so.
9570 Underline longer report help text headings.
9571
9572Version 1.02.27 - 25th June 2008
9573================================
9574 Align struct memblock in dbg_malloc for sparc.
9575 Add --unquoted and --rows to dmsetup.
9576 Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
9577 Fix inverted no_flush debug message.
9578 Remove --enable-jobs from configure. (Set at runtime instead.)
9579 Bring configure.in and list.h into line with the lvm2 versions.
9580
9581Version 1.02.26 - 6th June 2008
9582===============================
9583 Initialise params buffer to empty string in _emit_segment.
9584 Skip add_dev_node when ioctls disabled.
9585 Make dm_hash_iter safe against deletion.
9586 Accept a NULL pointer to dm_free silently.
9587 Add tables_loaded, readonly and suspended columns to reports.
9588 Add --nameprefixes to dmsetup.
9589 Add field name prefix option to reporting functions.
9590 Calculate string size within dm_pool_grow_object.
9591
9592Version 1.02.25 - 10th April 2008
9593=================================
9594 Remove redundant if-before-free tests.
9595 Use log_warn for reporting field help text instead of log_print.
9596 Change cluster mirror log type name (s/clustered_/clustered-/)
9597
9598Version 1.02.24 - 20th December 2007
9599====================================
9600 Fix deptree to pass new name to _resume_node after a rename.
9601 Suppress other node operations if node is deleted.
9602 Add node operation stack debug messages.
9603 Report error when empty device name passed to readahead functions.
9604 Fix minimum readahead debug message.
9605
9606Version 1.02.23 - 5th December 2007
9607===================================
9608 Update dm-ioctl.h after removal of compat code.
9609 Add readahead support to libdevmapper and dmsetup.
9610 Fix double free in a libdevmapper-event error path.
9611 Fix configure --with-dmeventd-path substitution.
9612 Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
9613 Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
9614 Avoid static link failure with some SELinux libraries that require libpthread.
9615 Remove obsolete dmfs code from tree and update INSTALL.
9616
9617Version 1.02.22 - 21st August 2007
9618==================================
9619 Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
9620 Update to use autoconf 2.61, while still supporting 2.57.
9621 Avoid repeated dm_task free on some dm_event_get_registered_device errors.
9622 Introduce log_sys_* macros from LVM2.
9623 Export dm_fclose and dm_create_dir; remove libdm-file.h.
9624 Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
9625 Add fclose wrapper dm_fclose that catches write failures (using ferror).
9626
9627Version 1.02.21 - 13th July 2007
9628================================
9629 Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
9630 Fix dmsetup -o devno string termination. (1.02.20)
9631
9632Version 1.02.20 - 15th June 2007
9633================================
9634 Fix default dmsetup report buffering and add --unbuffered.
9635 Add tree-based and dependency fields to dmsetup reports.
9636
9637Version 1.02.19 - 27th April 2007
9638=================================
9639 Standardise protective include file #defines.
9640 Add regex functions to library.
9641 Avoid trailing separator in reports when there are hidden sort fields.
9642 Fix segfault in 'dmsetup status' without --showkeys against crypt target.
9643 Deal with some more compiler warnings.
9644 Introduce _add_field() and _is_same_field() to libdm-report.c.
9645 Fix some libdevmapper-event and dmeventd memory leaks.
9646 Remove unnecessary memset() return value checks.
9647 Fix a few leaks in reporting error paths. [1.02.15+]
9648
9649Version 1.02.18 - 13th February 2007
9650====================================
9651 Improve dmeventd messaging protocol: drain pipe and tag messages.
9652
9653Version 1.02.17 - 29th January 2007
9654===================================
9655 Add recent reporting options to dmsetup man page.
9656 Revise some report fields names.
9657 Add dmsetup 'help' command and update usage text.
9658 Use fixed-size fields in report interface and reorder.
9659
9660Version 1.02.16 - 25th January 2007
9661===================================
9662 Add some missing close() and fclose() return value checks.
9663 Migrate dmsetup column-based output over to new libdevmapper report framework.
9664 Add descriptions to reporting field definitions.
9665 Add a dso-private variable to dmeventd dso interface.
9666 Add dm_event_handler_[gs]et_timeout functions.
9667 Streamline dm_report_field_* interface.
9668 Add cmdline debug & version options to dmeventd.
9669 Add DM_LIB_VERSION definition to configure.h.
9670 Suppress 'Unrecognised field' error if report field is 'help'.
9671 Add --separator and --sort to dmsetup (unused).
9672 Make alignment flag optional when specifying report fields.
9673
9674Version 1.02.15 - 17th January 2007
9675===================================
9676 Add basic reporting functions to libdevmapper.
9677 Fix a malloc error path in dmsetup message.
9678 More libdevmapper-event interface changes and fixes.
9679 Rename dm_saprintf() to dm_asprintf().
9680 Report error if NULL pointer is supplied to dm_strdup_aux().
9681 Reinstate dm_event_get_registered_device.
9682
9683Version 1.02.14 - 11th January 2007
9684===================================
9685 Add dm_saprintf().
9686 Use CFLAGS when linking so mixed sparc builds can supply -m64.
9687 Add dm_tree_use_no_flush_suspend().
9688 Lots of dmevent changes including revised interface.
9689 Export dm_basename().
9690 Cope with a trailing space when comparing tables prior to possible reload.
9691 Fix dmeventd to cope if monitored device disappears.
9692
9693Version 1.02.13 - 28 Nov 2006
9694=============================
9695 Update dmsetup man page (setgeometry & message).
9696 Fix dmsetup free after getline with debug.
9697 Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
9698
9699Version 1.02.12 - 13 Oct 2006
9700=============================
9701 Avoid deptree attempting to suspend a device that's already suspended.
9702
9703Version 1.02.11 - 12 Oct 2006
9704==============================
9705 Add suspend noflush support.
9706 Add basic dmsetup loop support.
9707 Switch dmsetup to use dm_malloc and dm_free.
9708
9709Version 1.02.10 - 19 Sep 2006
9710=============================
9711 Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
9712 Reorder mm bounds_check code to reduce window for a dmeventd race.
9713
9714Version 1.02.09 - 15 Aug 2006
9715=============================
9716 Add --table argument to dmsetup for a one-line table.
9717 Abort if errors are found during cmdline option processing.
9718 Add lockfs indicator to debug output.
9719
9720Version 1.02.08 - 17 July 2006
9721==============================
9722 Append full patch to check in emails.
9723 Avoid duplicate dmeventd subdir with 'make distclean'.
9724 Update dmsetup man page.
9725 Add --force to dmsetup remove* to load error target.
9726 dmsetup remove_all also performs mknodes.
9727 Don't suppress identical table reloads if permission changes.
9728 Fix corelog segment line.
9729 Suppress some compiler warnings.
9730
9731Version 1.02.07 - 11 May 2006
9732=============================
9733 Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
9734 Avoid a dmeventd compiler warning.
9735
9736Version 1.02.06 - 10 May 2006
9737=============================
9738 Move DEFS into configure.h.
9739 Fix leaks in error paths found by coverity.
9740 Remove dmsetup line buffer limitation.
9741
9742Version 1.02.05 - 19 Apr 2006
9743=============================
9744 Separate install_include target in makefiles.
9745 Separate out DEFS from CFLAGS.
9746 Support pkg-config.
9747 Check for libsepol.
9748
9749Version 1.02.04 - 14 Apr 2006
9750=============================
9751 Bring dmsetup man page up-to-date.
9752 Use name-based device refs if kernel doesn't support device number refs.
9753 Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
9754 If _create_and_load_v4 fails part way through, revert the creation.
9755 dmeventd thread/fifo fixes.
9756 Add file & line to dm_strdup_aux().
9757 Add setgeometry.
9758
9759Version 1.02.03 - 7 Feb 2006
9760============================
9761 Add exported functions to set uid, gid and mode.
9762 Rename _log to dm_log and export.
9763 Add dm_tree_skip_lockfs.
9764 Fix dm_strdup debug definition.
9765 Fix hash function to avoid using a negative array offset.
9766 Don't inline _find in hash.c and tidy signed/unsigned etc.
9767 Fix libdevmapper.h #endif.
9768 Fix dmsetup version driver version.
9769 Add sync, nosync and block_on_error mirror log parameters.
9770 Add hweight32.
9771 Fix dmeventd build.
9772
9773Version 1.02.02 - 2 Dec 2005
9774============================
9775 dmeventd added.
9776 Export dm_task_update_nodes.
9777 Use names instead of numbers in messages when ioctls fail.
9778
9779Version 1.02.01 - 23 Nov 2005
9780=============================
9781 Resume snapshot-origins last.
9782 Drop leading zeros from dm_format_dev.
9783 Suppress attempt to reload identical table.
9784 Additional LVM- prefix matching for transitional period.
9785
9786Version 1.02.00 - 10 Nov 2005
9787=============================
9788 Added activation functions to library.
9789 Added return macros.
9790 Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
9791 Export dm_set_selinux_context().
9792 Add dm_driver_version().
9793 Added dependency tree functions to library.
9794 Added hash, bitset, pool, dbg_malloc to library.
9795 Added ls --tree to dmsetup.
9796 Added dmsetup --nolockfs support for suspend/reload.
9797
9798Version 1.01.05 - 26 Sep 2005
9799=============================
9800 Resync list.h with LVM2.
9801 Remember increased buffer size and use for subsequent calls.
9802 On 'buffer full' condition, double buffer size and repeat ioctl.
9803 Fix termination of getopt_long() option array.
9804 Report 'buffer full' condition with v4 ioctl as well as with v1.
9805
9806Version 1.01.04 - 2 Aug 2005
9807============================
9808 Fix dmsetup ls -j and status --target with empty table.
9809
9810Version 1.01.03 - 13 Jun 2005
9811=============================
9812 Use matchpathcon mode parameter.
9813 Fix configure script to re-enable selinux.
9814
9815Version 1.01.02 - 17 May 2005
9816=============================
9817 Call dm_lib_exit() and dm_lib_release() automatically now.
9818 Add --target <target_type> filter to dmsetup table/status/ls.
9819 Add --exec <command> to dmsetup ls.
9820 Fix dmsetup getopt_long usage.
9821
9822Version 1.01.01 - 29 Mar 2005
9823=============================
9824 Update dmsetup man page.
9825 Drop-in devmap_name replacement.
9826 Add option to compile without ioctl for testing.
9827 Fix DM_LIB_VERSION sed.
9828
9829Version 1.01.00 - 17 Jan 2005
9830=============================
9831 Add dm_task_no_open_count() to skip getting open_count.
9832
9833Version 1.00.21 - 7 Jan 2005
9834============================
9835 Fix /proc/devices parsing.
9836
9837Version 1.00.20 - 6 Jan 2005
9838============================
9839 Attempt to fix /dev/mapper/control transparently if it's wrong.
9840 Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
9841 Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
9842 Add --noheadings columns option for colon-separated dmsetup output.
9843 Support device referencing by uuid or major/minor.
9844 Warn if kernel data didn't fit in buffer.
9845 Fix a printf.
9846
9847Version 1.00.19 - 3 July 2004
9848=============================
9849 More autoconf fixes.
9850 Fix a dmsetup newline.
9851 Fix device number handling for 2.6 kernels.
9852
9853Version 1.00.18 - 20 Jun 2004
9854=============================
9855 Fix a uuid free in libdm-iface.
9856 Fix a targets string size calc in driver.
9857 Add -c to dmsetup for column-based output.
9858 Add target message-passing ioctl.
9859
9860Version 1.00.17 - 17 Apr 2004
9861=============================
9862 configure --with-owner= --with-group= to avoid -o and -g args to 'install'
9863 Fix library selinux linking.
9864
9865Version 1.00.16 - 16 Apr 2004
9866=============================
9867 Ignore error setting selinux file context if fs doesn't support it.
9868
9869Version 1.00.15 - 7 Apr 2004
9870============================
9871 Fix status overflow check in kernel patches.
9872
9873Version 1.00.14 - 6 Apr 2004
9874============================
9875 Fix static selinux build.
9876
9877Version 1.00.13 - 6 Apr 2004
9878============================
9879 Add some basic selinux support.
9880
9881Version 1.00.12 - 6 Apr 2004
9882============================
9883 Fix dmsetup.static install.
9884
9885Version 1.00.11 - 5 Apr 2004
9886============================
9887 configure --enable-static_link does static build in addition to dynamic.
9888 Moved Makefile library targets definition into template.
9889
9890Version 1.00.10 - 2 Apr 2004
9891============================
9892 Fix DESTDIR handling.
9893 Static build installs to dmsetup.static.
9894 Basic support for internationalisation.
9895 Minor Makefile tidy-ups/fixes.
9896
9897Version 1.00.09 - 31 Mar 2004
9898=============================
9899 Update copyright notices to Red Hat.
9900 Move full mknodes functionality from dmsetup into libdevmapper.
9901 Avoid sscanf %as for uClibc compatibility.
9902 Cope if DM_LIST_VERSIONS is not defined.
9903 Add DM_LIST_VERSIONS functionality to kernel patches.
9904 Generate new kernel patches for 2.4.26-rc1.
9905
9906Version 1.00.08 - 27 Feb 2004
9907=============================
9908 Added 'dmsetup targets'.
9909 Added event_nr support to 'dmsetup wait'.
9910 Updated dmsetup man page.
9911 Allow logging function to be reset to use internal one.
9912 Bring log macros in line with LVM2 ones.
9913 Added 'make install_static_lib' which installs libdevmapper.a.
9914 Made configure/makefiles closer to LVM2 versions.
9915 Fixed DESTDIR for make install/install_static_lib.
9916 Updated README/INSTALL to reflect move to sources.redhat.com.
9917 Updated autoconf files to 2003-06-17.
9918\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0016536\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/vg_convert\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000001117\013062740170\0020640\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/sh -x
9919
9920# Original script used to convert a VG from LVM1 to LVM2 metadata format.
9921# Superceded by 'vgconvert', but left here to show how to do it step-by-step.
9922
9923# Takes vgname as parameter. No error checking. Uses temp file 'lvmbackup'.
9924
9925echo "Please use the 'vgconvert' tool instead"
9926exit 1
9927
9928./vgcfgbackup $1 || exit 1
9929./vgcfgbackup --file lvmbackup $1 || exit 1
9930
9931CMDS=`./pvscan -u | sed -ne "s/.*PV \(.*\) with UUID \(.*\) VG $1 .*/.\/pvcreate -ff -y -M lvm2 --restorefile lvmbackup -u \2 \1 ; /p"`
9932
9933sh -x -c "$CMDS" || exit 1
9934
9935./vgcfgrestore --file lvmbackup -M lvm2 $1 || exit 1
9936\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmpolld_systemd_red_hat.socket.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000336\013062740170\0026406\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
9937Description=LVM2 poll daemon socket
9938Documentation=man:lvmpolld(8)
9939DefaultDependencies=no
9940
9941[Socket]
9942ListenStream=@DEFAULT_RUN_DIR@/lvmpolld.socket
9943SocketMode=0600
9944RemoveOnStop=true
9945
9946[Install]
9947WantedBy=sysinit.target
9948\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/fsadm.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000035612\013062740170\0020176\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
9949#
9950# Copyright (C) 2007-2012 Red Hat, Inc. All rights reserved.
9951#
9952# This file is part of LVM2.
9953#
9954# This copyrighted material is made available to anyone wishing to use,
9955# modify, copy, or redistribute it subject to the terms and conditions
9956# of the GNU General Public License v.2.
9957#
9958# You should have received a copy of the GNU General Public License
9959# along with this program; if not, write to the Free Software Foundation,
9960# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9961#
9962# Author: Zdenek Kabelac <zkabelac at redhat.com>
9963#
9964# Script for resizing devices (usable for LVM resize)
9965#
9966# Needed utilities:
9967# mount, umount, grep, readlink, blockdev, blkid, fsck, xfs_check
9968#
9969# ext2/ext3/ext4: resize2fs, tune2fs
9970# reiserfs: resize_reiserfs, reiserfstune
9971# xfs: xfs_growfs, xfs_info
9972#
9973# Return values:
9974# 0 success
9975# 1 error
9976# 2 break detected
9977# 3 unsupported online filesystem check for given mounted fs
9978
9979TOOL=fsadm
9980
9981_SAVEPATH=$PATH
9982PATH=/sbin:/usr/sbin:/bin:/usr/sbin:$PATH
9983
9984# utilities
9985TUNE_EXT=tune2fs
9986RESIZE_EXT=resize2fs
9987TUNE_REISER=reiserfstune
9988RESIZE_REISER=resize_reiserfs
9989TUNE_XFS=xfs_info
9990RESIZE_XFS=xfs_growfs
9991
9992MOUNT=mount
9993UMOUNT=umount
9994MKDIR=mkdir
9995RMDIR=rmdir
9996BLOCKDEV=blockdev
9997BLKID=blkid
9998DATE=date
9999GREP=grep
10000READLINK=readlink
10001READLINK_E="-e"
10002FSCK=fsck
10003XFS_CHECK=xfs_check
10004# XFS_REPAIR -n is used when XFS_CHECK is not found
10005XFS_REPAIR=xfs_repair
10006
10007# user may override lvm location by setting LVM_BINARY
10008LVM=${LVM_BINARY:-lvm}
10009
10010YES=${_FSADM_YES}
10011DRY=0
10012VERB=
10013FORCE=
10014EXTOFF=${_FSADM_EXTOFF:-0}
10015DO_LVRESIZE=0
10016FSTYPE=unknown
10017VOLUME=unknown
10018TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$/m"
10019DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
10020BLOCKSIZE=
10021BLOCKCOUNT=
10022MOUNTPOINT=
10023MOUNTED=
10024REMOUNT=
10025PROCMOUNTS="/proc/mounts"
10026PROCSELFMOUNTINFO="/proc/self/mountinfo"
10027NULL="$DM_DEV_DIR/null"
10028
10029IFS_OLD=$IFS
10030# without bash $'\n'
10031NL='
10032'
10033
10034tool_usage() {
10035 echo "${TOOL}: Utility to resize or check the filesystem on a device"
10036 echo
10037 echo " ${TOOL} [options] check <device>"
10038 echo " - Check the filesystem on device using fsck"
10039 echo
10040 echo " ${TOOL} [options] resize <device> [<new_size>[BKMGTPE]]"
10041 echo " - Change the size of the filesystem on device to new_size"
10042 echo
10043 echo " Options:"
10044 echo " -h | --help Show this help message"
10045 echo " -v | --verbose Be verbose"
10046 echo " -e | --ext-offline unmount filesystem before ext2/ext3/ext4 resize"
10047 echo " -f | --force Bypass sanity checks"
10048 echo " -n | --dry-run Print commands without running them"
10049 echo " -l | --lvresize Resize given device (if it is LVM device)"
10050 echo " -y | --yes Answer \"yes\" at any prompts"
10051 echo
10052 echo " new_size - Absolute number of filesystem blocks to be in the filesystem,"
10053 echo " or an absolute size using a suffix (in powers of 1024)."
10054 echo " If new_size is not supplied, the whole device is used."
10055
10056 exit
10057}
10058
10059verbose() {
10060 test -n "$VERB" && echo "$TOOL: $@" || true
10061}
10062
10063error() {
10064 echo "$TOOL: $@" >&2
10065 cleanup 1
10066}
10067
10068dry() {
10069 if [ "$DRY" -ne 0 ]; then
10070 verbose "Dry execution $@"
10071 return 0
10072 fi
10073 verbose "Executing $@"
10074 "$@"
10075}
10076
10077cleanup() {
10078 trap '' 2
10079 # reset MOUNTPOINT - avoid recursion
10080 test "$MOUNTPOINT" = "$TEMPDIR" && MOUNTPOINT="" temp_umount
10081 if [ -n "$REMOUNT" ]; then
10082 verbose "Remounting unmounted filesystem back"
10083 dry "$MOUNT" "$VOLUME" "$MOUNTED"
10084 fi
10085 IFS=$IFS_OLD
10086 trap 2
10087
10088 test "$1" -eq 2 && verbose "Break detected"
10089
10090 if [ "$DO_LVRESIZE" -eq 2 ]; then
10091 # start LVRESIZE with the filesystem modification flag
10092 # and allow recursive call of fsadm
10093 _FSADM_YES=$YES
10094 _FSADM_EXTOFF=$EXTOFF
10095 export _FSADM_YES _FSADM_EXTOFF
10096 unset FSADM_RUNNING
10097 test -n "$LVM_BINARY" && PATH=$_SAVEPATH
10098 dry exec "$LVM" lvresize $VERB $FORCE -r -L${NEWSIZE}b "$VOLUME_ORIG"
10099 fi
10100
10101 # error exit status for break
10102 exit ${1:-1}
10103}
10104
10105# convert parameter from Exa/Peta/Tera/Giga/Mega/Kilo/Bytes and blocks
10106# (2^(60/50/40/30/20/10/0))
10107decode_size() {
10108 case "$1" in
10109 *[eE]) NEWSIZE=$(( ${1%[eE]} * 1152921504606846976 )) ;;
10110 *[pP]) NEWSIZE=$(( ${1%[pP]} * 1125899906842624 )) ;;
10111 *[tT]) NEWSIZE=$(( ${1%[tT]} * 1099511627776 )) ;;
10112 *[gG]) NEWSIZE=$(( ${1%[gG]} * 1073741824 )) ;;
10113 *[mM]) NEWSIZE=$(( ${1%[mM]} * 1048576 )) ;;
10114 *[kK]) NEWSIZE=$(( ${1%[kK]} * 1024 )) ;;
10115 *[bB]) NEWSIZE=${1%[bB]} ;;
10116 *) NEWSIZE=$(( $1 * $2 )) ;;
10117 esac
10118 #NEWBLOCKCOUNT=$(round_block_size $NEWSIZE $2)
10119 NEWBLOCKCOUNT=$(( $NEWSIZE / $2 ))
10120
10121 if [ $DO_LVRESIZE -eq 1 ]; then
10122 # start lvresize, but first cleanup mounted dirs
10123 DO_LVRESIZE=2
10124 cleanup 0
10125 fi
10126}
10127
10128# detect filesystem on the given device
10129# dereference device name if it is symbolic link
10130detect_fs() {
10131 VOLUME_ORIG=$1
10132 VOLUME=${1/#"${DM_DEV_DIR}/"/}
10133 VOLUME=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$VOLUME") || error "Cannot get readlink \"$1\""
10134 RVOLUME=$VOLUME
10135 case "$RVOLUME" in
10136 # hardcoded /dev since udev does not create these entries elsewhere
10137 /dev/dm-[0-9]*)
10138 read </sys/block/${RVOLUME#/dev/}/dm/name SYSVOLUME 2>&1 && VOLUME="$DM_DEV_DIR/mapper/$SYSVOLUME"
10139 read </sys/block/${RVOLUME#/dev/}/dev MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$VOLUME\""
10140 ;;
10141 *)
10142 STAT=$(stat --format "MAJOR=%t MINOR=%T" ${RVOLUME}) || error "Cannot get major:minor for \"$VOLUME\""
10143 eval $STAT
10144 MAJOR=$((0x${MAJOR}))
10145 MINOR=$((0x${MINOR}))
10146 MAJORMINOR=${MAJOR}:${MINOR}
10147 ;;
10148 esac
10149 # use null device as cache file to be sure about the result
10150 # not using option '-o value' to be compatible with older version of blkid
10151 FSTYPE=$("$BLKID" -c "$NULL" -s TYPE "$VOLUME") || error "Cannot get FSTYPE of \"$VOLUME\""
10152 FSTYPE=${FSTYPE##*TYPE=\"} # cut quotation marks
10153 FSTYPE=${FSTYPE%%\"*}
10154 verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
10155}
10156
10157detect_mounted_with_proc_self_mountinfo() {
10158 MOUNTED=$("$GREP" "^[0-9]* [0-9]* $MAJORMINOR " "$PROCSELFMOUNTINFO")
10159
10160 # extract 5th field which is mount point
10161 # echo -e translates \040 to spaces
10162 MOUNTED=$(echo ${MOUNTED} | cut -d " " -f 5)
10163 MOUNTED=$(echo -n -e ${MOUNTED})
10164
10165 test -n "$MOUNTED"
10166}
10167
10168detect_mounted_with_proc_mounts() {
10169 MOUNTED=$("$GREP" "^$VOLUME[ \t]" "$PROCMOUNTS")
10170
10171 # for empty string try again with real volume name
10172 test -z "$MOUNTED" && MOUNTED=$("$GREP" "^$RVOLUME[ \t]" "$PROCMOUNTS")
10173
10174 # cut device name prefix and trim everything past mountpoint
10175 # echo translates \040 to spaces
10176 MOUNTED=${MOUNTED#* }
10177 MOUNTED=$(echo -n -e ${MOUNTED%% *})
10178
10179 # for systems with different device names - check also mount output
10180 if test -z "$MOUNTED" ; then
10181 MOUNTED=$(LC_ALL=C "$MOUNT" | "$GREP" "^$VOLUME[ \t]")
10182 test -z "$MOUNTED" && MOUNTED=$(LC_ALL=C "$MOUNT" | "$GREP" "^$RVOLUME[ \t]")
10183 MOUNTED=${MOUNTED##* on }
10184 MOUNTED=${MOUNTED% type *} # allow type in the mount name
10185 fi
10186
10187 test -n "$MOUNTED"
10188}
10189
10190# check if the given device is already mounted and where
10191# FIXME: resolve swap usage and device stacking
10192detect_mounted() {
10193 if test -e "$PROCSELFMOUNTINFO"; then
10194 detect_mounted_with_proc_self_mountinfo
10195 elif test -e "$PROCMOUNTS"; then
10196 detect_mounted_with_proc_mounts
10197 else
10198 error "Cannot detect mounted device \"$VOLUME\""
10199 fi
10200}
10201
10202# get the full size of device in bytes
10203detect_device_size() {
10204 # check if blockdev supports getsize64
10205 "$BLOCKDEV" 2>&1 | "$GREP" getsize64 >"$NULL"
10206 if test $? -eq 0; then
10207 DEVSIZE=$("$BLOCKDEV" --getsize64 "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
10208 else
10209 DEVSIZE=$("$BLOCKDEV" --getsize "$VOLUME") || error "Cannot read size of device \"$VOLUME\""
10210 SSSIZE=$("$BLOCKDEV" --getss "$VOLUME") || error "Cannot block size read device \"$VOLUME\""
10211 DEVSIZE=$(($DEVSIZE * $SSSIZE))
10212 fi
10213}
10214
10215# round up $1 / $2
10216# could be needed to gaurantee 'at least given size'
10217# but it makes many troubles
10218round_up_block_size() {
10219 echo $(( ($1 + $2 - 1) / $2 ))
10220}
10221
10222temp_mount() {
10223 dry "$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR"
10224 dry "$MOUNT" "$VOLUME" "$TEMPDIR" || error "Failed to mount $TEMPDIR"
10225}
10226
10227temp_umount() {
10228 dry "$UMOUNT" "$TEMPDIR" || error "Failed to umount \"$TEMPDIR\""
10229 dry "$RMDIR" "${TEMPDIR}" || error "Failed to remove \"$TEMPDIR\""
10230 dry "$RMDIR" "${TEMPDIR%%m}" || error "Failed to remove \"${TEMPDIR%%m}\""
10231}
10232
10233yes_no() {
10234 echo -n "$@? [Y|n] "
10235
10236 if [ -n "$YES" ]; then
10237 echo y ; return 0
10238 fi
10239
10240 while read -r -s -n 1 ANS ; do
10241 case "$ANS" in
10242 "y" | "Y" | "") echo y ; return 0 ;;
10243 "n" | "N") echo n ; return 1 ;;
10244 esac
10245 done
10246}
10247
10248try_umount() {
10249 yes_no "Do you want to unmount \"$MOUNTED\"" && dry "$UMOUNT" "$MOUNTED" && return 0
10250 error "Cannot proceed with mounted filesystem \"$MOUNTED\""
10251}
10252
10253validate_parsing() {
10254 test -n "$BLOCKSIZE" && test -n "$BLOCKCOUNT" || error "Cannot parse $1 output"
10255}
10256####################################
10257# Resize ext2/ext3/ext4 filesystem
10258# - unmounted or mounted for upsize
10259# - unmounted for downsize
10260####################################
10261resize_ext() {
10262 verbose "Parsing $TUNE_EXT -l \"$VOLUME\""
10263 for i in $(LC_ALL=C "$TUNE_EXT" -l "$VOLUME"); do
10264 case "$i" in
10265 "Block size"*) BLOCKSIZE=${i##* } ;;
10266 "Block count"*) BLOCKCOUNT=${i##* } ;;
10267 esac
10268 done
10269 validate_parsing "$TUNE_EXT"
10270 decode_size $1 $BLOCKSIZE
10271 FSFORCE=$FORCE
10272
10273 if [ "$NEWBLOCKCOUNT" -lt "$BLOCKCOUNT" -o "$EXTOFF" -eq 1 ]; then
10274 detect_mounted && verbose "$RESIZE_EXT needs unmounted filesystem" && try_umount
10275 REMOUNT=$MOUNTED
10276 if test -n "$MOUNTED" ; then
10277 # Forced fsck -f for umounted extX filesystem.
10278 case "$-" in
10279 *i*) dry "$FSCK" $YES -f "$VOLUME" ;;
10280 *) dry "$FSCK" -f -p "$VOLUME" ;;
10281 esac
10282 fi
10283 fi
10284
10285 verbose "Resizing filesystem on device \"$VOLUME\" to $NEWSIZE bytes ($BLOCKCOUNT -> $NEWBLOCKCOUNT blocks of $BLOCKSIZE bytes)"
10286 dry "$RESIZE_EXT" $FSFORCE "$VOLUME" $NEWBLOCKCOUNT
10287}
10288
10289#############################
10290# Resize reiserfs filesystem
10291# - unmounted for upsize
10292# - unmounted for downsize
10293#############################
10294resize_reiser() {
10295 detect_mounted && verbose "ReiserFS resizes only unmounted filesystem" && try_umount
10296 REMOUNT=$MOUNTED
10297 verbose "Parsing $TUNE_REISER \"$VOLUME\""
10298 for i in $(LC_ALL=C "$TUNE_REISER" "$VOLUME"); do
10299 case "$i" in
10300 "Blocksize"*) BLOCKSIZE=${i##*: } ;;
10301 "Count of blocks"*) BLOCKCOUNT=${i##*: } ;;
10302 esac
10303 done
10304 validate_parsing "$TUNE_REISER"
10305 decode_size $1 $BLOCKSIZE
10306 verbose "Resizing \"$VOLUME\" $BLOCKCOUNT -> $NEWBLOCKCOUNT blocks ($NEWSIZE bytes, bs: $NEWBLOCKCOUNT)"
10307 if [ -n "$YES" ]; then
10308 echo y | dry "$RESIZE_REISER" -s $NEWSIZE "$VOLUME"
10309 else
10310 dry "$RESIZE_REISER" -s $NEWSIZE "$VOLUME"
10311 fi
10312}
10313
10314########################
10315# Resize XFS filesystem
10316# - mounted for upsize
10317# - cannot downsize
10318########################
10319resize_xfs() {
10320 detect_mounted
10321 MOUNTPOINT=$MOUNTED
10322 if [ -z "$MOUNTED" ]; then
10323 MOUNTPOINT=$TEMPDIR
10324 temp_mount || error "Cannot mount Xfs filesystem"
10325 fi
10326 verbose "Parsing $TUNE_XFS \"$MOUNTPOINT\""
10327 for i in $(LC_ALL=C "$TUNE_XFS" "$MOUNTPOINT"); do
10328 case "$i" in
10329 "data"*) BLOCKSIZE=${i##*bsize=} ; BLOCKCOUNT=${i##*blocks=} ;;
10330 esac
10331 done
10332 BLOCKSIZE=${BLOCKSIZE%%[^0-9]*}
10333 BLOCKCOUNT=${BLOCKCOUNT%%[^0-9]*}
10334 validate_parsing "$TUNE_XFS"
10335 decode_size $1 $BLOCKSIZE
10336 if [ $NEWBLOCKCOUNT -gt $BLOCKCOUNT ]; then
10337 verbose "Resizing Xfs mounted on \"$MOUNTPOINT\" to fill device \"$VOLUME\""
10338 dry "$RESIZE_XFS" $MOUNTPOINT
10339 elif [ $NEWBLOCKCOUNT -eq $BLOCKCOUNT ]; then
10340 verbose "Xfs filesystem already has the right size"
10341 else
10342 error "Xfs filesystem shrinking is unsupported"
10343 fi
10344}
10345
10346####################
10347# Resize filesystem
10348####################
10349resize() {
10350 NEWSIZE=$2
10351 detect_fs "$1"
10352 detect_device_size
10353 verbose "Device \"$VOLUME\" size is $DEVSIZE bytes"
10354 # if the size parameter is missing use device size
10355 #if [ -n "$NEWSIZE" -a $NEWSIZE <
10356 test -z "$NEWSIZE" && NEWSIZE=${DEVSIZE}b
10357 IFS=$NL
10358 case "$FSTYPE" in
10359 "ext3"|"ext2"|"ext4") resize_ext $NEWSIZE ;;
10360 "reiserfs") resize_reiser $NEWSIZE ;;
10361 "xfs") resize_xfs $NEWSIZE ;;
10362 *) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool" ;;
10363 esac || error "Resize $FSTYPE failed"
10364 cleanup 0
10365}
10366
10367####################################
10368# Calclulate diff between two dates
10369# LC_ALL=C input is expected the
10370# only one supported
10371####################################
10372diff_dates() {
10373 echo $(( $("$DATE" -u -d"$1" +%s 2>"$NULL") - $("$DATE" -u -d"$2" +%s 2>"$NULL") ))
10374}
10375
10376###################
10377# Check filesystem
10378###################
10379check() {
10380 detect_fs "$1"
10381 if detect_mounted ; then
10382 verbose "Skipping filesystem check for device \"$VOLUME\" as the filesystem is mounted on $MOUNTED";
10383 cleanup 3
10384 fi
10385
10386 case "$FSTYPE" in
10387 "ext2"|"ext3"|"ext4")
10388 IFS_CHECK=$IFS
10389 IFS=$NL
10390 for i in $(LC_ALL=C "$TUNE_EXT" -l "$VOLUME"); do
10391 case "$i" in
10392 "Last mount"*) LASTMOUNT=${i##*: } ;;
10393 "Last checked"*) LASTCHECKED=${i##*: } ;;
10394 esac
10395 done
10396 case "$LASTMOUNT" in
10397 *"n/a") ;; # nothing to do - system was not mounted yet
10398 *)
10399 LASTDIFF=$(diff_dates $LASTMOUNT $LASTCHECKED)
10400 if test "$LASTDIFF" -gt 0 ; then
10401 verbose "Filesystem has not been checked after the last mount, using fsck -f"
10402 FORCE="-f"
10403 fi
10404 ;;
10405 esac
10406 IFS=$IFS_CHECK
10407 esac
10408
10409 case "$FSTYPE" in
10410 "xfs") if which "$XFS_CHECK" >"$NULL" 2>&1 ; then
10411 dry "$XFS_CHECK" "$VOLUME"
10412 else
10413 # Replacement for outdated xfs_check
10414 # FIXME: for small devices we need to force_geometry,
10415 # since we run in '-n' mode, it shouldn't be problem.
10416 # Think about better way....
10417 dry "$XFS_REPAIR" -n -o force_geometry "$VOLUME"
10418 fi ;;
10419 *) # check if executed from interactive shell environment
10420 case "$-" in
10421 *i*) dry "$FSCK" $YES $FORCE "$VOLUME" ;;
10422 *) dry "$FSCK" $FORCE -p "$VOLUME" ;;
10423 esac
10424 esac
10425}
10426
10427#############################
10428# start point of this script
10429# - parsing parameters
10430#############################
10431trap "cleanup 2" 2
10432
10433# test if we are not invoked recursively
10434test -n "$FSADM_RUNNING" && exit 0
10435
10436# test some prerequisities
10437for i in "$TUNE_EXT" "$RESIZE_EXT" "$TUNE_REISER" "$RESIZE_REISER" \
10438 "$TUNE_XFS" "$RESIZE_XFS" "$MOUNT" "$UMOUNT" "$MKDIR" \
10439 "$RMDIR" "$BLOCKDEV" "$BLKID" "$GREP" "$READLINK" \
10440 "$DATE" "$FSCK" "$XFS_CHECK" "$XFS_REPAIR" "$LVM" ; do
10441 test -n "$i" || error "Required command definitions in the script are missing!"
10442done
10443
10444"$LVM" version >"$NULL" 2>&1 || error "Could not run lvm binary \"$LVM\""
10445$("$READLINK" -e / >"$NULL" 2>&1) || READLINK_E="-f"
10446TEST64BIT=$(( 1000 * 1000000000000 ))
10447test "$TEST64BIT" -eq 1000000000000000 || error "Shell does not handle 64bit arithmetic"
10448$(echo Y | "$GREP" Y >"$NULL") || error "Grep does not work properly"
10449test $("$DATE" -u -d"Jan 01 00:00:01 1970" +%s) -eq 1 || error "Date translation does not work"
10450
10451
10452if [ "$#" -eq 0 ] ; then
10453 tool_usage
10454fi
10455
10456while [ "$#" -ne 0 ]
10457do
10458 case "$1" in
10459 "") ;;
10460 "-h"|"--help") tool_usage ;;
10461 "-v"|"--verbose") VERB="-v" ;;
10462 "-n"|"--dry-run") DRY=1 ;;
10463 "-f"|"--force") FORCE="-f" ;;
10464 "-e"|"--ext-offline") EXTOFF=1 ;;
10465 "-y"|"--yes") YES="-y" ;;
10466 "-l"|"--lvresize") DO_LVRESIZE=1 ;;
10467 "check") CHECK="$2" ; shift ;;
10468 "resize") RESIZE="$2"; NEWSIZE="$3" ; shift 2 ;;
10469 *) error "Wrong argument \"$1\". (see: $TOOL --help)"
10470 esac
10471 shift
10472done
10473
10474test "$YES" = "-y" || YES=
10475test "$EXTOFF" -eq 1 || EXTOFF=0
10476
10477if [ -n "$CHECK" ]; then
10478 check "$CHECK"
10479elif [ -n "$RESIZE" ]; then
10480 export FSADM_RUNNING="fsadm"
10481 resize "$RESIZE" "$NEWSIZE"
10482else
10483 error "Missing command. (see: $TOOL --help)"
10484fi
10485\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/cmirrord_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000002617\013062740170\0023431\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
10486#
10487# chkconfig: - 22 78
10488# description: Starts and stops cmirrord
10489# pidfile: @CMIRRORD_PIDFILE@
10490#
10491# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
10492#
10493### BEGIN INIT INFO
10494# Provides: cmirrord
10495# Required-Start: $network $time $local_fs
10496# Required-Stop: $network $time $local_fs
10497# Short-Description: Starts and stops cmirrord
10498# Description: Starts and stops the cluster mirror log daemon
10499### END INIT INFO
10500
10501. /etc/init.d/functions
10502
10503DAEMON=cmirrord
10504
10505LOCK_FILE="/var/lock/subsys/$DAEMON"
10506
10507start()
10508{
10509 rtrn=0
10510 if ! pidof $DAEMON > /dev/null
10511 then
10512 echo -n "Starting $DAEMON: "
10513 daemon $DAEMON
10514 rtrn=$?
10515 echo
10516 fi
10517
10518 return $rtrn
10519}
10520
10521stop()
10522{
10523 echo -n "Stopping $DAEMON:"
10524 killproc $DAEMON -TERM
10525 rtrn=$?
10526 echo
10527
10528 return $rtrn
10529}
10530
10531wait_for_finish()
10532{
10533 count=0
10534
10535 while [ "$count" -le 10 -a -n "`pidof $DAEMON`" ]
10536 do
10537 sleep 1
10538 count=$((count + 1))
10539 done
10540
10541 if [ `pidof $DAEMON` ]
10542 then
10543 return 1
10544 else
10545 return 0
10546 fi
10547}
10548
10549cmirror_status()
10550{
10551 status $DAEMON
10552}
10553
10554rtrn=1
10555
10556# See how we were called.
10557case "$1" in
10558 start)
10559 start
10560 rtrn=$?
10561 [ $rtrn = 0 ] && touch $LOCK_FILE
10562 ;;
10563
10564 stop)
10565 stop
10566 rtrn=$?
10567 [ $rtrn = 0 ] && rm -f $LOCK_FILE
10568 ;;
10569
10570 restart)
10571 if stop
10572 then
10573 wait_for_finish
10574 start
10575 fi
10576 rtrn=$?
10577 ;;
10578
10579 status)
10580 cmirror_status
10581 rtrn=$?
10582 if [ $rtrn -eq 0 ]; then
10583 echo "cmirror is running."
10584 fi
10585 ;;
10586
10587 *)
10588 echo $"Usage: $0 {start|stop|restart|status}"
10589 ;;
10590esac
10591
10592exit $rtrn
10593\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_monitoring_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001232\013062740170\0027106\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
10594Description=Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
10595Documentation=man:dmeventd(8) man:lvcreate(8) man:lvchange(8) man:vgchange(8)
10596Requires=dm-event.socket lvm2-lvmetad.socket
10597After=dm-event.socket dm-event.service lvm2-lvmetad.socket lvm2-activation.service lvm2-lvmetad.service
10598Before=local-fs-pre.target
10599DefaultDependencies=no
10600Conflicts=shutdown.target
10601
10602[Service]
10603Type=oneshot
10604Environment=LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1
10605ExecStart=@sbindir@/lvm vgchange --monitor y --ignoreskippedcluster
10606ExecStop=@sbindir@/lvm vgchange --monitor n --ignoreskippedcluster
10607RemainAfterExit=yes
10608
10609[Install]
10610WantedBy=sysinit.target
10611\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_monitoring_init_rhel4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004077\013062740170\0023737\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
10612#
10613# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
10614#
10615# This copyrighted material is made available to anyone wishing to use,
10616# modify, copy, or redistribute it subject to the terms and conditions
10617# of the GNU General Public License v.2.
10618#
10619# You should have received a copy of the GNU General Public License
10620# along with this program; if not, write to the Free Software Foundation,
10621# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
10622#
10623# This file is part of LVM2.
10624# It is required for the proper handling of failures of LVM2 mirror
10625# devices that were created using the -m option of lvcreate.
10626#
10627#
10628# chkconfig: 12345 02 99
10629# description: Starts and stops dmeventd monitoring for lvm2
10630#
10631### BEGIN INIT INFO
10632# Provides:
10633### END INIT INFO
10634
10635. /etc/init.d/functions
10636
10637VGCHANGE="/usr/sbin/vgchange"
10638WARN=1
10639
10640start()
10641{
10642 ret=0
10643 # TODO do we want to separate out already active groups only?
10644 VGS=`vgs --noheadings -o name --config 'log{command_names=0 prefix=" "}' 2> /dev/null`
10645 for vg in $VGS
10646 do
10647 action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y --config 'log{command_names=0 prefix=" "}' $vg || ret=$?
10648 done
10649
10650 return $ret
10651}
10652
10653
10654stop()
10655{
10656 ret=0
10657 # TODO do we want to separate out already active groups only?
10658 if test "$WARN" = "1"; then
10659 echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
10660 return 1
10661 fi
10662 VGS=`vgs --noheadings -o name --config 'log{command_names=0 prefix=" "}' 2> /dev/null`
10663 for vg in $VGS
10664 do
10665 action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n --config 'log{command_names=0 prefix=" "}' $vg || ret=$?
10666 done
10667 return $ret
10668}
10669
10670result=1
10671
10672# See how we were called.
10673case "$1" in
10674 start)
10675 start
10676 result=$?
10677 ;;
10678
10679 force-stop)
10680 WARN=0
10681 stop
10682 result=$?
10683 ;;
10684
10685 stop)
10686 test "$runlevel" = "0" && WARN=0
10687 test "$runlevel" = "6" && WARN=0
10688 stop
10689 result=$?
10690 ;;
10691
10692 restart)
10693 WARN=0
10694 if stop
10695 then
10696 start
10697 fi
10698 result=$?
10699 ;;
10700
10701 status)
10702 # TODO anyone with an idea how to dump monitored volumes?
10703 ;;
10704
10705 *)
10706 echo $"Usage: $0 {start|stop|restart|status|force-stop}"
10707 ;;
10708esac
10709
10710exit $result
10711\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvmconf.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000030623\013062740170\0020542\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
10712#
10713# Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
10714#
10715# This file is part of the lvm2 package.
10716#
10717# This copyrighted material is made available to anyone wishing to use,
10718# modify, copy, or redistribute it subject to the terms and conditions
10719# of the GNU General Public License v.2.
10720#
10721# You should have received a copy of the GNU General Public License
10722# along with this program; if not, write to the Free Software Foundation,
10723# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
10724
10725#
10726# Edit an lvm.conf file to adjust various properties
10727#
10728
10729# cluster with clvmd and/or locking lib?
10730HANDLE_CLUSTER=0
10731
10732# cluster without clvmd?
10733HANDLE_HALVM=0
10734
10735# also enable services appropriately (lvmetad, clvmd)?
10736HANDLE_SERVICES=0
10737
10738# also enable cmirrord service in addition?
10739HANDLE_MIRROR_SERVICE=0
10740
10741# also start/start services in addition to enabling/disabling them?
10742START_STOP_SERVICES=0
10743
10744function usage
10745{
10746 echo "Usage: $0 <command>"
10747 echo ""
10748 echo "Commands:"
10749 echo "Enable clvm: --enable-cluster [--lockinglibdir <dir>] [--lockinglib <lib>]"
10750 echo "Disable clvm: --disable-cluster"
10751 echo "Enable halvm: --enable-halvm"
10752 echo "Disable halvm: --disable-halvm"
10753 echo "Set locking library: --lockinglibdir <dir> [--lockinglib <lib>]"
10754 echo ""
10755 echo "Global options:"
10756 echo "Config file location: --file <configfile>"
10757 echo "Set services: --services [--mirrorservice] [--startstopservices]"
10758 echo ""
10759 echo "Use the separate command 'lvmconfig' to display configuration information"
10760}
10761
10762function set_default_use_lvmetad_var
10763{
10764 eval $(lvm dumpconfig --type default global/use_lvmetad 2>/dev/null)
10765 if [ "$?" != "0" ]; then
10766 USE_LVMETAD=0
10767 else
10768 USE_LVMETAD=$use_lvmetad
10769 fi
10770}
10771
10772function parse_args
10773{
10774 while [ -n "$1" ]; do
10775 case $1 in
10776 --enable-cluster)
10777 LOCKING_TYPE=3
10778 USE_LVMETAD=0
10779 HANDLE_CLUSTER=1
10780 shift
10781 ;;
10782 --disable-cluster)
10783 LOCKING_TYPE=1
10784 set_default_use_lvmetad_var
10785 HANDLE_CLUSTER=1
10786 shift
10787 ;;
10788 --enable-halvm)
10789 LOCKING_TYPE=1
10790 USE_LVMETAD=0
10791 HANDLE_HALVM=1
10792 shift
10793 ;;
10794 --disable-halvm)
10795 LOCKING_TYPE=1
10796 set_default_use_lvmetad_var
10797 HANDLE_HALVM=1
10798 shift
10799 ;;
10800 --lockinglibdir)
10801 if [ -n "$2" ]; then
10802 LOCKINGLIBDIR=$2
10803 shift 2
10804 else
10805 usage
10806 exit 1
10807 fi
10808 HANDLE_CLUSTER=1
10809 ;;
10810 --lockinglib)
10811 if [ -n "$2" ]; then
10812 LOCKINGLIB=$2
10813 shift 2
10814 else
10815 usage
10816 exit 1
10817 fi
10818 HANDLE_CLUSTER=1
10819 ;;
10820 --file)
10821 if [ -n "$2" ]; then
10822 CONFIGFILE=$2
10823 shift 2
10824 else
10825 usage
10826 exit 1
10827 fi
10828 ;;
10829 --services)
10830 HANDLE_SERVICES=1
10831 shift
10832 ;;
10833 --mirrorservice)
10834 HANDLE_MIRROR_SERVICE=1
10835 shift
10836 ;;
10837 --startstopservices)
10838 START_STOP_SERVICES=1
10839 shift
10840 ;;
10841 *)
10842 usage
10843 exit 1
10844 esac
10845 done
10846
10847 if [ "$LOCKINGLIBDIR" -o "$LOCKINGLIB" ]; then
10848 LOCKING_TYPE=2
10849 USE_LVMETAD=0
10850 fi
10851}
10852
10853function validate_args
10854{
10855 [ -z "$CONFIGFILE" ] && CONFIGFILE="/etc/lvm/lvm.conf"
10856
10857 if [ ! -f "$CONFIGFILE" ]
10858 then
10859 echo "$CONFIGFILE does not exist"
10860 exit 10
10861 fi
10862
10863 if [ "$HANDLE_CLUSTER" = "1" -a "$HANDLE_HALVM" = "1" ]; then
10864 echo "Either HA LVM or cluster method may be used at one time"
10865 exit 18
10866 fi
10867
10868 if [ "$HANDLE_SERVICES" = "0" ]; then
10869 if [ "$HANDLE_MIRROR_SERVICE" = "1" ]; then
10870 echo "--mirrorservice may be used only with --services"
10871 exit 19
10872 fi
10873 if [ "$START_STOP_SERVICES" = "1" ]; then
10874 echo "--startstopservices may be used only with --services"
10875 exit 19
10876 fi
10877 fi
10878
10879 if [ -z "$LOCKING_TYPE" ] && [ -z "$LOCKINGLIBDIR" ]; then
10880 usage
10881 exit 1
10882 fi
10883
10884 if [ -n "$LOCKINGLIBDIR" ]; then
10885
10886 if [ "${LOCKINGLIBDIR:0:1}" != "/" ]
10887 then
10888 echo "Prefix must be an absolute path name (starting with a /)"
10889 exit 12
10890 fi
10891
10892 if [ -n "$LOCKINGLIB" ] && [ ! -f "$LOCKINGLIBDIR/$LOCKINGLIB" ]
10893 then
10894 echo "$LOCKINGLIBDIR/$LOCKINGLIB does not exist, did you do a \"make install\" ?"
10895 exit 11
10896 fi
10897
10898 fi
10899
10900 if [ "$LOCKING_TYPE" = "1" ] && [ -n "$LOCKINGLIBDIR" -o -n "$LOCKINGLIB" ]; then
10901 echo "Superfluous locking lib parameter, ignoring"
10902 fi
10903}
10904
10905umask 0077
10906
10907parse_args "$@"
10908
10909validate_args
10910
10911
10912SCRIPTFILE=/etc/lvm/.lvmconf-script.tmp
10913TMPFILE=/etc/lvm/.lvmconf-tmp.tmp
10914
10915
10916# Flags so we know which parts of the file we can replace and which need
10917# adding. These are return codes from grep, so zero means it IS present!
10918have_type=1
10919have_dir=1
10920have_library=1
10921have_use_lvmetad=1
10922have_global=1
10923
10924grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $CONFIGFILE
10925have_type=$?
10926
10927grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $CONFIGFILE
10928have_dir=$?
10929
10930grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $CONFIGFILE
10931have_library=$?
10932
10933grep -q '^[[:blank:]]*use_lvmetad[[:blank:]]*=' $CONFIGFILE
10934have_use_lvmetad=$?
10935
10936# Those options are in section "global {" so we must have one if any are present.
10937if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" -o "$have_use_lvmetad" = "0" ]
10938then
10939
10940 # See if we can find it...
10941 grep -q '^[[:blank:]]*global[[:blank:]]*{' $CONFIGFILE
10942 have_global=$?
10943
10944 if [ "$have_global" = "1" ]
10945 then
10946 echo "global keys but no 'global {' found, can't edit file"
10947 exit 13
10948 fi
10949fi
10950
10951if [ "$LOCKING_TYPE" = "2" ] && [ -z "$LOCKINGLIBDIR" ] && [ "$have_dir" = "1" ]; then
10952 echo "no library_dir specified in $CONFIGFILE"
10953 exit 16
10954fi
10955
10956# So if we don't have "global {" we need to create one and
10957# populate it
10958
10959if [ "$have_global" = "1" ]
10960then
10961 if [ -z "$LOCKING_TYPE" ]; then
10962 LOCKING_TYPE=1
10963 fi
10964 if [ "$LOCKING_TYPE" = "3" ] || [ "$LOCKING_TYPE" = "2" ]; then
10965 cat $CONFIGFILE - <<EOF > $TMPFILE
10966global {
10967 # Enable locking for cluster LVM
10968 locking_type = $LOCKING_TYPE
10969 library_dir = "$LOCKINGLIBDIR"
10970 # Disable lvmetad in cluster
10971 use_lvmetad = 0
10972EOF
10973 if [ $? != 0 ]
10974 then
10975 echo "failed to create temporary config file, $CONFIGFILE not updated"
10976 exit 14
10977 fi
10978 if [ -n "$LOCKINGLIB" ]; then
10979 cat - <<EOF >> $TMPFILE
10980 locking_library = "$LOCKINGLIB"
10981EOF
10982 if [ $? != 0 ]
10983 then
10984 echo "failed to create temporary config file, $CONFIGFILE not updated"
10985 exit 16
10986 fi
10987 fi
10988 cat - <<EOF >> $TMPFILE
10989}
10990EOF
10991 fi # if we aren't setting cluster locking, we don't need to create a global section
10992
10993 if [ $? != 0 ]
10994 then
10995 echo "failed to create temporary config file, $CONFIGFILE not updated"
10996 exit 17
10997 fi
10998else
10999 #
11000 # We have a "global {" section, so add or replace the
11001 # locking entries as appropriate
11002 #
11003
11004 if [ -n "$LOCKING_TYPE" ]; then
11005 if [ "$have_type" = "0" ]
11006 then
11007 SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
11008 else
11009 SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
11010 fi
11011 fi
11012
11013 if [ -n "$LOCKINGLIBDIR" ]; then
11014 if [ "$have_dir" = "0" ]
11015 then
11016 SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$LOCKINGLIBDIR\"'g"
11017 else
11018 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$LOCKINGLIBDIR\""
11019 fi
11020 fi
11021
11022 if [ -n "$LOCKINGLIB" ]; then
11023 if [ "$have_library" = "0" ]
11024 then
11025 SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LOCKINGLIB\"/g"
11026 else
11027 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LOCKINGLIB\""
11028 fi
11029 fi
11030
11031 if [ "$have_use_lvmetad" = "0" ]
11032 then
11033 SEDCMD="${SEDCMD}\ns'^[[:blank:]]*use_lvmetad[[:blank:]]*=.*'\ \ \ \ use_lvmetad = $USE_LVMETAD'g"
11034 else
11035 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ use_lvmetad = $USE_LVMETAD"
11036 fi
11037
11038 echo -e $SEDCMD > $SCRIPTFILE
11039 sed <$CONFIGFILE >$TMPFILE -f $SCRIPTFILE
11040 if [ $? != 0 ]
11041 then
11042 echo "sed failed, $CONFIGFILE not updated"
11043 exit 15
11044 fi
11045fi
11046
11047# Now we have a suitably editted config file in a temp place,
11048# backup the original and copy our new one into place.
11049
11050cp $CONFIGFILE $CONFIGFILE.lvmconfold
11051if [ $? != 0 ]
11052 then
11053 echo "failed to backup old config file, $CONFIGFILE not updated"
11054 exit 2
11055fi
11056
11057cp $TMPFILE $CONFIGFILE
11058if [ $? != 0 ]
11059 then
11060 echo "failed to copy new config file into place, check $CONFIGFILE is still OK"
11061 exit 3
11062fi
11063
11064rm -f $SCRIPTFILE $TMPFILE
11065
11066function set_service {
11067 local type="$1"
11068 local action="$2"
11069 shift 2
11070
11071 if [ "$type" = "systemd" ]; then
11072 if [ "$action" = "activate" ]; then
11073 for i in $@; do
11074 eval $($SYSTEMCTL_BIN show $i -p LoadState)
11075 test "$LoadState" = "loaded" || continue
11076 $SYSTEMCTL_BIN enable $i
11077 if [ "$START_STOP_SERVICES" = "1" ]; then
11078 $SYSTEMCTL_BIN start $i
11079 fi
11080 done
11081 elif [ "$action" = "deactivate" ]; then
11082 for i in $@; do
11083 eval $($SYSTEMCTL_BIN show $i -p LoadState)
11084 test "$LoadState" = "loaded" || continue
11085 $SYSTEMCTL_BIN disable $i
11086 if [ "$START_STOP_SERVICES" = "1" ]; then
11087 $SYSTEMCTL_BIN stop $i
11088 fi
11089 done
11090 fi
11091 elif [ "$type" = "sysv" ]; then
11092 if [ "$action" = "activate" ]; then
11093 for i in $@; do
11094 $CHKCONFIG_BIN --list $i > /dev/null || continue
11095 $CHKCONFIG_BIN $i on
11096 if [ "$START_STOP_SERVICES" = "1" ]; then
11097 $SERVICE_BIN $i start
11098 fi
11099 done
11100 elif [ "$action" = "deactivate" ]; then
11101 for i in $@; do
11102 $CHKCONFIG_BIN --list $i > /dev/null || continue
11103 if [ "$START_STOP_SERVICES" = "1" ]; then
11104 $SERVICE_BIN $i stop
11105 fi
11106 $CHKCONFIG_BIN $i off
11107 done
11108 fi
11109 fi
11110}
11111
11112# Start/stop and enable/disable services if needed.
11113
11114if [ "$HANDLE_SERVICES" == "1" ]; then
11115
11116 SYSTEMCTL_BIN=$(which systemctl 2>/dev/null)
11117 CHKCONFIG_BIN=$(which chkconfig 2>/dev/null)
11118 SERVICE_BIN=$(which service 2>/dev/null)
11119
11120 # Systemd services
11121 if [ -n "$SYSTEMCTL_BIN" ]; then
11122 if [ "$USE_LVMETAD" = "0" ]; then
11123 set_service systemd deactivate lvm2-lvmetad.service lvm2-lvmetad.socket
11124 else
11125 set_service systemd activate lvm2-lvmetad.socket
11126 fi
11127
11128 if [ "$LOCKING_TYPE" = "3" ]; then
11129 set_service systemd activate lvm2-cluster-activation.service
11130 if [ "$HANDLE_MIRROR_SERVICE" = "1" ]; then
11131 set_service activate lvm2-cmirrord.service
11132 fi
11133 else
11134 set_service systemd deactivate lvm2-cluster-activation.service
11135 if [ "$HANDLE_MIRROR_SERVICE" = "1" ]; then
11136 set_service systemd deactivate lvm2-cmirrord.service
11137 fi
11138 fi
11139
11140 # System V init scripts
11141 elif [ -n "$SERVICE_BIN" -a -n "$CHKCONFIG_BIN" ]; then
11142 if [ "$USE_LVMETAD" = "0" ]; then
11143 set_service sysv deactivate lvm2-lvmetad
11144 else
11145 set_service sysv activate lvm2-lvmetad
11146 fi
11147
11148 if [ "$LOCKING_TYPE" = "3" ]; then
11149 set_service sysv activate clvmd
11150 if [ "$HANDLE_MIRROR_SERVICE" = "1" ]; then
11151 set_service sysv activate cmirrord
11152 fi
11153 else
11154 set_service sysv deactivate clvmd
11155 if [ "$HANDLE_MIRROR_SERVICE" = "1" ]; then
11156 set_service sysv deactivate cmirrord
11157 fi
11158 fi
11159
11160 # None of the service tools found, error out
11161 else
11162 echo "Missing tools to handle services"
11163 exit 20
11164 fi
11165fi
11166\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_tmpfiles_red_hat.conf.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000113\013062740170\0024256\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d @DEFAULT_LOCK_DIR@ 0700 root root -
11167d @DEFAULT_RUN_DIR@ 0700 root root -
11168\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/vgimportclone.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000022633\013062740170\0021773\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
11169
11170# Copyright (C) 2009 Chris Procter All rights reserved.
11171# Copyright (C) 2009-2015 Red Hat, Inc. All rights reserved.
11172#
11173# This file is part of LVM2.
11174#
11175# This copyrighted material is made available to anyone wishing to use,
11176# modify, copy, or redistribute it subject to the terms and conditions
11177# of the GNU General Public License v.2.
11178#
11179# You should have received a copy of the GNU General Public License
11180# along with this program; if not, write to the Free Software Foundation,
11181# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
11182#
11183# vgimportclone: This script is used to rename the VG and change the associated
11184# VG and PV UUIDs (primary application being HW snapshot restore)
11185
11186# following external commands are used throughout the script
11187# echo and test are internal in bash at least
11188RM=rm
11189BASENAME=basename
11190MKTEMP=mktemp
11191READLINK=readlink
11192GETOPT=getopt
11193
11194# user may override lvm location by setting LVM_BINARY
11195LVM="${LVM_BINARY:-lvm}"
11196
11197die() {
11198 code=$1; shift
11199 echo "Fatal: $@" 1>&2
11200 exit $code
11201}
11202
11203"$LVM" version >& /dev/null || die 2 "Could not run lvm binary '$LVM'"
11204
11205
11206function getvgname {
11207### get a unique vg name
11208### $1 = list of exists VGs
11209### $2 = the name we want
11210 VGLIST=$1
11211 VG=$2
11212 NEWVG=$3
11213
11214 BNAME="${NEWVG:-${VG}}"
11215 NAME="${BNAME}"
11216 I=0
11217
11218 while [[ "${VGLIST}" =~ ":${NAME}:" ]]
11219 do
11220 I=$(($I+1))
11221 NAME="${BNAME}$I"
11222 done
11223 echo "${NAME}"
11224}
11225
11226
11227function checkvalue {
11228### check return value and error if non zero
11229 if [ $1 -ne 0 ]
11230 then
11231 die $1 "$2, error: $1"
11232 fi
11233}
11234
11235
11236function usage {
11237### display usage message
11238 echo "Usage: ${SCRIPTNAME} [options] PhysicalVolume [PhysicalVolume...]"
11239 echo " -n|--basevgname - Base name for the new volume group(s)"
11240 echo " -i|--import - Import any exported volume groups found"
11241 echo " -t|--test - Run in test mode"
11242 echo " --quiet - Suppress output"
11243 echo " -v|--verbose - Set verbose level"
11244 echo " -d|--debug - Set debug level"
11245 echo " --version - Display version information"
11246 echo " -h|--help - Display this help message"
11247 echo ""
11248 exit 1
11249}
11250
11251
11252function cleanup {
11253 #set to use old lvm.conf
11254 LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
11255
11256 if [ $KEEP_TMP_LVM_SYSTEM_DIR -eq 1 ]; then
11257 echo "${SCRIPTNAME}: LVM_SYSTEM_DIR (${TMP_LVM_SYSTEM_DIR}) must be cleaned up manually."
11258 else
11259 "$RM" -rf -- "${TMP_LVM_SYSTEM_DIR}"
11260 fi
11261}
11262
11263SCRIPTNAME=`"$BASENAME" $0`
11264
11265
11266if [ "$UID" != "0" -a "$EUID" != "0" ]
11267then
11268 die 3 "${SCRIPTNAME} must be run as root."
11269fi
11270
11271LVM_OPTS=""
11272TEST_OPT=""
11273DISKS=""
11274# for compatibility: using mktemp -t rather than --tmpdir
11275TMP_LVM_SYSTEM_DIR=`"$MKTEMP" -d -t snap.XXXXXXXX`
11276KEEP_TMP_LVM_SYSTEM_DIR=0
11277CHANGES_MADE=0
11278IMPORT=0
11279DEBUG=""
11280VERBOSE=""
11281VERBOSE_COUNT=0
11282DEVNO=0
11283
11284if [ -n "${LVM_SYSTEM_DIR}" ]; then
11285 export ORIG_LVM_SYS_DIR="${LVM_SYSTEM_DIR}"
11286fi
11287
11288trap cleanup 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
11289
11290#####################################################################
11291### Get and check arguments
11292#####################################################################
11293OPTIONS=`"$GETOPT" -o n:dhitv \
11294 -l basevgname:,debug,help,import,quiet,test,verbose,version \
11295 -n "${SCRIPTNAME}" -- "$@"`
11296[ $? -ne 0 ] && usage
11297eval set -- "$OPTIONS"
11298
11299while true
11300do
11301 case $1 in
11302 -n|--basevgname)
11303 NEWVG="$2"; shift; shift
11304 ;;
11305 -i|--import)
11306 IMPORT=1; shift
11307 ;;
11308 -t|--test)
11309 TEST_OPT="-t"
11310 shift
11311 ;;
11312 --quiet)
11313 LVM_OPTS="--quiet ${LVM_OPTS}"
11314 shift
11315 ;;
11316 -v|--verbose)
11317 let VERBOSE_COUNT=VERBOSE_COUNT+1
11318 if [ -z "$VERBOSE" ]
11319 then
11320 VERBOSE="-v"
11321 else
11322 VERBOSE="${VERBOSE}v"
11323 fi
11324 shift
11325 ;;
11326 -d|--debug)
11327 if [ -z "$DEBUG" ]
11328 then
11329 DEBUG="-d"
11330 set -x
11331 else
11332 DEBUG="${DEBUG}d"
11333 fi
11334 shift
11335 ;;
11336 --version)
11337 "$LVM" version
11338 shift
11339 exit 0
11340 ;;
11341 -h|--help)
11342 usage; shift
11343 ;;
11344 --)
11345 shift; break
11346 ;;
11347 *)
11348 usage
11349 ;;
11350 esac
11351done
11352
11353# turn on DEBUG (special case associated with -v use)
11354if [ -z "$DEBUG" -a $VERBOSE_COUNT -gt 3 ]; then
11355 DEBUG="-d"
11356 set -x
11357fi
11358
11359# setup LVM_OPTS
11360if [ -n "${DEBUG}" -o -n "${VERBOSE}" ]
11361then
11362 LVM_OPTS="${LVM_OPTS} ${DEBUG} ${VERBOSE}"
11363fi
11364
11365# process remaining arguments (which should be disks)
11366for ARG
11367do
11368 if [ -b "$ARG" ]
11369 then
11370 ln -s "$ARG" ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO}
11371 DISKS="${DISKS} ${TMP_LVM_SYSTEM_DIR}/vgimport${DEVNO}"
11372 DEVNO=$((${DEVNO}+1))
11373 else
11374 die 3 "$ARG is not a block device."
11375 fi
11376done
11377
11378### check we have suitable values for important variables
11379if [ -z "${DISKS}" ]
11380then
11381 usage
11382fi
11383
11384#####################################################################
11385### Get the existing state so we can use it later.
11386### The list of VG names is saved in this format:
11387### :vgname1:vgname2:...:vgnameN:
11388#####################################################################
11389
11390OLDVGS=":`"${LVM}" vgs ${LVM_OPTS} -o name --noheadings --rows --separator : --config 'log{prefix=""}'`:"
11391checkvalue $? "Current VG names could not be collected without errors"
11392
11393#####################################################################
11394### Prepare the temporary lvm environment
11395#####################################################################
11396
11397for BLOCK in ${DISKS}
11398do
11399 FILTER="\"a|^${BLOCK}$|\", ${FILTER}"
11400done
11401export FILTER="filter=[ ${FILTER} \"r|.*|\" ]"
11402
11403LVMCONF=${TMP_LVM_SYSTEM_DIR}/lvm.conf
11404
11405CMD_CONFIG_LINE="devices { \
11406 scan = [ \"${TMP_LVM_SYSTEM_DIR}\" ] \
11407 cache_dir = \"${TMP_LVM_SYSTEM_DIR}/cache\"
11408 global_filter = [ \"a|.*|\" ] \
11409 ${FILTER}
11410 } \
11411 global { \
11412 use_lvmetad = 0 \
11413 }"
11414
11415$LVM dumpconfig ${LVM_OPTS} --file ${LVMCONF} --mergedconfig --config "${CMD_CONFIG_LINE}"
11416
11417checkvalue $? "Failed to generate ${LVMCONF}"
11418# Only keep TMP_LVM_SYSTEM_DIR if it contains something worth keeping
11419[ -n "${DEBUG}" ] && KEEP_TMP_LVM_SYSTEM_DIR=1
11420
11421### set to use new lvm.conf
11422export LVM_SYSTEM_DIR=${TMP_LVM_SYSTEM_DIR}
11423
11424# Check if there are any PVs that don't belong to any VG
11425# or even if there are disks which are not PVs at all.
11426NOVGDEVLIST=`${LVM} pvs -a -o pv_name --select vg_name="" --noheadings`
11427checkvalue $? "Failed to collect information for PV check"
11428if [ -n "${NOVGDEVLIST}" ]; then
11429 FOLLOWLIST=""
11430 while read PVNAME; do
11431 FOLLOW=`$READLINK $PVNAME`
11432 FOLLOWLIST="$FOLLOWLIST $FOLLOW"
11433 done <<< "`echo "${NOVGDEVLIST}"`"
11434 die 8 "Specified devices don't belong to a VG:$FOLLOWLIST"
11435fi
11436
11437#####################################################################
11438### Rename the VG(s) and change the VG and PV UUIDs.
11439#####################################################################
11440VGLIST=`${LVM} vgs -o vg_name,vg_exported,vg_missing_pv_count --noheadings --binary`
11441checkvalue $? "Failed to collect VG information"
11442
11443while read VGNAME VGEXPORTED VGMISSINGPVCOUNT; do
11444 if [ $VGMISSINGPVCOUNT -gt 0 ]; then
11445 echo "Volume Group ${VGNAME} has unknown PV(s), skipping."
11446 echo "- Were all associated PV(s) supplied as arguments?"
11447 continue
11448 fi
11449
11450 if [ "$VGEXPORTED" = "1" ]; then
11451 if [ ${IMPORT} -eq 1 ]; then
11452 "$LVM" vgimport ${LVM_OPTS} ${TEST_OPT} "${VGNAME}"
11453 checkvalue $? "Volume Group ${VGNAME} could not be imported"
11454 else
11455 echo "Volume Group ${VGNAME} exported, skipping."
11456 continue
11457 fi
11458 fi
11459
11460 "$LVM" pvchange ${LVM_OPTS} ${TEST_OPT} --uuid --config 'global{activation=0}' --select "vg_name=${VGNAME}"
11461 checkvalue $? "Unable to change all PV uuids in VG ${VGNAME}"
11462
11463 NEWVGNAME=`getvgname "${OLDVGS}" "${VGNAME}" "${NEWVG}"`
11464
11465 "$LVM" vgchange ${LVM_OPTS} ${TEST_OPT} --uuid --config 'global{activation=0}' ${VGNAME}
11466 checkvalue $? "Unable to change VG uuid for ${VGNAME}"
11467
11468 ## if the name isn't going to get changed dont even try.
11469 if [ "${VGNAME}" != "${NEWVGNAME}" ]
11470 then
11471 "$LVM" vgrename ${LVM_OPTS} ${TEST_OPT} "${VGNAME}" "${NEWVGNAME}"
11472 checkvalue $? "Unable to rename ${VGNAME} to ${NEWVGNAME}"
11473 fi
11474
11475 CHANGES_MADE=1
11476done <<< "`echo "${VGLIST}"`"
11477
11478#####################################################################
11479### Restore the old environment
11480#####################################################################
11481### set to use old lvm.conf
11482if [ -z "${ORIG_LVM_SYS_DIR}" ]
11483then
11484 unset LVM_SYSTEM_DIR
11485else
11486 LVM_SYSTEM_DIR=${ORIG_LVM_SYS_DIR}
11487fi
11488
11489### update the device cache and make sure all
11490### the device nodes we need are straight
11491if [ ${CHANGES_MADE} -eq 1 ]
11492then
11493 # get global/use_lvmetad config and if set also notify lvmetad about changes
11494 # since we were running LVM commands above with use_lvmetad=0
11495 eval $(${LVM} dumpconfig ${LVM_OPTS} global/use_lvmetad)
11496 if [ "$use_lvmetad" = "1" ]
11497 then
11498 echo "Notifying lvmetad about changes since it was disabled temporarily."
11499 echo "(This resolves any WARNING message about restarting lvmetad that appears above.)"
11500 LVM_OPTS="${LVM_OPTS} --cache"
11501 fi
11502
11503 "$LVM" vgscan ${LVM_OPTS} --mknodes
11504fi
11505
11506exit 0
11507\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmlockd_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000422\013062740170\0026534\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
11508Description=LVM2 lock daemon
11509Documentation=man:lvmlockd(8)
11510After=lvm2-lvmetad.service
11511
11512[Service]
11513Type=simple
11514NonBlocking=true
11515ExecStart=@sbindir@/lvmlockd -f
11516Environment=SD_ACTIVATION=1
11517PIDFile=@LVMLOCKD_PIDFILE@
11518SendSIGKILL=no
11519
11520[Install]
11521WantedBy=multi-user.target
11522
11523\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/blk_availability_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002663\013062740170\0025110\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
11524#
11525# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
11526#
11527# This copyrighted material is made available to anyone wishing to use,
11528# modify, copy, or redistribute it subject to the terms and conditions
11529# of the GNU General Public License v.2.
11530#
11531# You should have received a copy of the GNU General Public License
11532# along with this program; if not, write to the Free Software Foundation,
11533# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
11534#
11535# This script is responsible for executing blkdeactivate at shutdown
11536# to properly unmount filesystems and deactivate device stacks containing
11537# device-mapper devices (including plain device-mapper devices, LVM2 and
11538# multipath devices) and MD devices.
11539#
11540# chkconfig: 12345 25 75
11541# description: Controls availability of block devices
11542#
11543# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
11544#
11545### BEGIN INIT INFO
11546# Provides: blk-availability
11547# Required-Start:
11548# Required-Stop:
11549# Default-Start: 1 2 3 4 5
11550# Default-Stop: 0 6
11551# Short-Description: Availability of block devices
11552### END INIT INFO
11553
11554. /etc/init.d/functions
11555
11556sbindir=@sbindir@
11557script=blkdeactivate
11558options="-u -l wholevg -m disablequeueing"
11559
11560LOCK_FILE="/var/lock/subsys/blk-availability"
11561
11562
11563rtrn=1
11564
11565case "$1" in
11566 start)
11567 touch $LOCK_FILE
11568 ;;
11569
11570 stop)
11571 action "Stopping block device availability:" $sbindir/$script $options
11572 rm -f $LOCK_FILE
11573 ;;
11574
11575 status)
11576 ;;
11577 *)
11578 echo $"Usage: $0 {start|stop|status}"
11579 ;;
11580esac
11581\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmlocking_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001254\013062740170\0027072\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
11582Description=Availability of lockspaces in lvmlockd
11583Documentation=man:lvmlockd(8)
11584After=lvm2-lvmlockd.service sanlock.service dlm.service
11585
11586[Service]
11587Type=oneshot
11588RemainAfterExit=yes
11589
11590# start lockspaces and wait for them to finish starting
11591ExecStart=@sbindir@/vgchange --lock-start --lock-opt autowait
11592
11593# auto activate LVs in the newly started lockd VGs
11594ExecStart=@sbindir@/vgchange -aay -S 'locktype=sanlock || locktype=dlm'
11595
11596# deactivate LVs in lockd VGs
11597ExecStop=@sbindir@/vgchange -an -S 'locktype=sanlock || locktype=dlm'
11598
11599# stop lockspaces and wait for them to finish stopping
11600ExecStop=@sbindir@/lvmlockctl --stop-lockspaces --wait 1
11601
11602[Install]
11603WantedBy=multi-user.target
11604
11605\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/clvmd_fix_conf.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007413\013062740170\0022057\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
11606#
11607# Edit an lvm.conf file to enable cluster locking.
11608#
11609# $1 is the directory where the locking library is installed.
11610# $2 (optional) is the config file
11611# $3 (optional) is the locking library name
11612#
11613#
11614PREFIX=$1
11615LVMCONF=$2
11616LIB=$3
11617
11618if [ -z "$PREFIX" ]
11619then
11620 echo "usage: $0 <prefix> [<config file>] [<library>]"
11621 echo ""
11622 echo "<prefix>|UNDO location of the cluster locking shared library. (no default)"
11623 echo " UNDO will reset the locking back to local"
11624 echo "<config file> name of the LVM config file (default: /etc/lvm/lvm.conf)"
11625 echo "<library> name of the shared library (default: liblvm2clusterlock.so)"
11626 echo ""
11627 exit 0
11628fi
11629
11630[ -z "$LVMCONF" ] && LVMCONF="/etc/lvm/lvm.conf"
11631[ -z "$LIB" ] && LIB="liblvm2clusterlock.so"
11632
11633if [ "$PREFIX" = "UNDO" ]
11634then
11635 locking_type="1"
11636else
11637 locking_type="2"
11638
11639 if [ "${PREFIX:0:1}" != "/" ]
11640 then
11641 echo "Prefix must be an absolute path name (starting with a /)"
11642 exit 12
11643 fi
11644
11645 if [ ! -f "$PREFIX/$LIB" ]
11646 then
11647 echo "$PREFIX/$LIB does not exist, did you do a \"make install\" ?"
11648 exit 11
11649 fi
11650fi
11651
11652if [ ! -f "$LVMCONF" ]
11653then
11654 echo "$LVMCONF does not exist"
11655 exit 10
11656fi
11657
11658
11659SCRIPTFILE=`mktemp -t lvmscript.XXXXXXXXXX`
11660TMPFILE=`mktemp -t lvmtmp.XXXXXXXXXX`
11661
11662
11663# Flags so we know which parts of the file we can replace and which need
11664# adding. These are return codes from grep, so zero means it IS present!
11665have_type=1
11666have_dir=1
11667have_library=1
11668have_global=1
11669
11670grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $LVMCONF
11671have_type=$?
11672
11673grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $LVMCONF
11674have_dir=$?
11675
11676grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $LVMCONF
11677have_library=$?
11678
11679# Those options are in section "global {" so we must have one if any are present.
11680if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" ]
11681then
11682
11683 # See if we can find it...
11684 grep -q '^[[:blank:]]*global[[:blank:]]*{' $LVMCONF
11685 have_global=$?
11686
11687 if [ "$have_global" = "1" ]
11688 then
11689 echo "global keys but no 'global {' found, can't edit file"
11690 exit 12
11691 fi
11692fi
11693
11694# So if we don't have "global {" we need to create one and
11695# populate it
11696
11697if [ "$have_global" = "1" ]
11698then
11699 cat $LVMCONF - <<EOF > $TMPFILE
11700global {
11701 # Enable locking for cluster LVM
11702 locking_type = $locking_type
11703 library_dir = "$PREFIX"
11704 locking_library = "$LIB"
11705}
11706EOF
11707 if [ $? != 0 ]
11708 then
11709 echo "failed to create temporary config file, $LVMCONF not updated"
11710 exit 1
11711 fi
11712else
11713 #
11714 # We have a "global {" section, so add or replace the
11715 # locking entries as appropriate
11716 #
11717
11718 if [ "$have_type" = "0" ]
11719 then
11720 SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $locking_type/g"
11721 else
11722 SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = 2"
11723 fi
11724
11725 if [ "$have_dir" = "0" ]
11726 then
11727 SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$PREFIX\"'g"
11728 else
11729 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$PREFIX\""
11730 fi
11731
11732 if [ "$have_library" = "0" ]
11733 then
11734 SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LIB\"/g"
11735 else
11736 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LIB\""
11737 fi
11738
11739 echo -e $SEDCMD > $SCRIPTFILE
11740 sed <$LVMCONF >$TMPFILE -f $SCRIPTFILE
11741 if [ $? != 0 ]
11742 then
11743 echo "sed failed, $LVMCONF not updated"
11744 exit 1
11745 fi
11746fi
11747
11748# Now we have a suitably editted config file in a temp place,
11749# backup the original and copy our new one into place.
11750
11751cp $LVMCONF $LVMCONF.nocluster
11752if [ $? != 0 ]
11753 then
11754 echo "failed to backup old config file, $LVMCONF not updated"
11755 exit 2
11756fi
11757
11758cp $TMPFILE $LVMCONF
11759if [ $? != 0 ]
11760 then
11761 echo "failed to copy new config file into place, check $LVMCONF is still OK"
11762 exit 3
11763fi
11764
11765rm -f $SCRIPTFILE $TMPFILE
11766
11767\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/dm_event_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000523\013062740170\0025564\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
11768Description=Device-mapper event daemon
11769Documentation=man:dmeventd(8)
11770Requires=dm-event.socket
11771After=dm-event.socket
11772Before=local-fs-pre.target
11773DefaultDependencies=no
11774
11775[Service]
11776Type=simple
11777ExecStart=@sbindir@/dmeventd -f
11778Environment=SD_ACTIVATION=1
11779PIDFile=@DMEVENTD_PIDFILE@
11780OOMScoreAdjust=-1000
11781
11782[Install]
11783WantedBy=sysinit.target
11784\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/clvmd_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010551\013062740170\0022706\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
11785#
11786# clvmd - Clustered LVM Daemon init script
11787#
11788# chkconfig: - 24 76
11789# description: Cluster daemon for userland logical volume management tools.
11790# pidfile: @CLVMD_PIDFILE@
11791#
11792# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
11793#
11794### BEGIN INIT INFO
11795# Provides: clvmd
11796# Required-Start: $local_fs@CLVMD_CMANAGERS@
11797# Required-Stop: $local_fs@CLVMD_CMANAGERS@
11798# Short-Description: This service is Clusterd LVM Daemon.
11799# Description: Cluster daemon for userland logical volume management tools.
11800### END INIT INFO
11801
11802. /etc/rc.d/init.d/functions
11803
11804DAEMON=clvmd
11805
11806exec_prefix=@exec_prefix@
11807sbindir=@sbindir@
11808
11809lvm_vgchange=${sbindir}/vgchange
11810lvm_vgs=${sbindir}/vgs
11811lvm_vgscan=${sbindir}/vgscan
11812lvm_lvs=${sbindir}/lvs
11813
11814CLVMDOPTS="-T30"
11815
11816[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
11817[ -f /etc/sysconfig/$DAEMON ] && . /etc/sysconfig/$DAEMON
11818
11819[ -n "$CLVMD_CLUSTER_IFACE" ] && CLVMDOPTS="$CLVMDOPTS -I $CLVMD_CLUSTER_IFACE"
11820
11821# allow up to $CLVMD_STOP_TIMEOUT seconds to clvmd to complete exit operations
11822# default to 10 seconds
11823
11824[ -z $CLVMD_STOP_TIMEOUT ] && CLVMD_STOP_TIMEOUT=10
11825
11826LOCK_FILE="/var/lock/subsys/$DAEMON"
11827
11828clustered_vgs() {
11829 ${lvm_vgs} --noheadings -o vg_name -S 'vg_clustered=1' 2>/dev/null
11830}
11831
11832clustered_active_lvs() {
11833 ${lvm_lvs} --noheadings -o lv_name -S 'vg_clustered=1 && lv_active!=""' 2>/dev/null
11834}
11835
11836rh_status() {
11837 status $DAEMON
11838}
11839
11840rh_status_q() {
11841 rh_status >/dev/null 2>&1
11842}
11843
11844start()
11845{
11846 if ! rh_status_q; then
11847 echo -n "Starting $DAEMON: "
11848 $DAEMON $CLVMDOPTS || return $?
11849 echo
11850 fi
11851
11852 # Refresh local cache.
11853 #
11854 # It's possible that new PVs were added to this, or other VGs
11855 # while this node was down. So we run vgscan here to avoid
11856 # any potential "Missing UUID" messages with subsequent
11857 # LVM commands.
11858
11859 # The following step would be better and more informative to the user:
11860 # 'action "Refreshing VG(s) local cache:" ${lvm_vgscan}'
11861 # but it could show warnings such as:
11862 # 'clvmd not running on node x-y-z Unable to obtain global lock.'
11863 # and the action would be shown as FAILED when in reality it didn't.
11864 # Ideally vgscan should have a startup mode that would not print
11865 # unnecessary warnings.
11866
11867 ${lvm_vgscan} > /dev/null 2>&1
11868
11869 action "Activating VG(s):" ${lvm_vgchange} -aay $LVM_VGS || return $?
11870
11871 touch $LOCK_FILE
11872
11873 return 0
11874}
11875
11876wait_for_finish()
11877{
11878 count=0
11879 while [ "$count" -le "$CLVMD_STOP_TIMEOUT" ] && \
11880 rh_status_q ]; do
11881 sleep 1
11882 count=$((count+1))
11883 done
11884
11885 ! rh_status_q
11886}
11887
11888stop()
11889{
11890 rh_status_q || return 0
11891
11892 [ -z "$LVM_VGS" ] && LVM_VGS="$(clustered_vgs)"
11893 if [ -n "$LVM_VGS" ]; then
11894 action "Deactivating clustered VG(s):" ${lvm_vgchange} -anl $LVM_VGS || return $?
11895 fi
11896
11897 action "Signaling $DAEMON to exit" kill -TERM $(pidofproc $DAEMON) || return $?
11898
11899 # wait half second before we start the waiting loop or we will show
11900 # the loop more time than really necessary
11901 usleep 500000
11902
11903 # clvmd could take some time to stop
11904 rh_status_q && action "Waiting for $DAEMON to exit:" wait_for_finish
11905
11906 if rh_status_q; then
11907 echo -n "$DAEMON failed to exit"
11908 failure
11909 echo
11910 return 1
11911 else
11912 echo -n "$DAEMON terminated"
11913 success
11914 echo
11915 fi
11916
11917 rm -f $LOCK_FILE
11918
11919 return 0
11920}
11921
11922reload() {
11923 rh_status_q || exit 7
11924 action "Reloading $DAEMON configuration: " $DAEMON -R || return $?
11925}
11926
11927restart() {
11928 # if stop fails, restart will return the error and not attempt
11929 # another start. Even if start is protected by rh_status_q,
11930 # that would avoid spawning another daemon, it would try to
11931 # reactivate the VGs.
11932
11933 # Try to get clvmd to restart itself. This will preserve
11934 # exclusive LV locks
11935 action "Restarting $DAEMON: " $DAEMON -S
11936
11937 # If that fails then do a normal stop & restart
11938 if [ $? != 0 ]; then
11939 stop && start
11940 return $?
11941 else
11942 touch $LOCK_FILE
11943 return 0
11944 fi
11945}
11946
11947[ "$EUID" != "0" ] && {
11948 echo "clvmd init script can only be executed as root user"
11949 exit 4
11950}
11951
11952# See how we were called.
11953case "$1" in
11954 start)
11955 start
11956 rtrn=$?
11957 ;;
11958
11959 stop)
11960 stop
11961 rtrn=$?
11962 ;;
11963
11964 restart|force-reload)
11965 restart
11966 rtrn=$?
11967 ;;
11968
11969 condrestart|try-restart)
11970 rh_status_q || exit 0
11971 restart
11972 rtrn=$?
11973 ;;
11974
11975 reload)
11976 reload
11977 rtrn=$?
11978 ;;
11979
11980 status)
11981 rh_status
11982 rtrn=$?
11983 if [ $rtrn = 0 ]; then
11984 cvgs="$(clustered_vgs)"
11985 echo Clustered Volume Groups: ${cvgs:-"(none)"}
11986 clvs="$(clustered_active_lvs)"
11987 echo Active clustered Logical Volumes: ${clvs:-"(none)"}
11988 fi
11989 ;;
11990
11991 *)
11992 echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
11993 rtrn=2
11994 ;;
11995esac
11996
11997exit $rtrn
11998\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/com.redhat.lvmdbus1.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000167\013062740170\0024311\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[D-BUS Service]
11999Name=com.redhat.lvmdbus1
12000Exec=@sbindir@/lvmdbusd --udev
12001User=root
12002SystemdService=lvm2-lvmdbusd.service
12003\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmetad_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004147\013062740170\0024201\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
12004#
12005# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
12006#
12007# This copyrighted material is made available to anyone wishing to use,
12008# modify, copy, or redistribute it subject to the terms and conditions
12009# of the GNU General Public License v.2.
12010#
12011# You should have received a copy of the GNU General Public License
12012# along with this program; if not, write to the Free Software Foundation,
12013# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12014#
12015# This file is part of LVM2.
12016# It is required for the proper handling of failures of LVM2 mirror
12017# devices that were created using the -m option of lvcreate.
12018#
12019#
12020# chkconfig: 12345 02 99
12021# description: Starts and stops LVM metadata daemon
12022#
12023# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
12024#
12025### BEGIN INIT INFO
12026# Provides: lvm2-lvmetad
12027# Required-Start: $local_fs
12028# Required-Stop: $local_fs
12029# Default-Start: 1 2 3 4 5
12030# Default-Stop: 0 6
12031# Short-Description: A daemon that maintains LVM metadata state for improved
12032# performance by avoiding further scans while running
12033# subsequent LVM commands or while using lvm2app library.
12034### END INIT INFO
12035
12036. /etc/init.d/functions
12037
12038DAEMON=lvmetad
12039
12040exec_prefix=@exec_prefix@
12041sbindir=@sbindir@
12042
12043LOCK_FILE="/var/lock/subsys/$DAEMON"
12044PID_FILE="@LVMETAD_PIDFILE@"
12045
12046rh_status() {
12047 status -p $PID_FILE $DAEMON
12048}
12049
12050rh_status_q() {
12051 rh_status >/dev/null 2>&1
12052}
12053
12054start()
12055{
12056 ret=0
12057 action "Starting LVM metadata daemon:" $DAEMON || ret=$?
12058 return $ret
12059}
12060
12061
12062stop()
12063{
12064 ret=0
12065 action "Signaling LVM metadata daemon to exit:" killproc -p $PID_FILE $DAEMON -TERM || ret=$?
12066 return $ret
12067}
12068
12069rtrn=1
12070
12071# See how we were called.
12072case "$1" in
12073 start)
12074 rh_status_q && exit 0
12075 start
12076 rtrn=$?
12077 [ $rtrn = 0 ] && touch $LOCK_FILE
12078 ;;
12079
12080 stop|force-stop)
12081 rh_status_q || exit 0
12082 stop
12083 rtrn=$?
12084 [ $rtrn = 0 ] && rm -f $LOCK_FILE
12085 ;;
12086
12087 restart)
12088 if stop
12089 then
12090 start
12091 fi
12092 rtrn=$?
12093 ;;
12094
12095 condrestart|try-restart)
12096 rh_status_q || exit 0
12097 if stop
12098 then
12099 start
12100 fi
12101 rtrn=$?
12102 ;;
12103
12104 status)
12105 rh_status
12106 rtrn=$?
12107 ;;
12108
12109 *)
12110 echo $"Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
12111 ;;
12112esac
12113
12114exit $rtrn
12115\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmetad_systemd_red_hat.socket.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000340\013062740170\0026204\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
12116Description=LVM2 metadata daemon socket
12117Documentation=man:lvmetad(8)
12118DefaultDependencies=no
12119
12120[Socket]
12121ListenStream=@DEFAULT_RUN_DIR@/lvmetad.socket
12122SocketMode=0600
12123RemoveOnStop=true
12124
12125[Install]
12126WantedBy=sysinit.target
12127\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/blkdeactivate.sh.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000032573\013062740170\0022313\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
12128#
12129# Copyright (C) 2012-2015 Red Hat, Inc. All rights reserved.
12130#
12131# This file is part of LVM2.
12132#
12133# This copyrighted material is made available to anyone wishing to use,
12134# modify, copy, or redistribute it subject to the terms and conditions
12135# of the GNU General Public License v.2.
12136#
12137# You should have received a copy of the GNU General Public License
12138# along with this program; if not, write to the Free Software Foundation,
12139# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12140#
12141# Author: Peter Rajnoha <prajnoha at redhat.com>
12142#
12143# Script for deactivating block devices
12144#
12145# Requires:
12146# bash >= 4.0 (associative array support)
12147# util-linux {
12148# lsblk >= 2.22 (lsblk -s support)
12149# umount
12150# }
12151# dmsetup >= 1.02.68 (--retry option support)
12152# lvm >= 2.2.89 (activation/retry_deactivation config support)
12153#
12154
12155#set -x
12156shopt -s dotglob nullglob
12157
12158TOOL=blkdeactivate
12159
12160DEV_DIR='/dev'
12161SYS_BLK_DIR='/sys/block'
12162
12163MOUNTPOINT="/bin/mountpoint"
12164UMOUNT="/bin/umount"
12165DMSETUP="@sbindir@/dmsetup"
12166LVM="@sbindir@/lvm"
12167MDADM="@sbindir@/mdadm"
12168MPATHD="/sbin/multipathd"
12169
12170if $UMOUNT --help | grep -- "--all-targets" >$DEV_DIR/null; then
12171 UMOUNT_OPTS="--all-targets "
12172else
12173 UMOUNT_OPTS=""
12174 FINDMNT="/bin/findmnt -r --noheadings -u -o TARGET"
12175 FINDMNT_READ="read -r mnt"
12176fi
12177DMSETUP_OPTS=""
12178LVM_OPTS=""
12179MDADM_OPTS=""
12180MPATHD_OPTS=""
12181
12182LSBLK="/bin/lsblk -r --noheadings -o TYPE,KNAME,NAME,MOUNTPOINT"
12183LSBLK_VARS="local devtype local kname local name local mnt"
12184LSBLK_READ="read -r devtype kname name mnt"
12185SORT_MNT="/bin/sort -r -u -k 4"
12186
12187# Do not show tool errors by default (only done/skipping summary
12188# message provided by this script) and no verbose mode by default.
12189ERRORS=0
12190VERBOSE=0
12191
12192# Do not unmount mounted devices by default.
12193DO_UMOUNT=0
12194
12195# Deactivate each LV separately by default (not the whole VG).
12196LVM_DO_WHOLE_VG=0
12197# Do not retry LV deactivation by default.
12198LVM_CONFIG="activation{retry_deactivation=0}"
12199
12200# Do not disable queueing if set on multipath devices.
12201MPATHD_DO_DISABLEQUEUEING=0
12202
12203#
12204# List of device names and/or VGs to be skipped.
12205# Device name is the KNAME from lsblk output.
12206#
12207# If deactivation of any device fails, it's automatically
12208# added to the SKIP_DEVICE_LIST (also a particular VG
12209# added to the SKIP_VG_LIST for a device that is an LV).
12210#
12211# These lists provide device tree pruning to skip
12212# particular device/VG deactivation that failed already.
12213# (lists are associative arrays!)
12214#
12215declare -A SKIP_DEVICE_LIST=()
12216declare -A SKIP_VG_LIST=()
12217
12218#
12219# List of mountpoints to be skipped. Any device that is mounted on the mountpoint
12220# listed here will be added to SKIP_DEVICE_LIST (and SKIP_VG_LIST) automatically.
12221# (list is an associative array!)
12222#
12223declare -A SKIP_UMOUNT_LIST=(["/"]=1 ["/boot"]=1 \
12224 ["/lib"]=1 ["/lib64"]=1 \
12225 ["/bin"]=1 ["/sbin"]=1 \
12226 ["/var"]=1 ["/var/log"]=1 \
12227 ["/usr"]=1 \
12228 ["/usr/lib"]=1 ["/usr/lib64"]=1 \
12229 ["/usr/sbin"]=1 ["/usr/bin"]=1)
12230# Bash can't properly handle '[' and ']' used as a subscript
12231# within the '()'initialization - it needs to be done separately!
12232SKIP_UMOUNT_LIST["[SWAP]"]=1
12233
12234usage() {
12235 echo "${TOOL}: Utility to deactivate block devices"
12236 echo
12237 echo " ${TOOL} [options] [device...]"
12238 echo " - Deactivate block device tree."
12239 echo " If devices are specified, deactivate only supplied devices and their holders."
12240 echo
12241 echo " Options:"
12242 echo " -e | --errors Show errors reported from tools"
12243 echo " -h | --help Show this help message"
12244 echo " -d | --dmoption DM_OPTIONS Comma separated DM specific options"
12245 echo " -l | --lvmoption LVM_OPTIONS Comma separated LVM specific options"
12246 echo " -m | --mpathoption MPATH_OPTIONS Comma separated DM-multipath specific options"
12247 echo " -u | --umount Unmount the device if mounted"
12248 echo " -v | --verbose Verbose mode (also implies -e)"
12249 echo
12250 echo " Device specific options:"
12251 echo " DM_OPTIONS:"
12252 echo " retry retry removal several times in case of failure"
12253 echo " force force device removal"
12254 echo " LVM_OPTIONS:"
12255 echo " retry retry removal several times in case of failure"
12256 echo " wholevg deactivate the whole VG when processing an LV"
12257 echo " MPATH_OPTIONS:"
12258 echo " disablequeueing disable queueing on all DM-multipath devices first"
12259
12260 exit
12261}
12262
12263add_device_to_skip_list() {
12264 SKIP_DEVICE_LIST+=(["$kname"]=1)
12265 return 1
12266}
12267
12268add_vg_to_skip_list() {
12269 SKIP_VG_LIST+=(["$DM_VG_NAME"]=1)
12270 return 1
12271}
12272
12273is_top_level_device() {
12274 # top level devices do not have any holders, that is
12275 # the SYS_BLK_DIR/<device_name>/holders dir is empty
12276 files="`echo $SYS_BLK_DIR/$kname/holders/*`"
12277 test -z "$files"
12278}
12279
12280device_umount_one() {
12281 test -z "$mnt" && return 0
12282
12283 if test -z "${SKIP_UMOUNT_LIST["$mnt"]}" -a "$DO_UMOUNT" -eq "1"; then
12284 echo -n " [UMOUNT]: unmounting $name ($kname) mounted on $mnt... "
12285 if eval $UMOUNT $UMOUNT_OPTS "$(printf "%s" "$mnt")" $OUT $ERR; then
12286 echo "done"
12287 elif $MOUNTPOINT -q "$mnt"; then
12288 echo "skipping"
12289 add_device_to_skip_list
12290 else
12291 echo "already unmounted"
12292 fi
12293 else
12294 echo " [SKIP]: unmount of $name ($kname) mounted on $mnt"
12295 add_device_to_skip_list
12296 fi
12297}
12298
12299device_umount() {
12300 test "$devtype" != "lvm" && test "${kname:0:3}" != "dm-" && return 0
12301
12302 # FINDMNT is defined only if umount --all-targets is not available.
12303 # In that case, read the list of multiple mount points of one device
12304 # using FINDMNT and unmount it one by one manually.
12305 if test -z "$FINDMNT"; then
12306 device_umount_one
12307 else
12308 while $FINDMNT_READ; do
12309 device_umount_one || return 1
12310 done <<< "`$FINDMNT $DEV_DIR/$kname`"
12311 fi
12312
12313}
12314
12315deactivate_holders () {
12316 local skip=1; $LSBLK_VARS
12317
12318 # Get holders for the device - either a mount or another device.
12319 # First line on the lsblk output is the device itself - skip it for
12320 # the deactivate call as this device is already being deactivated.
12321 while $LSBLK_READ; do
12322 test -e $SYS_BLK_DIR/$kname || continue
12323 # check if the device not on the skip list already
12324 test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
12325
12326 # try to deactivate the holder
12327 test $skip -eq 1 && skip=0 && continue
12328 deactivate || return 1
12329 done <<< "`$LSBLK $1`"
12330}
12331
12332deactivate_dm () {
12333 local name=$(printf "%s" "$name")
12334 test -b "$DEV_DIR/mapper/$name" || return 0
12335 test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
12336
12337 deactivate_holders "$DEV_DIR/mapper/$name" || return 1
12338
12339 echo -n " [DM]: deactivating $devtype device $name ($kname)... "
12340 if eval $DMSETUP $DMSETUP_OPTS remove "$name" $OUT $ERR; then
12341 echo "done"
12342 else
12343 echo "skipping"
12344 add_device_to_skip_list
12345 fi
12346}
12347
12348deactivate_lvm () {
12349 local DM_VG_NAME; local DM_LV_NAME; local DM_LV_LAYER
12350
12351 eval $(eval $DMSETUP splitname --nameprefixes --noheadings --rows "$name" LVM $ERR)
12352 test -b "$DEV_DIR/$DM_VG_NAME/$DM_LV_NAME" || return 0
12353 test -z ${SKIP_VG_LIST["$DM_VG_NAME"]} || return 1
12354
12355 if test $LVM_DO_WHOLE_VG -eq 0; then
12356 # Skip LVM device deactivation if LVM tools missing.
12357 test $LVM_AVAILABLE -eq 0 && {
12358 add_device_to_skip_list
12359 return 1
12360 }
12361 # Deactivating only the LV specified
12362 deactivate_holders "$DEV_DIR/$DM_VG_NAME/$DM_LV_NAME" || {
12363 add_device_to_skip_list
12364 return 1
12365 }
12366
12367 echo -n " [LVM]: deactivating Logical Volume $DM_VG_NAME/$DM_LV_NAME... "
12368 if eval $LVM lvchange $LVM_OPTS --config \'log{prefix=\"\"} $LVM_CONFIG\' -aln $DM_VG_NAME/$DM_LV_NAME $OUT $ERR; then
12369 echo "done"
12370 else
12371 echo "skipping"
12372 add_device_to_skip_list
12373 fi
12374
12375 else
12376 # Skip LVM VG deactivation if LVM tools missing.
12377 test $LVM_AVAILABLE -eq 0 && {
12378 add_vg_to_skip_list
12379 return 1
12380 }
12381 # Deactivating the whole VG the LV is part of
12382 lv_list=$(eval $LVM vgs --config "$LVM_CONFIG" --noheadings --rows -o lv_name $DM_VG_NAME $ERR)
12383 for lv in $lv_list; do
12384 test -b "$DEV_DIR/$DM_VG_NAME/$lv" || continue
12385 deactivate_holders "$DEV_DIR/$DM_VG_NAME/$lv" || {
12386 add_vg_to_skip_list
12387 return 1
12388 }
12389 done
12390
12391 echo -n " [LVM]: deactivating Volume Group $DM_VG_NAME... "
12392 if eval $LVM vgchange $LVM_OPTS --config \'log{prefix=\" \"} $LVM_CONFIG\' -aln $DM_VG_NAME $OUT $ERR; then
12393 echo "done"
12394 else
12395 echo "skipping"
12396 add_vg_to_skip_list
12397 fi
12398 fi
12399}
12400
12401deactivate_md () {
12402 local name=$(printf "%s" "$name")
12403 test -b "$DEV_DIR/$name" || return 0
12404 test -z ${SKIP_DEVICE_LIST["$kname"]} || return 1
12405
12406 # Skip MD device deactivation if MD tools missing.
12407 test $MDADM_AVAILABLE -eq 0 && {
12408 add_device_to_skip_list
12409 return 1
12410 }
12411
12412 deactivate_holders "$DEV_DIR/$name" || return 1
12413
12414 echo -n " [MD]: deactivating $devtype device $kname... "
12415 if eval $MDADM $MDADM_OPTS -S "$name" $OUT $ERR; then
12416 echo "done"
12417 else
12418 echo "skipping"
12419 add_device_to_skip_list
12420 fi
12421}
12422
12423deactivate () {
12424 ######################################################################
12425 # DEACTIVATION HOOKS FOR NEW DEVICE TYPES GO HERE! #
12426 # #
12427 # Identify a new device type either by inspecting the TYPE provided #
12428 # by lsblk directly ($devtype) or by any other mean that is suitable #
12429 # e.g. the KNAME provided by lsblk ($kname). See $LSBLK_VARS for #
12430 # complete list of variables that may be used. Then call a #
12431 # device-specific deactivation function that handles the exact type. #
12432 # #
12433 # This device-specific function will certainly need to call #
12434 # deactivate_holders first to recursively deactivate any existing #
12435 # holders it might have before deactivating the device it processes. #
12436 ######################################################################
12437 if test "$devtype" = "lvm"; then
12438 deactivate_lvm
12439 elif test "${kname:0:3}" = "dm-"; then
12440 deactivate_dm
12441 elif test "${kname:0:2}" = "md"; then
12442 deactivate_md
12443 fi
12444}
12445
12446deactivate_all() {
12447 $LSBLK_VARS
12448 skip=0
12449
12450 echo "Deactivating block devices:"
12451
12452 test $MPATHD_RUNNING -eq 1 && {
12453 echo -n " [DM]: disabling queueing on all multipath devices... "
12454 eval $MPATHD $MPATHD_OPTS disablequeueing maps $ERR | grep '^ok$' >$DEV_DIR/null && echo "done" || echo "failed"
12455 }
12456
12457 if test $# -eq 0; then
12458 #######################
12459 # Process all devices #
12460 #######################
12461
12462 # Unmount all relevant mountpoints first
12463 while $LSBLK_READ; do
12464 device_umount
12465 done <<< "`$LSBLK | $SORT_MNT`"
12466
12467 # Do deactivate
12468 while $LSBLK_READ; do
12469 # 'disk' is at the bottom already and it's a real device
12470 test "$devtype" = "disk" && continue
12471
12472 # if deactivation of any device fails, skip processing
12473 # any subsequent devices within its subtree as the
12474 # top-level device could not be deactivated anyway
12475 test $skip -eq 1 && {
12476 # reset 'skip' on top level device
12477 is_top_level_device && skip=0 || continue
12478 }
12479
12480 # check if the device is not on the skip list already
12481 test -z ${SKIP_DEVICE_LIST["$kname"]} || continue
12482
12483 # try to deactivate top-level device, set 'skip=1'
12484 # if it fails to do so - this will cause all the
12485 # device's subtree to be skipped when processing
12486 # devices further in this loop
12487 deactivate || skip=1
12488 done <<< "`$LSBLK -s`"
12489 else
12490 ##################################
12491 # Process only specified devices #
12492 ##################################
12493
12494 while test $# -ne 0; do
12495 # Unmount all relevant mountpoints first
12496 while $LSBLK_READ; do
12497 device_umount
12498 done <<< "`$LSBLK $1 | $SORT_MNT`"
12499
12500 # Do deactivate
12501 # Single dm device tree deactivation.
12502 if test -b "$1"; then
12503 $LSBLK_READ <<< "`$LSBLK --nodeps $1`"
12504
12505 # check if the device is not on the skip list already
12506 test -z ${SKIP_DEVICE_LIST["$kname"]} || {
12507 shift
12508 continue
12509 }
12510
12511 deactivate
12512 else
12513 echo "$1: device not found"
12514 return 1
12515 fi
12516 shift
12517 done;
12518 fi
12519}
12520
12521get_dmopts() {
12522 ORIG_IFS=$IFS; IFS=','
12523
12524 for opt in $1; do
12525 case $opt in
12526 "") ;;
12527 "retry") DMSETUP_OPTS+="--retry " ;;
12528 "force") DMSETUP_OPTS+="--force " ;;
12529 *) echo "$opt: unknown DM option"
12530 esac
12531 done
12532
12533 IFS=$ORIG_IFS
12534}
12535
12536get_lvmopts() {
12537 ORIG_IFS=$IFS; IFS=','
12538
12539 for opt in $1; do
12540 case "$opt" in
12541 "") ;;
12542 "retry") LVM_CONFIG="activation{retry_deactivation=1}" ;;
12543 "wholevg") LVM_DO_WHOLE_VG=1 ;;
12544 *) echo "$opt: unknown LVM option"
12545 esac
12546 done
12547
12548 IFS=$ORIG_IFS
12549}
12550
12551get_mpathopts() {
12552 ORIG_IFS=$IFS; IFS=','
12553
12554 for opt in $1; do
12555 case "$opt" in
12556 "") ;;
12557 "disablequeueing") MPATHD_DO_DISABLEQUEUEING=1 ;;
12558 *) echo "$opt: unknown DM-multipath option"
12559 esac
12560 done
12561
12562 IFS=$ORIG_IFS
12563}
12564
12565set_env() {
12566 if test "$ERRORS" -eq "1"; then
12567 unset ERR
12568 else
12569 ERR="2>$DEV_DIR/null"
12570 fi
12571
12572 if test "$VERBOSE" -eq "1"; then
12573 unset OUT
12574 UMOUNT_OPTS+="-v"
12575 DMSETUP_OPTS+="-vvvv"
12576 LVM_OPTS+="-vvvv"
12577 MDADM_OPTS+="-vv"
12578 MPATHD_OPTS+="-v 3"
12579 else
12580 OUT="1>$DEV_DIR/null"
12581 fi
12582
12583 if test -f $LVM; then
12584 LVM_AVAILABLE=1
12585 else
12586 LVM_AVAILABLE=0
12587 fi
12588
12589 if test -f $MDADM; then
12590 MDADM_AVAILABLE=1
12591 else
12592 MDADM_AVAILABLE=0
12593 fi
12594
12595 MPATHD_RUNNING=0
12596 test $MPATHD_DO_DISABLEQUEUEING -eq 1 && {
12597 if test -f $MPATHD; then
12598 if eval $MPATHD show daemon $ERR | grep "running" >$DEV_DIR/null; then
12599 MPATHD_RUNNING=1
12600 fi
12601 fi
12602 }
12603}
12604
12605while test $# -ne 0; do
12606 case "$1" in
12607 "") ;;
12608 "-e"|"--errors") ERRORS=1 ;;
12609 "-h"|"--help") usage ;;
12610 "-d"|"--dmoption ") get_dmopts "$2" ; shift ;;
12611 "-l"|"--lvmoption ") get_lvmopts "$2" ; shift ;;
12612 "-m"|"--mpathoption ") get_mpathopts "$2" ; shift ;;
12613 "-u"|"--umount") DO_UMOUNT=1 ;;
12614 "-v"|"--verbose") VERBOSE=1 ; ERRORS=1 ;;
12615 "-vv") VERBOSE=1 ; ERRORS=1 ; set -x ;;
12616 *) break ;;
12617 esac
12618 shift
12619done
12620
12621set_env
12622deactivate_all "$@"
12623\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmpolld_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004360\013062740170\0024373\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
12624#
12625# Copyright (C) 2015 Red Hat, Inc. All rights reserved.
12626#
12627# This copyrighted material is made available to anyone wishing to use,
12628# modify, copy, or redistribute it subject to the terms and conditions
12629# of the GNU General Public License v.2.
12630#
12631# You should have received a copy of the GNU General Public License
12632# along with this program; if not, write to the Free Software Foundation,
12633# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12634#
12635# This file is part of LVM2.
12636# It is required for the proper handling of failures of LVM2 mirror
12637# devices that were created using the -m option of lvcreate.
12638#
12639#
12640# chkconfig: 12345 02 99
12641# description: Starts and stops LVM poll daemon
12642#
12643# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
12644#
12645### BEGIN INIT INFO
12646# Provides: lvm2-lvmpolld
12647# Required-Start: $local_fs
12648# Required-Stop: $local_fs
12649# Default-Start: 1 2 3 4 5
12650# Default-Stop: 0 6
12651# Short-Description: A daemon that is responsible for monitoring in-progress
12652# and possibly longer term operations on logical volumes.
12653# It helps to reduce the number of spawned processes if same
12654# logical volume is requested to get monitored multiple times.
12655# Also avoids unsolicited termination due to external factors.
12656### END INIT INFO
12657
12658. /etc/init.d/functions
12659
12660DAEMON=lvmpolld
12661
12662exec_prefix=@exec_prefix@
12663sbindir=@sbindir@
12664
12665LOCK_FILE="/var/lock/subsys/$DAEMON"
12666PID_FILE="@LVMPOLLD_PIDFILE@"
12667
12668rh_status() {
12669 status -p $PID_FILE $DAEMON
12670}
12671
12672rh_status_q() {
12673 rh_status >/dev/null 2>&1
12674}
12675
12676start()
12677{
12678 ret=0
12679 action "Starting LVM poll daemon:" $DAEMON || ret=$?
12680 return $ret
12681}
12682
12683
12684stop()
12685{
12686 ret=0
12687 action "Signaling LVM poll daemon to exit:" killproc -p $PID_FILE $DAEMON -TERM || ret=$?
12688 return $ret
12689}
12690
12691rtrn=1
12692
12693# See how we were called.
12694case "$1" in
12695 start)
12696 rh_status_q && exit 0
12697 start
12698 rtrn=$?
12699 [ $rtrn = 0 ] && touch $LOCK_FILE
12700 ;;
12701
12702 stop|force-stop)
12703 rh_status_q || exit 0
12704 stop
12705 rtrn=$?
12706 [ $rtrn = 0 ] && rm -f $LOCK_FILE
12707 ;;
12708
12709 restart)
12710 if stop
12711 then
12712 start
12713 fi
12714 rtrn=$?
12715 ;;
12716
12717 condrestart|try-restart)
12718 rh_status_q || exit 0
12719 if stop
12720 then
12721 start
12722 fi
12723 rtrn=$?
12724 ;;
12725
12726 status)
12727 rh_status
12728 rtrn=$?
12729 ;;
12730
12731 *)
12732 echo $"Usage: $0 {start|stop|force-stop|restart|condrestart|try-restart|status}"
12733 ;;
12734esac
12735
12736exit $rtrn
12737\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/blk_availability_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000577\013062740170\0027276\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
12738Description=Availability of block devices
12739After=lvm2-activation.service lvm2-lvmetad.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service
12740DefaultDependencies=no
12741Conflicts=shutdown.target
12742
12743[Service]
12744Type=oneshot
12745ExecStart=/usr/bin/true
12746ExecStop=@sbindir@/blkdeactivate -u -l wholevg -m disablequeueing
12747RemainAfterExit=yes
12748
12749[Install]
12750WantedBy=sysinit.target
12751\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvmconf_lockingtype2.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015124\013062740170\0023233\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
12752#
12753# Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
12754#
12755# This file is part of the lvm2-cluster package.
12756#
12757# This copyrighted material is made available to anyone wishing to use,
12758# modify, copy, or redistribute it subject to the terms and conditions
12759# of the GNU General Public License v.2.
12760#
12761# You should have received a copy of the GNU General Public License
12762# along with this program; if not, write to the Free Software Foundation,
12763# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
12764
12765#
12766# Edit an lvm.conf file to adjust various properties
12767#
12768
12769function usage
12770{
12771 echo "usage: $0 <command>"
12772 echo ""
12773 echo "Commands:"
12774 echo "Enable clvm: --enable-cluster [--lockinglibdir <dir>] [--lockinglib <lib>]"
12775 echo "Disable clvm: --disable-cluster"
12776 echo "Set locking library: --lockinglibdir <dir> [--lockinglib <lib>]"
12777 echo ""
12778 echo "Global options:"
12779 echo "Config file location: --file <configfile>"
12780 echo ""
12781}
12782
12783
12784function parse_args
12785{
12786 while [ -n "$1" ]; do
12787 case $1 in
12788 --enable-cluster)
12789 LOCKING_TYPE=2
12790 shift
12791 ;;
12792 --disable-cluster)
12793 LOCKING_TYPE=1
12794 shift
12795 ;;
12796 --lockinglibdir)
12797 if [ -n "$2" ]; then
12798 LOCKINGLIBDIR=$2
12799 shift 2
12800 else
12801 usage
12802 exit 1
12803 fi
12804 ;;
12805 --lockinglib)
12806 if [ -n "$2" ]; then
12807 LOCKINGLIB=$2
12808 shift 2
12809 else
12810 usage
12811 exit 1
12812 fi
12813 ;;
12814 --file)
12815 if [ -n "$2" ]; then
12816 CONFIGFILE=$2
12817 shift 2
12818 else
12819 usage
12820 exit 1
12821 fi
12822 ;;
12823 *)
12824 usage
12825 exit 1
12826 esac
12827 done
12828}
12829
12830function validate_args
12831{
12832 [ -z "$CONFIGFILE" ] && CONFIGFILE="/etc/lvm/lvm.conf"
12833
12834 if [ ! -f "$CONFIGFILE" ]
12835 then
12836 echo "$CONFIGFILE does not exist"
12837 exit 10
12838 fi
12839
12840 if [ -z "$LOCKING_TYPE" ] && [ -z "$LOCKINGLIBDIR" ]; then
12841 usage
12842 exit 1
12843 fi
12844
12845 if [ -n "$LOCKINGLIBDIR" ]; then
12846
12847 [ -z "$LOCKINGLIB" ] && LOCKINGLIB="liblvm2clusterlock.so"
12848
12849 if [ "${LOCKINGLIBDIR:0:1}" != "/" ]
12850 then
12851 echo "Prefix must be an absolute path name (starting with a /)"
12852 exit 12
12853 fi
12854
12855 if [ ! -f "$LOCKINGLIBDIR/$LOCKINGLIB" ]
12856 then
12857 echo "$LOCKINGLIBDIR/$LOCKINGLIB does not exist, did you do a \"make install\" ?"
12858 exit 11
12859 fi
12860
12861 fi
12862
12863 if [ "$LOCKING_TYPE" = "1" ] && [ -n "$LOCKINGLIBDIR" -o -n "$LOCKINGLIB" ]; then
12864 echo "Superfluous locking lib parameter, ignoring"
12865 fi
12866}
12867
12868umask 0077
12869
12870parse_args "$@"
12871
12872validate_args
12873
12874
12875SCRIPTFILE=/etc/lvm/.lvmconf-script.tmp
12876TMPFILE=/etc/lvm/.lvmconf-tmp.tmp
12877
12878
12879# Flags so we know which parts of the file we can replace and which need
12880# adding. These are return codes from grep, so zero means it IS present!
12881have_type=1
12882have_dir=1
12883have_library=1
12884have_global=1
12885
12886grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $CONFIGFILE
12887have_type=$?
12888
12889grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $CONFIGFILE
12890have_dir=$?
12891
12892grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $CONFIGFILE
12893have_library=$?
12894
12895# Those options are in section "global {" so we must have one if any are present.
12896if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" ]
12897then
12898
12899 # See if we can find it...
12900 grep -q '^[[:blank:]]*global[[:blank:]]*{' $CONFIGFILE
12901 have_global=$?
12902
12903 if [ "$have_global" = "1" ]
12904 then
12905 echo "global keys but no 'global {' found, can't edit file"
12906 exit 13
12907 fi
12908fi
12909
12910if [ "$LOCKING_TYPE" = "2" ] && [ -z "$LOCKINGLIBDIR" ] && [ "$have_dir" = "1" ]; then
12911 echo "no library_dir specified in $CONFIGFILE"
12912 exit 16
12913fi
12914
12915# So if we don't have "global {" we need to create one and
12916# populate it
12917
12918if [ "$have_global" = "1" ]
12919then
12920 if [ -z "$LOCKING_TYPE" ]; then
12921 LOCKING_TYPE=1
12922 fi
12923 if [ "$LOCKING_TYPE" = "2" ]; then
12924 cat $CONFIGFILE - <<EOF > $TMPFILE
12925global {
12926 # Enable locking for cluster LVM
12927 locking_type = $LOCKING_TYPE
12928 library_dir = "$LOCKINGLIBDIR"
12929 locking_library = "$LOCKINGLIB"
12930}
12931EOF
12932 fi # if we aren't setting cluster locking, we don't need to create a global section
12933
12934 if [ $? != 0 ]
12935 then
12936 echo "failed to create temporary config file, $CONFIGFILE not updated"
12937 exit 14
12938 fi
12939else
12940 #
12941 # We have a "global {" section, so add or replace the
12942 # locking entries as appropriate
12943 #
12944
12945 if [ -n "$LOCKING_TYPE" ]; then
12946 if [ "$have_type" = "0" ]
12947 then
12948 SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
12949 else
12950 SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
12951 fi
12952 fi
12953
12954 if [ -n "$LOCKINGLIBDIR" ]; then
12955 if [ "$have_dir" = "0" ]
12956 then
12957 SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$LOCKINGLIBDIR\"'g"
12958 else
12959 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$LOCKINGLIBDIR\""
12960 fi
12961
12962 if [ "$have_library" = "0" ]
12963 then
12964 SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LOCKINGLIB\"/g"
12965 else
12966 SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LOCKINGLIB\""
12967 fi
12968 fi
12969
12970 if [ "$LOCKING_TYPE" = "1" ]; then
12971 # if we're not using cluster locking, remove the library dir and locking library name
12972 if [ "$have_dir" = "0" ]
12973 then
12974 SEDCMD="${SEDCMD}\n/^[[:blank:]]*library_dir[[:blank:]]*=.*/d"
12975 fi
12976
12977 if [ "$have_library" = "0" ]
12978 then
12979 SEDCMD="${SEDCMD}\n/^[[:blank:]]*locking_library[[:blank:]]*=.*/d"
12980 fi
12981 fi
12982
12983 echo -e $SEDCMD > $SCRIPTFILE
12984 sed <$CONFIGFILE >$TMPFILE -f $SCRIPTFILE
12985 if [ $? != 0 ]
12986 then
12987 echo "sed failed, $CONFIGFILE not updated"
12988 exit 15
12989 fi
12990fi
12991
12992# Now we have a suitably editted config file in a temp place,
12993# backup the original and copy our new one into place.
12994
12995cp $CONFIGFILE $CONFIGFILE.lvmconfold
12996if [ $? != 0 ]
12997 then
12998 echo "failed to backup old config file, $CONFIGFILE not updated"
12999 exit 2
13000fi
13001
13002cp $TMPFILE $CONFIGFILE
13003if [ $? != 0 ]
13004 then
13005 echo "failed to copy new config file into place, check $CONFIGFILE is still OK"
13006 exit 3
13007fi
13008
13009rm -f $SCRIPTFILE $TMPFILE
13010\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_monitoring_init_red_hat.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005763\013062740170\0024737\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
13011#
13012# Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
13013#
13014# This copyrighted material is made available to anyone wishing to use,
13015# modify, copy, or redistribute it subject to the terms and conditions
13016# of the GNU General Public License v.2.
13017#
13018# You should have received a copy of the GNU General Public License
13019# along with this program; if not, write to the Free Software Foundation,
13020# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
13021#
13022# This file is part of LVM2.
13023# It is required for the proper handling of failures of LVM2 mirror
13024# devices that were created using the -m option of lvcreate.
13025#
13026#
13027# chkconfig: 12345 02 99
13028# description: Starts and stops dmeventd monitoring for lvm2
13029#
13030# For Red-Hat-based distributions such as Fedora, RHEL, CentOS.
13031#
13032### BEGIN INIT INFO
13033# Provides: lvm2-monitor
13034# Required-Start: $local_fs
13035# Required-Stop: $local_fs
13036# Default-Start: 1 2 3 4 5
13037# Default-Stop: 0 6
13038# Short-Description: Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
13039### END INIT INFO
13040
13041. /etc/init.d/functions
13042
13043DAEMON=lvm2-monitor
13044DMEVENTD_DAEMON=dmeventd
13045
13046exec_prefix=@exec_prefix@
13047sbindir=@sbindir@
13048
13049VGCHANGE=${sbindir}/vgchange
13050VGS=${sbindir}/vgs
13051LVS=${sbindir}/lvs
13052
13053LOCK_FILE="/var/lock/subsys/$DAEMON"
13054PID_FILE="@DMEVENTD_PIDFILE@"
13055
13056WARN=1
13057export LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1
13058
13059rh_status() {
13060 status -p $PID_FILE $DMEVENTD_DAEMON
13061}
13062
13063rh_status_q() {
13064 rh_status >/dev/null 2>&1
13065}
13066start()
13067{
13068 ret=0
13069 # TODO do we want to separate out already active groups only?
13070 VGSLIST=`$VGS --noheadings -o name --ignoreskippedcluster --config 'log{command_names=0 prefix=" "}' 2> /dev/null`
13071 for vg in $VGSLIST
13072 do
13073 action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y --poll y --ignoreskippedcluster --config 'log{command_names=0 prefix=" "}' $vg || ret=$?
13074 done
13075
13076 return $ret
13077}
13078
13079
13080stop()
13081{
13082 ret=0
13083 # TODO do we want to separate out already active groups only?
13084 if test "$WARN" = "1"; then
13085 echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
13086 return 1
13087 fi
13088 VGSLIST=`$VGS --noheadings -o name --ignoreskippedcluster --config 'log{command_names=0 prefix=" "}' 2> /dev/null`
13089 for vg in $VGSLIST
13090 do
13091 action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n --ignoreskippedcluster --config 'log{command_names=0 prefix=" "}' $vg || ret=$?
13092 done
13093 return $ret
13094}
13095
13096rtrn=1
13097
13098# See how we were called.
13099case "$1" in
13100 start)
13101 rh_status_q && exit 0
13102 start
13103 rtrn=$?
13104 [ $rtrn = 0 ] && touch $LOCK_FILE
13105 ;;
13106
13107 force-stop)
13108 rh_status_q || exit 0
13109 WARN=0
13110 stop
13111 rtrn=$?
13112 [ $rtrn = 0 ] && rm -f $LOCK_FILE
13113 ;;
13114
13115 stop)
13116 rh_status_q || exit 0
13117 test "$runlevel" = "0" && WARN=0
13118 test "$runlevel" = "6" && WARN=0
13119 stop
13120 rtrn=$?
13121 [ $rtrn = 0 ] && rm -f $LOCK_FILE
13122 ;;
13123
13124 restart)
13125 WARN=0
13126 if stop
13127 then
13128 start
13129 fi
13130 rtrn=$?
13131 ;;
13132
13133 status)
13134 rh_status
13135 rtrn=$?
13136 [ $rtrn = 0 ] && $LVS -S 'seg_monitor=monitored' -o lv_full_name,seg_monitor
13137 ;;
13138
13139 *)
13140 echo $"Usage: $0 {start|stop|restart|status|force-stop}"
13141 ;;
13142esac
13143
13144exit $rtrn
13145\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/com.redhat.lvmdbus1.conf\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000722\013062740170\0023166\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<?xml version="1.0"?> <!--*-nxml-*-->
13146<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
13147 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
13148<busconfig>
13149 <policy user="root">
13150 <allow own_prefix="com.redhat.lvmdbus1"/>
13151 <allow send_destination="com.redhat.lvmdbus1"/>
13152 </policy>
13153 <policy context="default">
13154 <deny own_prefix="com.redhat.lvmdbus1"/>
13155 <deny send_destination="com.redhat.lvmdbus1"/>
13156 </policy>
13157</busconfig>
13158\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvmdump.sh.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000024270\013062740170\0021170\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
13159# We use some bash-isms (getopts?)
13160
13161# Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved.
13162#
13163# This file is part of LVM2.
13164#
13165# This copyrighted material is made available to anyone wishing to use,
13166# modify, copy, or redistribute it subject to the terms and conditions
13167# of the GNU General Public License v.2.
13168#
13169# You should have received a copy of the GNU General Public License
13170# along with this program; if not, write to the Free Software Foundation,
13171# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
13172
13173# lvm_dump: This script is used to collect pertinent information for
13174# the debugging of lvm issues.
13175
13176# following external commands are used throughout the script
13177# echo and test are internal in bash at least
13178MKDIR=mkdir # need -p
13179TAR=tar # need czf
13180RM=rm # need -rf
13181CP=cp
13182TAIL=tail # we need -n
13183LS=ls # need -la
13184PS=ps # need alx
13185SED=sed
13186DD=dd
13187CUT=cut
13188GREP=grep
13189DATE=date
13190BASENAME=basename
13191UDEVADM=udevadm
13192UNAME=uname
13193TR=tr
13194SOCAT=socat # either socat or nc is needed for dumping lvmetad state
13195NC=nc
13196
13197if test "@ODIRECT@" = yes; then
13198 DDFLAGS='iflag=direct oflag=direct'
13199else
13200 DDFLAGS=
13201fi
13202
13203# user may override lvm and dmsetup location by setting LVM_BINARY
13204# and DMSETUP_BINARY respectively
13205LVM=${LVM_BINARY-lvm}
13206DMSETUP=${DMSETUP_BINARY-dmsetup}
13207LVMETAD_SOCKET=${LVM_LVMETAD_SOCKET-/var/run/lvm/lvmetad.socket}
13208LVMPOLLD_SOCKET=${LVM_LVMPOLLD_SOCKET-/var/run/lvm/lvmpolld.socket}
13209
13210die() {
13211 code=$1; shift
13212 echo "$@" 1>&2
13213 exit $code
13214}
13215
13216"$LVM" version >& /dev/null || die 2 "Could not run lvm binary '$LVM'"
13217"$DMSETUP" version >& /dev/null || DMSETUP=:
13218
13219function usage {
13220 echo "$0 [options]"
13221 echo " -h print this message"
13222 echo " -a advanced collection - warning: if lvm is already hung,"
13223 echo " then this script may hang as well if -a is used"
13224 echo " -c if running clvmd, gather cluster data as well"
13225 echo " -d <directory> dump into a directory instead of tarball"
13226 echo " -l gather lvmetad state if running"
13227 echo " -p gather lvmpolld state if running"
13228 echo " -m gather LVM metadata from the PVs"
13229 echo " -s gather system info and context"
13230 echo " -u gather udev info and context"
13231 echo ""
13232
13233 exit 1
13234}
13235
13236advanced=0
13237clustered=0
13238metadata=0
13239sysreport=0
13240udev=0
13241while getopts :acd:hlpmus opt; do
13242 case $opt in
13243 a) advanced=1 ;;
13244 c) clustered=1 ;;
13245 d) userdir=$OPTARG ;;
13246 h) usage ;;
13247 l) lvmetad=1 ;;
13248 p) lvmpolld=1 ;;
13249 m) metadata=1 ;;
13250 s) sysreport=1 ;;
13251 u) udev=1 ;;
13252 :) echo "$0: $OPTARG requires a value:"; usage ;;
13253 \?) echo "$0: unknown option $OPTARG"; usage ;;
13254 *) usage ;;
13255 esac
13256done
13257
13258NOW=`$DATE -u +%G%m%d%k%M%S | $TR -d ' '`
13259if test -n "$userdir"; then
13260 dir="$userdir"
13261else
13262 dirbase="lvmdump-$HOSTNAME-$NOW"
13263 dir="$HOME/$dirbase"
13264fi
13265
13266if test -d $dir ; then
13267 (shopt -s nullglob dotglob; test -r $dir -a -w $dir -a -x $dir && cd $dir && files=(*) && ((! ${#files[@]}))) || \
13268 die 5 "Fatal: directory $dir already exists and is not empty or inaccessible"
13269else
13270 test -e $dir && die 3 "Fatal: $dir already exists"
13271 $MKDIR -p $dir || die 4 "Fatal: could not create $dir"
13272fi
13273
13274log="$dir/lvmdump.log"
13275
13276myecho() {
13277 echo "$@"
13278 echo "$@" >> "$log"
13279}
13280
13281log() {
13282 echo "$@" >> "$log"
13283 eval "$@"
13284}
13285
13286warnings() {
13287 if test "$UID" != "0" && test "$EUID" != "0"; then
13288 myecho "WARNING! Running as non-privileged user, dump is likely incomplete!"
13289 elif test "$DMSETUP" = ":"; then
13290 myecho "WARNING! Could not run dmsetup, dump is likely incomplete."
13291 fi
13292}
13293
13294warnings
13295
13296myecho "Creating dump directory: $dir"
13297echo " "
13298
13299if (( $advanced )); then
13300 myecho "Gathering LVM volume info..."
13301
13302 myecho " vgscan..."
13303 log "\"$LVM\" vgscan -vvvv >> \"$dir/vgscan\" 2>&1"
13304
13305 myecho " pvscan..."
13306 log "\"$LVM\" pvscan -v >> \"$dir/pvscan\" 2>> \"$log\""
13307
13308 myecho " lvs..."
13309 log "\"$LVM\" lvs -a -H -o +devices,kernel_major,kernel_minor >> \"$dir/lvs\" 2>> \"$log\""
13310
13311 myecho " pvs..."
13312 log "\"$LVM\" pvs -a -o +major,minor -v >> \"$dir/pvs\" 2>> \"$log\""
13313
13314 myecho " vgs..."
13315 log "\"$LVM\" vgs -v >> \"$dir/vgs\" 2>> \"$log\""
13316fi
13317
13318if (( $clustered )); then
13319 myecho "Gathering cluster info..."
13320
13321 {
13322 for i in nodes status services; do
13323 cap_i=$(echo $i|tr a-z A-Z)
13324 printf "$cap_i:\n----------------------------------\n"
13325 log "cman_tool $i 2>> \"$log\""
13326 echo
13327 done
13328
13329 echo "LOCKS:"
13330 echo "----------------------------------"
13331 if [ -f /proc/cluster/dlm_locks ]
13332 then
13333 echo clvmd > /proc/cluster/dlm_locks
13334 cat /proc/cluster/dlm_locks
13335 echo
13336 echo "RESOURCE DIR:"
13337 cat /proc/cluster/dlm_dir
13338 echo
13339 echo "DEBUG LOG:"
13340 cat /proc/cluster/dlm_debug
13341 echo
13342 fi
13343 if [ -f /debug/dlm/clvmd ]
13344 then
13345 cat /debug/dlm/clvmd
13346 echo
13347 echo "WAITERS:"
13348 cat /debug/dlm/clvmd_waiters
13349 echo
13350 echo "MASTER:"
13351 cat /debug/dlm/clvmd_master
13352 fi
13353 } >> $dir/cluster_info
13354fi
13355
13356myecho "Gathering LVM & device-mapper version info..."
13357echo "LVM VERSION:" >> "$dir/versions"
13358"$LVM" lvs --version >> "$dir/versions" 2>> "$log"
13359echo "DEVICE MAPPER VERSION:" >> "$dir/versions"
13360"$DMSETUP" --version >> "$dir/versions" 2>> "$log"
13361echo "KERNEL VERSION:" >> "$dir/versions"
13362"$UNAME" -a >> "$dir/versions" 2>> "$log"
13363echo "DM TARGETS VERSIONS:" >> "$dir/versions"
13364"$DMSETUP" targets >> "$dir/versions" 2>> "$log"
13365
13366myecho "Gathering dmsetup info..."
13367log "\"$DMSETUP\" info -c >> \"$dir/dmsetup_info\" 2>> \"$log\""
13368log "\"$DMSETUP\" table >> \"$dir/dmsetup_table\" 2>> \"$log\""
13369log "\"$DMSETUP\" status >> \"$dir/dmsetup_status\" 2>> \"$log\""
13370
13371# cat as workaround to avoid tty ioctl (selinux)
13372log "\"$DMSETUP\" ls --tree 2>> \"$log\" | cat >> \"$dir/dmsetup_ls_tree\""
13373
13374myecho "Gathering process info..."
13375log "$PS alx >> \"$dir/ps_info\" 2>> \"$log\""
13376
13377myecho "Gathering console messages..."
13378log "$TAIL -n 75 /var/log/messages >> \"$dir/messages\" 2>> \"$log\""
13379
13380myecho "Gathering /etc/lvm info..."
13381log "$LS -laR /etc/lvm >> \"$dir/etc_lvm_listing\" 2>> \"$log\""
13382log "$CP -RL --preserve=all /etc/lvm \"$dir/lvm\" 2>> \"$log\""
13383log "$LVM dumpconfig --type diff --file \"$dir/config_diff\" 2>> \"$log\""
13384log "$LVM dumpconfig --type missing --file \"$dir/config_missing\" 2>> \"$log\""
13385
13386myecho "Gathering /dev listing..."
13387log "$LS -laR /dev >> \"$dir/dev_listing\" 2>> \"$log\""
13388
13389myecho "Gathering /sys/block listing..."
13390log "$LS -laR /sys/block >> \"$dir/sysblock_listing\" 2>> \"$log\""
13391log "$LS -laR /sys/devices/virtual/block >> \"$dir/sysblock_listing\" 2>> \"$log\""
13392
13393if (( $metadata )); then
13394 myecho "Gathering LVM metadata from Physical Volumes..."
13395
13396 log "$MKDIR -p \"$dir/metadata\""
13397
13398 pvs="$("$LVM" pvs --separator , --noheadings --units s --nosuffix -o \
13399 name,pe_start 2>> "$log" | $SED -e 's/^ *//')"
13400 for line in $pvs
13401 do
13402 test -z "$line" && continue
13403 pv="$(echo $line | $CUT -d, -f1)"
13404 pe_start="$(echo $line | $CUT -d, -f2)"
13405 name="$($BASENAME "$pv")"
13406 myecho " $pv"
13407 log "$DD if=$pv \"of=$dir/metadata/$name\" $DDFLAGS bs=512 count=$pe_start 2>> \"$log\""
13408 done
13409fi
13410
13411if (( $sysreport )); then
13412 myecho "Gathering system info..."
13413
13414 sysreport_dir="$dir/sysreport"
13415 log_lines=10000
13416
13417 SYSTEMCTL=$(which systemctl 2>> $log)
13418 JOURNALCTL=$(which journalctl 2>> $log)
13419 LSBLK=$(which lsblk 2>> $log)
13420
13421 log "$MKDIR -p \"$sysreport_dir\""
13422
13423 if test -z "LSBLK"; then
13424 myecho "WARNING: lsblk not found"
13425 else
13426 if $LSBLK --help | $GREP -- --output-all >/dev/null; then
13427 log "$LSBLK -O >> \"$sysreport_dir/lsblk_O\""
13428 else
13429 log "$LSBLK >> \"$sysreport_dir/lsblk\""
13430 fi
13431 if $LSBLK --help | $GREP -- --inverse >/dev/null; then
13432 log "$LSBLK -s >> \"$sysreport_dir/lsblk_s\""
13433 fi
13434 fi
13435
13436 if test -z "$SYSTEMCTL"; then
13437 myecho "WARNING: systemctl not found"
13438 elif test -z "$JOURNALCTL"; then
13439 myecho "WARNING: journalctl not found"
13440 else
13441 log "$JOURNALCTL -b --no-pager -o short-precise > \"$sysreport_dir/journal_content\" 2>> \"$log\""
13442 log "$SYSTEMCTL status -l --no-pager -n $log_lines -o short-precise dm-event.socket dm-event.service \
13443 lvm2-monitor.service \
13444 lvm2-lvmetad.socket lvm2-lvmetad.service \
13445 lvm2-lvmpolld.socket lvm2-lvmpolld.service \
13446 lvm2-cluster-activation.service \
13447 lvm2-clvmd.service \
13448 lvm2-cmirrord.service \
13449 lvm2-activation-early.service \
13450 lvm2-activation.service \
13451 lvm2-activation-net.service \
13452 > \"$sysreport_dir/systemd_lvm2_services_status\" 2>> \"$log\""
13453 log "$SYSTEMCTL list-units -l -a --no-legend --no-pager > \"$sysreport_dir/systemd_unit_list\" 2>> \"$log\""
13454 for unit in $(cat $sysreport_dir/systemd_unit_list | $GREP lvm2-pvscan | cut -d " " -f 1); do
13455 log "$SYSTEMCTL status -l --no-pager -n $log_lines -o short-precise $unit >> \"$sysreport_dir/systemd_lvm2_pvscan_service_status\""
13456 done
13457 fi
13458fi
13459
13460if (( $udev )); then
13461 myecho "Gathering udev info..."
13462
13463 udev_dir="$dir/udev"
13464
13465 log "$MKDIR -p \"$udev_dir\""
13466 log "$UDEVADM info --version >> \"$udev_dir/version\" 2>> \"$log\""
13467 log "$UDEVADM info --export-db >> \"$udev_dir/db\" 2>> \"$log\""
13468 log "$CP -a /etc/udev/udev.conf \"$udev_dir/conf\" 2>> \"$log\""
13469 log "$LS -la /lib/udev >> \"$udev_dir/lib_dir\" 2>> \"$log\""
13470 log "$CP -RL --preserve=all /etc/udev/rules.d \"$udev_dir/rules_etc\" 2>> \"$log\""
13471 log "$CP -RL --preserve=all /lib/udev/rules.d \"$udev_dir/rules_lib\" 2>> \"$log\""
13472fi
13473
13474if (( $lvmetad )); then
13475 (echo 'request="dump"'; echo '##') | {
13476 if type -p $SOCAT >& /dev/null; then
13477 echo "$SOCAT unix-connect:$LVMETAD_SOCKET -" >> "$log"
13478 $SOCAT "unix-connect:$LVMETAD_SOCKET" - 2>> "$log"
13479 elif echo | $NC -U "$LVMETAD_SOCKET"; then
13480 echo "$NC -U $LVMETAD_SOCKET" >> "$log"
13481 $NC -U "$LVMETAD_SOCKET" 2>> "$log"
13482 else
13483 myecho "WARNING: Neither socat nor nc -U seems to be available." 1>&2
13484 echo "# DUMP FAILED"
13485 return 1
13486 fi
13487 } > "$dir/lvmetad.txt"
13488fi
13489
13490if (( $lvmpolld )); then
13491 (echo 'request="dump"'; echo '##') | {
13492 if type -p $SOCAT >& /dev/null; then
13493 echo "$SOCAT unix-connect:$LVMPOLLD_SOCKET -" >> "$log"
13494 $SOCAT "unix-connect:$LVMPOLLD_SOCKET" - 2>> "$log"
13495 elif echo | $NC -U "$LVMPOLLD_SOCKET"; then
13496 echo "$NC -U $LVMPOLLD_SOCKET" >> "$log"
13497 $NC -U "$LVMPOLLD_SOCKET" 2>> "$log"
13498 else
13499 myecho "WARNING: Neither socat nor nc -U seems to be available." 1>&2
13500 echo "# DUMP FAILED"
13501 return 1
13502 fi
13503 } > "$dir/lvmpolld.txt"
13504fi
13505
13506if test -z "$userdir"; then
13507 lvm_dump="$dirbase.tgz"
13508 myecho "Creating report tarball in $HOME/$lvm_dump..."
13509fi
13510
13511warnings
13512
13513if test -z "$userdir"; then
13514 cd "$HOME"
13515 "$TAR" czf "$lvm_dump" "$dirbase" 2>/dev/null
13516 "$RM" -rf "$dir"
13517fi
13518
13519exit 0
13520\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/dm_event_systemd_red_hat.socket.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000430\013062740170\0025411\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
13521Description=Device-mapper event daemon FIFOs
13522Documentation=man:dmeventd(8)
13523DefaultDependencies=no
13524
13525[Socket]
13526ListenFIFO=@DEFAULT_DM_RUN_DIR@/dmeventd-server
13527ListenFIFO=@DEFAULT_DM_RUN_DIR@/dmeventd-client
13528SocketMode=0600
13529RemoveOnStop=true
13530
13531[Install]
13532WantedBy=sockets.target
13533\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmetad_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000536\013062740170\0026363\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
13534Description=LVM2 metadata daemon
13535Documentation=man:lvmetad(8)
13536Requires=lvm2-lvmetad.socket
13537After=lvm2-lvmetad.socket
13538DefaultDependencies=no
13539Conflicts=shutdown.target
13540
13541[Service]
13542Type=simple
13543NonBlocking=true
13544ExecStart=@sbindir@/lvmetad -f
13545Environment=SD_ACTIVATION=1
13546Restart=on-abort
13547PIDFile=@LVMETAD_PIDFILE@
13548
13549[Install]
13550WantedBy=sysinit.target
13551\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_cmirrord_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000526\013062740170\0026547\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
13552Description=Clustered LVM mirror log daemon
13553Documentation=man:cmirrord(8)
13554Requires=corosync.service
13555After=corosync.service
13556Before=remote-fs-pre.target
13557DefaultDependencies=no
13558Conflicts=shutdown.target
13559
13560[Service]
13561Type=forking
13562ExecStart=@sbindir@/cmirrord
13563PIDFile=@CMIRRORD_PIDFILE@
13564Restart=on-abort
13565
13566[Install]
13567WantedBy=multi-user.target
13568\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_activation_generator_systemd_red_hat.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013454\013062740170\0027316\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
13569 * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
13570 *
13571 * This file is part of the device-mapper userspace tools.
13572 *
13573 * This copyrighted material is made available to anyone wishing to use,
13574 * modify, copy, or redistribute it subject to the terms and conditions
13575 * of the GNU General Public License v.2.
13576 *
13577 * You should have received a copy of the GNU General Public License
13578 * along with this program; if not, write to the Free Software Foundation,
13579 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
13580*/
13581
13582#include <stdio.h>
13583#include <unistd.h>
13584#include <errno.h>
13585#include <stdarg.h>
13586#include <syslog.h>
13587#include <sys/types.h>
13588#include <sys/stat.h>
13589#include <fcntl.h>
13590#include <limits.h> /* For PATH_MAX for musl libc */
13591#include "lvm2app.h"
13592#include "configure.h" /* for LVM_PATH */
13593
13594#define KMSG_DEV_PATH "/dev/kmsg"
13595#define LVM_CONF_USE_LVMETAD "global/use_lvmetad"
13596#define LVM_CONF_USE_LVMPOLLD "global/use_lvmpolld"
13597
13598#define UNIT_TARGET_LOCAL_FS "local-fs-pre.target"
13599#define UNIT_TARGET_REMOTE_FS "remote-fs-pre.target"
13600
13601static char unit_path[PATH_MAX];
13602static char target_path[PATH_MAX];
13603static char message[PATH_MAX + 3]; /* +3 for '<n>' where n is the log level */
13604static int kmsg_fd = -1;
13605
13606enum {
13607 UNIT_EARLY,
13608 UNIT_MAIN,
13609 UNIT_NET
13610};
13611
13612static const char *unit_names[] = {
13613 [UNIT_EARLY] = "lvm2-activation-early.service",
13614 [UNIT_MAIN] = "lvm2-activation.service",
13615 [UNIT_NET] = "lvm2-activation-net.service"
13616};
13617
13618__attribute__ ((format(printf, 2, 3)))
13619static void kmsg(int log_level, const char *format, ...)
13620{
13621 va_list ap;
13622 int n;
13623
13624 snprintf(message, 4, "<%d>", log_level);
13625
13626 va_start(ap, format);
13627 n = vsnprintf(message + 3, PATH_MAX, format, ap);
13628 va_end(ap);
13629
13630 if (kmsg_fd < 0 || (n < 0 || ((unsigned) n + 1 > PATH_MAX)))
13631 return;
13632
13633 /* The n+4: +3 for "<n>" prefix and +1 for '\0' suffix */
13634 if (write(kmsg_fd, message, n + 4)) { /* Ignore result code */; }
13635}
13636
13637static void lvm_get_use_lvmetad_and_lvmpolld(int *use_lvmetad, int *use_lvmpolld)
13638{
13639 *use_lvmetad = *use_lvmpolld = 0;
13640
13641 *use_lvmetad = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMETAD, 0);
13642 *use_lvmpolld = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMPOLLD, 0);
13643}
13644
13645static int register_unit_with_target(const char *dir, const char *unit, const char *target)
13646{
13647 int r = 1;
13648
13649 if (dm_snprintf(target_path, PATH_MAX, "%s/%s.wants", dir, target) < 0) {
13650 r = 0; goto out;
13651 }
13652 (void) dm_prepare_selinux_context(target_path, S_IFDIR);
13653 if (mkdir(target_path, 0755) < 0 && errno != EEXIST) {
13654 kmsg(LOG_ERR, "LVM: Failed to create target directory %s: %m.\n", target_path);
13655 r = 0; goto out;
13656 }
13657
13658 if (dm_snprintf(target_path, PATH_MAX, "%s/%s.wants/%s", dir, target, unit) < 0) {
13659 r = 0; goto out;
13660 }
13661 (void) dm_prepare_selinux_context(target_path, S_IFLNK);
13662 if (symlink(unit_path, target_path) < 0) {
13663 kmsg(LOG_ERR, "LVM: Failed to create symlink for unit %s: %m.\n", unit);
13664 r = 0;
13665 }
13666out:
13667 dm_prepare_selinux_context(NULL, 0);
13668 return r;
13669}
13670
13671static int generate_unit(const char *dir, int unit, int sysinit_needed)
13672{
13673 FILE *f;
13674 const char *unit_name = unit_names[unit];
13675 const char *target_name = unit == UNIT_NET ? UNIT_TARGET_REMOTE_FS : UNIT_TARGET_LOCAL_FS;
13676
13677 if (dm_snprintf(unit_path, PATH_MAX, "%s/%s", dir, unit_name) < 0)
13678 return 0;
13679
13680 if (!(f = fopen(unit_path, "wxe"))) {
13681 kmsg(LOG_ERR, "LVM: Failed to create unit file %s: %m.\n", unit_name);
13682 return 0;
13683 }
13684
13685 fputs("# Automatically generated by lvm2-activation-generator.\n"
13686 "#\n"
13687 "# This unit is responsible for direct activation of LVM2 logical volumes\n"
13688 "# if lvmetad daemon is not used (global/use_lvmetad=0 lvm.conf setting),\n"
13689 "# hence volume autoactivation is not applicable.\n"
13690 "# Direct LVM2 activation requires udev to be settled!\n\n"
13691 "[Unit]\n"
13692 "Description=Activation of LVM2 logical volumes\n"
13693 "Documentation=man:lvm2-activation-generator(8)\n"
13694 "SourcePath=/etc/lvm/lvm.conf\n"
13695 "DefaultDependencies=no\n", f);
13696
13697 if (unit == UNIT_NET) {
13698 fprintf(f, "After=%s iscsi.service fcoe.service\n"
13699 "Before=remote-fs-pre.target shutdown.target\n\n"
13700 "[Service]\n"
13701 "ExecStartPre=/bin/udevadm settle\n", unit_names[UNIT_MAIN]);
13702 } else {
13703 if (unit == UNIT_EARLY) {
13704 fputs("After=systemd-udev-settle.service\n"
13705 "Before=cryptsetup.target\n", f);
13706 } else
13707 fprintf(f, "After=%s cryptsetup.target\n", unit_names[UNIT_EARLY]);
13708
13709 fputs("Before=local-fs-pre.target shutdown.target\n"
13710 "Wants=systemd-udev-settle.service\n\n"
13711 "[Service]\n", f);
13712 }
13713
13714 fputs("ExecStart=" LVM_PATH " vgchange -aay --ignoreskippedcluster", f);
13715 if (sysinit_needed)
13716 fputs (" --sysinit", f);
13717 fputs("\nType=oneshot\n", f);
13718
13719 if (fclose(f) < 0) {
13720 kmsg(LOG_ERR, "LVM: Failed to write unit file %s: %m.\n", unit_name);
13721 return 0;
13722 }
13723
13724 if (!register_unit_with_target(dir, unit_name, target_name)) {
13725 kmsg(LOG_ERR, "LVM: Failed to register unit %s with target %s.\n", unit_name, target_name);
13726 return 0;
13727 }
13728
13729 return 1;
13730}
13731
13732int main(int argc, char *argv[])
13733{
13734 int use_lvmetad, use_lvmpolld, sysinit_needed;
13735 const char *dir;
13736 int r = EXIT_SUCCESS;
13737 mode_t old_mask;
13738
13739 kmsg_fd = open(KMSG_DEV_PATH, O_WRONLY|O_NOCTTY);
13740
13741 if (argc != 4) {
13742 kmsg(LOG_ERR, "LVM: Incorrect number of arguments for activation generator.\n");
13743 r = EXIT_FAILURE; goto out;
13744 }
13745
13746 /* If lvmetad used, rely on autoactivation instead of direct activation. */
13747 lvm_get_use_lvmetad_and_lvmpolld(&use_lvmetad, &use_lvmpolld);
13748 if (use_lvmetad)
13749 goto out;
13750
13751 dir = argv[1];
13752
13753 /* mark lvm2-activation.*.service as world-accessible */
13754 old_mask = umask(0022);
13755
13756 sysinit_needed = !use_lvmpolld;
13757
13758 if (!generate_unit(dir, UNIT_EARLY, sysinit_needed) ||
13759 !generate_unit(dir, UNIT_MAIN, sysinit_needed) ||
13760 !generate_unit(dir, UNIT_NET, sysinit_needed))
13761 r = EXIT_FAILURE;
13762 umask(old_mask);
13763out:
13764 if (r)
13765 kmsg(LOG_ERR, "LVM: Activation generator failed.\n");
13766 if (kmsg_fd != -1)
13767 (void) close(kmsg_fd);
13768 return r;
13769}
13770\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000014243\013062740170\0020607\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
13771# Copyright (C) 2006-2015 Red Hat, Inc. All rights reserved.
13772#
13773# This file is part of LVM2.
13774#
13775# This copyrighted material is made available to anyone wishing to use,
13776# modify, copy, or redistribute it subject to the terms and conditions
13777# of the GNU General Public License v.2.
13778#
13779# You should have received a copy of the GNU General Public License
13780# along with this program; if not, write to the Free Software Foundation,
13781# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
13782
13783srcdir = @srcdir@
13784top_srcdir = @top_srcdir@
13785top_builddir = @top_builddir@
13786
13787ifeq ("@APPLIB@", "yes")
13788 SOURCES = lvm2_activation_generator_systemd_red_hat.c
13789 TARGETS = lvm2_activation_generator_systemd_red_hat
13790endif
13791
13792include $(top_builddir)/make.tmpl
13793
13794ifeq ("@APPLIB@", "yes")
13795 DEPLIBS += $(top_builddir)/liblvm/liblvm2app.so $(top_builddir)/libdm/libdevmapper.so
13796 LDFLAGS += -L$(top_builddir)/liblvm
13797ifeq ("@DMEVENTD@", "yes")
13798 LDFLAGS += -Wl,-rpath-link,$(top_builddir)/daemons/dmeventd
13799endif
13800 LVMLIBS = @LVM2APP_LIB@ -ldevmapper
13801endif
13802
13803LVM_SCRIPTS = lvmdump.sh lvmconf.sh
13804DM_SCRIPTS =
13805
13806ifeq ("@FSADM@", "yes")
13807 LVM_SCRIPTS += fsadm.sh
13808endif
13809
13810ifeq ("@BLKDEACTIVATE@", "yes")
13811 DM_SCRIPTS += blkdeactivate.sh
13812endif
13813
13814OCF_SCRIPTS =
13815ifeq ("@OCF@", "yes")
13816 OCF_SCRIPTS += VolumeGroup.ocf
13817endif
13818
13819vpath %.sh $(srcdir)
13820vpath %.ocf $(srcdir)
13821
13822%_install: %.sh
13823 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(basename $(<F))
13824
13825%_install: %.ocf
13826 $(INSTALL_DIR) $(ocf_scriptdir)
13827 $(INSTALL_SCRIPT) $< $(ocf_scriptdir)/$(basename $(<F))
13828
13829install_lvm2: $(LVM_SCRIPTS:.sh=_install)
13830install_device-mapper: $(DM_SCRIPTS:.sh=_install)
13831
13832install_ocf: $(OCF_SCRIPTS:.ocf=_install)
13833
13834install: install_lvm2 install_ocf install_device-mapper
13835
13836# FIXME Customise for other distributions
13837install_initscripts:
13838 $(INSTALL_DIR) $(initdir)
13839ifeq ("@BUILD_DMEVENTD@", "yes")
13840 $(INSTALL_SCRIPT) lvm2_monitoring_init_red_hat $(initdir)/lvm2-monitor
13841endif
13842ifeq ("@BUILD_LVMETAD@", "yes")
13843 $(INSTALL_SCRIPT) lvm2_lvmetad_init_red_hat $(initdir)/lvm2-lvmetad
13844endif
13845ifeq ("@BUILD_LVMPOLLD@", "yes")
13846 $(INSTALL_SCRIPT) lvm2_lvmpolld_init_red_hat $(initdir)/lvm2-lvmpolld
13847endif
13848ifneq ("@CLVMD@", "none")
13849 $(INSTALL_SCRIPT) clvmd_init_red_hat $(initdir)/clvmd
13850endif
13851ifeq ("@BUILD_CMIRRORD@", "yes")
13852 $(INSTALL_SCRIPT) cmirrord_init_red_hat $(initdir)/cmirrord
13853endif
13854ifeq ("@BLKDEACTIVATE@", "yes")
13855 $(INSTALL_SCRIPT) blk_availability_init_red_hat $(initdir)/blk-availability
13856endif
13857
13858CFLAGS_lvm2_activation_generator_systemd_red_hat.o += $(EXTRA_EXEC_CFLAGS)
13859
13860lvm2_activation_generator_systemd_red_hat: $(OBJECTS) $(DEPLIBS)
13861 $(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(LVMLIBS)
13862
13863install_systemd_generators:
13864 $(INSTALL_DIR) $(systemd_generator_dir)
13865ifeq ("@APPLIB@", "yes")
13866 $(INSTALL_PROGRAM) lvm2_activation_generator_systemd_red_hat $(systemd_generator_dir)/lvm2-activation-generator
13867else
13868 @echo "WARNING: LVM2 activation systemd generator not installed." \
13869 "It requires the LVM2 application library to be built as well."
13870endif
13871
13872install_systemd_units: install_dbus_service
13873 $(INSTALL_DIR) $(systemd_unit_dir)
13874ifeq ("@BUILD_DMEVENTD@", "yes")
13875 $(INSTALL_DATA) dm_event_systemd_red_hat.socket $(systemd_unit_dir)/dm-event.socket
13876 $(INSTALL_DATA) dm_event_systemd_red_hat.service $(systemd_unit_dir)/dm-event.service
13877 $(INSTALL_DATA) lvm2_monitoring_systemd_red_hat.service $(systemd_unit_dir)/lvm2-monitor.service
13878endif
13879ifeq ("@BLKDEACTIVATE@", "yes")
13880 $(INSTALL_DATA) blk_availability_systemd_red_hat.service $(systemd_unit_dir)/blk-availability.service
13881endif
13882ifeq ("@BUILD_LVMETAD@", "yes")
13883 $(INSTALL_DATA) lvm2_lvmetad_systemd_red_hat.socket $(systemd_unit_dir)/lvm2-lvmetad.socket
13884 $(INSTALL_DATA) lvm2_lvmetad_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmetad.service
13885 $(INSTALL_DATA) lvm2_pvscan_systemd_red_hat@.service $(systemd_unit_dir)/lvm2-pvscan@.service
13886endif
13887ifeq ("@BUILD_LVMPOLLD@", "yes")
13888 $(INSTALL_DATA) lvm2_lvmpolld_systemd_red_hat.socket $(systemd_unit_dir)/lvm2-lvmpolld.socket
13889 $(INSTALL_DATA) lvm2_lvmpolld_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmpolld.service
13890endif
13891ifeq ("@BUILD_LVMLOCKD@", "yes")
13892 $(INSTALL_DATA) lvm2_lvmlockd_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmlockd.service
13893 $(INSTALL_DATA) lvm2_lvmlocking_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmlocking.service
13894endif
13895ifneq ("@CLVMD@", "none")
13896 $(INSTALL_DATA) lvm2_clvmd_systemd_red_hat.service $(systemd_unit_dir)/lvm2-clvmd.service
13897 $(INSTALL_DATA) lvm2_cluster_activation_systemd_red_hat.service $(systemd_unit_dir)/lvm2-cluster-activation.service
13898 $(INSTALL_SCRIPT) lvm2_cluster_activation_red_hat.sh $(systemd_dir)/lvm2-cluster-activation
13899endif
13900ifeq ("@BUILD_CMIRRORD@", "yes")
13901 $(INSTALL_DATA) lvm2_cmirrord_systemd_red_hat.service $(systemd_unit_dir)/lvm2-cmirrord.service
13902endif
13903ifeq ("@BUILD_LVMDBUSD@", "yes")
13904 $(INSTALL_DATA) lvm2_lvmdbusd_systemd_red_hat.service $(systemd_unit_dir)/lvm2-lvmdbusd.service
13905endif
13906
13907ifeq ("@BUILD_LVMDBUSD@", "yes")
13908install_dbus_service:
13909 $(INSTALL_DIR) $(dbusconfdir)
13910 $(INSTALL_DIR) $(dbusservicedir)
13911 $(INSTALL_DATA) $(top_srcdir)/scripts/com.redhat.lvmdbus1.conf $(dbusconfdir)
13912 $(INSTALL_DATA) com.redhat.lvmdbus1.service $(dbusservicedir)
13913
13914install_systemd_units: install_dbus_service
13915endif
13916
13917install_tmpfiles_configuration:
13918 $(INSTALL_DIR) $(tmpfiles_dir)
13919 $(INSTALL_DATA) lvm2_tmpfiles_red_hat.conf $(tmpfiles_dir)/lvm2.conf
13920
13921DISTCLEAN_TARGETS += \
13922 blkdeactivate.sh \
13923 blk_availability_init_red_hat \
13924 blk_availability_systemd_red_hat.service \
13925 clvmd_init_red_hat \
13926 cmirrord_init_red_hat \
13927 com.redhat.lvmdbus1.service \
13928 dm_event_systemd_red_hat.service \
13929 dm_event_systemd_red_hat.socket \
13930 lvmdump.sh \
13931 lvm2_cluster_activation_red_hat.sh \
13932 lvm2_cluster_activation_systemd_red_hat.service \
13933 lvm2_clvmd_systemd_red_hat.service \
13934 lvm2_cmirrord_systemd_red_hat.service \
13935 lvm2_lvmdbusd_systemd_red_hat.service \
13936 lvm2_lvmetad_init_red_hat \
13937 lvm2_lvmpolld_init_red_hat \
13938 lvm2_lvmetad_systemd_red_hat.service \
13939 lvm2_lvmetad_systemd_red_hat.socket \
13940 lvm2_lvmpolld_systemd_red_hat.service \
13941 lvm2_lvmpolld_systemd_red_hat.socket \
13942 lvm2_lvmlockd_systemd_red_hat.service \
13943 lvm2_lvmlocking_systemd_red_hat.service \
13944 lvm2_monitoring_init_red_hat \
13945 lvm2_monitoring_systemd_red_hat.service \
13946 lvm2_pvscan_systemd_red_hat@.service \
13947 lvm2_tmpfiles_red_hat.conf
13948\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/gdbinit\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000033125\013062740170\0020105\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
13949# This file is part of LVM2.
13950
13951# This copyrighted material is made available to anyone wishing to use,
13952# modify, copy, or redistribute it subject to the terms and conditions
13953# of the GNU Lesser General Public License v.2.1.
13954
13955# You should have received a copy of the GNU Lesser General Public License
13956# along with this program; if not, write to the Free Software Foundation,
13957# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
13958#
13959# Author(s):
13960# Jonathan Brassow <jbrassow@redhat.com>
13961#
13962# Copy this file to ~/.gdbinit or <working_dir>/.gdbinit
13963
13964printf "\n\n"
13965printf "Loading commands:\n"
13966printf " - dm_list_size <list ptr>\n"
13967printf " - pv_dev_name <PV ptr>\n"
13968printf " - first_seg <LV ptr>\n"
13969printf " - lv_status <LV ptr>\n"
13970printf " - lv_status_r <LV ptr>\n"
13971printf " - lv_is_mirrored <LV ptr>\n"
13972printf " - seg_item <seg ptr> <index>\n"
13973printf " - seg_status <seg ptr>\n"
13974printf " - segs_using_this_lv <seg ptr>\n"
13975printf " - seg_pvs <list ptr>\n"
13976printf " - \n"
13977printf "Use 'help <command>' for more info\n"
13978printf "\n\n"
13979printf "Popular breakpoints:\n"
13980printf "break _alloc_image_components\n"
13981printf "run --repair --use-policies vg/lv\n"
13982printf "\n\n"
13983
13984set follow-fork-mode child
13985
13986# Conventions:
13987# foo : function named 'foo' available to user
13988# __foo : an internal function
13989#
13990# External functions should have a corresponding 'document'
13991# section. Internal functions should have leading comments
13992
13993
13994
13995define dm_list_size
13996 set $_DLS_list_head = (struct dm_list *)$arg0
13997 set $_DLS_list = $_DLS_list_head->n
13998 set $_DLS_size = 0
13999
14000 while (($_DLS_list != $_DLS_list_head) && ($_DLS_size < 100))
14001 set $_DLS_list = $_DLS_list->n
14002 set $_DLS_size++
14003 end
14004
14005 printf "%d list items\n", $_DLS_size
14006end
14007
14008document dm_list_size
14009Returns the number of elements in the dm_list
14010
14011 Usage: dm_list_size <list ptr>
14012end
14013
14014define pv_dev_name
14015 set $_PDN_pv = (struct physical_volume *)$arg0
14016 set $_PDN_dev = $_PDN_pv->dev
14017 set $_PDN_strl = (struct str_list *)$_PDN_dev->aliases.n
14018
14019 printf "%s\n", $_PDN_strl->str
14020end
14021
14022document pv_dev_name
14023Print the name of the PV for the given PV pointer
14024
14025 Usage: pv_dev_name <PV ptr>
14026end
14027
14028define seg_pvs
14029 set $_SP_list_head = (struct dm_list *)$arg0
14030 set $_SP_list = $_SP_list_head->n
14031
14032 while (($_SP_list != $_SP_list_head) && ($_SP_size < 100))
14033 set $_SP_spv = (struct seg_pvs *)$_SP_list
14034
14035 printf "* Can't print PV list\n"
14036
14037 set $_SP_list = $_SP_list->n
14038 end
14039
14040 printf "%d list items\n", $_SP_size
14041end
14042
14043document seg_pvs
14044Print the elements of a seg_pvs list
14045
14046 Usage: seg_pvs <list ptr>
14047end
14048
14049#
14050# __first_seg <return> <LV>
14051define __first_seg
14052 set $arg0 = 0x0
14053 set $_FS_lv = (struct logical_volume *)$arg1
14054
14055 if ($_FS_lv->segments.n != &$_FS_lv->segments)
14056 set $arg0 = (struct lv_segment *)$_FS_lv->segments.n
14057 end
14058end
14059
14060define first_seg
14061 set $_seg = 0
14062 set $_lv=(struct logical_volume *)$arg0
14063
14064 __first_seg $_seg $_lv
14065
14066 if ($_seg)
14067 p $_seg
14068 else
14069 printf "No segments (list empty)\n"
14070 end
14071end
14072
14073document first_seg
14074Returns the pointer to the first segment of an LV
14075
14076 Usage: first_seg <LV ptr>
14077
14078WARNING: If the list pointer in 'struct lv_segment' moves,
14079 this function will be wrong.
14080end
14081
14082#
14083# __seg_type <return> <seg> <index>
14084define __seg_type
14085 set $arg0 = 0x0
14086 set $_ST_seg = (struct lv_segment *)$arg1
14087 set $_ST_index= $arg2
14088 set $_ST_area = $_ST_seg->areas[$_ST_index]
14089 set $_ST_type = $_ST_area.type
14090
14091 set $arg0 = $_ST_type
14092end
14093
14094#
14095# __seg_item <return> <seg> <index>
14096define __seg_item
14097 set $arg0 = 0x0
14098 set $_SI_seg = (struct lv_segment *)$arg1
14099 set $_SI_index= $arg2
14100
14101 if ($_SI_index < $_SI_seg->area_count)
14102 set $_SI_area = $_SI_seg->areas[$_SI_index]
14103 set $_SI_type = $_SI_area.type
14104
14105 if ($_SI_type == AREA_PV)
14106 set $arg0 = $_SI_area.u.pv.pvseg->pv
14107 else
14108 if ($_SI_type == AREA_LV)
14109 set $arg0 = $_SI_area.u.lv.lv
14110 end
14111 end
14112 end
14113end
14114
14115#
14116# __seg_metaitem <return> <seg> <index>
14117define __seg_metaitem
14118 set $arg0 = 0x0
14119 set $_SMI_seg = (struct lv_segment *)$arg1
14120 set $_SMI_index= $arg2
14121
14122 if (($_SMI_index < $_SMI_seg->area_count) && $_SMI_seg->meta_areas)
14123 set $_SMI_area = $_SMI_seg->meta_areas[$_SMI_index]
14124 set $_SMI_type = $_SMI_area.type
14125
14126 if ($_SMI_type == AREA_PV)
14127 set $arg0 = $_SMI_area.u.pv.pvseg->pv
14128 else
14129 if ($_SMI_type == AREA_LV)
14130 set $arg0 = $_SMI_area.u.lv.lv
14131 end
14132 end
14133 end
14134end
14135
14136define seg_item
14137 set $_item = 0x0
14138
14139 __seg_item $_item $arg0 $arg1
14140 if ($_item)
14141 p $_item
14142 else
14143 printf "AREA_UNASSIGNED or invalid\n"
14144 end
14145end
14146
14147define seg_metaitem
14148 set $_metaitem = 0x0
14149
14150 __seg_metaitem $_metaitem $arg0 $arg1
14151 if ($_metaitem)
14152 p $_metaitem
14153 else
14154 printf "AREA_UNASSIGNED or invalid\n"
14155 end
14156end
14157
14158document seg_item
14159Returns the pointer to the LV or PV for the indexed area of a segment
14160
14161 Usage: seg_item <struct lv_segment *> <index>
14162
14163Example - Getting to the sub-lv of a mirror:
14164 (gdb) p lv->name
14165 $1 = 0x712548 "lv"
14166
14167 (gdb) first_seg lv
14168 $2 = (struct lv_segment *) 0x7128b8
14169
14170 (gdb) seg_item $2 0
14171 $3 = (struct logical_volume *) 0x712688
14172
14173 (gdb) p $3->name
14174 $4 = 0x712770 "lv_mimage_0"
14175end
14176
14177define __status
14178 set $_s_status = $arg0->status
14179
14180# Constants defined in metadata-exported.h
14181
14182# if ($_s_status & RAID)
14183 if ($_s_status & 0x0000000100000000LU)
14184 set $_s_status = $_s_status & ~0x0000000100000000LU
14185 printf " RAID"
14186 end
14187# if ($_s_status & RAID_META)
14188 if ($_s_status & 0x0000000200000000LU)
14189 set $_s_status = $_s_status & ~0x0000000200000000LU
14190 printf " RAID_META"
14191 end
14192# if ($_s_status & RAID_IMAGE)
14193 if ($_s_status & 0x0000000400000000LU)
14194 set $_s_status = $_s_status & ~0x0000000400000000LU
14195 printf " RAID_IMAGE"
14196 end
14197# if ($_s_status & MIRRORED)
14198 if ($_s_status & 0x00008000U)
14199 set $_s_status = $_s_status & ~0x00008000U
14200 printf " MIRRORED"
14201 end
14202# if ($_s_status & MIRROR_LOG)
14203 if ($_s_status & 0x00020000U)
14204 set $_s_status = $_s_status & ~0x00020000U
14205 printf " MIRROR_LOG"
14206 end
14207# if ($_s_status & MIRROR_IMAGE)
14208 if ($_s_status & 0x00040000U)
14209 set $_s_status = $_s_status & ~0x00040000U
14210 printf " MIRROR_IMAGE"
14211 end
14212# if ($_s_status & VISIBLE_LV)
14213 if ($_s_status & 0x00000040U)
14214 printf " VISIBLE_LV"
14215 set $_s_status = $_s_status & ~0x00000040U
14216 else
14217 printf " *HIDDEN_LV*"
14218 end
14219# if ($_s_status & FIXED_MINOR)
14220 if ($_s_status & 0x00000080U)
14221 set $_s_status = $_s_status & ~0x00000080U
14222 printf " FIXED_MINOR"
14223 end
14224# if ($_s_status & LVM_READ)
14225 if ($_s_status & 0x00000100U)
14226 set $_s_status = $_s_status & ~0x00000100U
14227 printf " LVM_READ"
14228 end
14229# if ($_s_status & LVM_WRITE)
14230 if ($_s_status & 0x00000200U)
14231 set $_s_status = $_s_status & ~0x00000200U
14232 printf " LVM_WRITE"
14233 end
14234# if ($_s_status & SNAPSHOT)
14235 if ($_s_status & 0x00001000U)
14236 set $_s_status = $_s_status & ~0x00001000U
14237 printf " SNAPSHOT"
14238 end
14239# if ($_s_status & PVMOVE)
14240 if ($_s_status & 0x00002000U)
14241 set $_s_status = $_s_status & ~0x00002000U
14242 printf " PVMOVE"
14243 end
14244# if ($_s_status & LOCKED)
14245 if ($_s_status & 0x00004000U)
14246 set $_s_status = $_s_status & ~0x00004000U
14247 printf " LOCKED"
14248 end
14249# if ($_s_status & LV_NOTSYNCED)
14250 if ($_s_status & 0x00080000U)
14251 set $_s_status = $_s_status & ~0x00080000U
14252 printf " LV_NOTSYNCED"
14253 end
14254# if ($_s_status & CONVERTING)
14255 if ($_s_status & 0x00400000U)
14256 set $_s_status = $_s_status & ~0x00400000U
14257 printf " CONVERTING"
14258 end
14259# if ($_s_status & LV_REBUILD)
14260 if ($_s_status & 0x100000U)
14261 set $_s_status = $_s_status & ~0x100000U
14262 printf " LV_REBUILD"
14263 end
14264# if ($_s_status & PARTIAL_LV)
14265 if ($_s_status & 0x1000000U)
14266 set $_s_status = $_s_status & ~0x1000000U
14267 printf " PARTIAL_LV"
14268 end
14269# if ($_s_status & MERGING)
14270 if ($_s_status & 0x10000000U)
14271 set $_s_status = $_s_status & ~0x10000000U
14272 printf " MERGING"
14273 end
14274# if ($_s_status & LV_WRITEMOSTLY)
14275 if ($_s_status & 0x10000000000U)
14276 set $_s_status = $_s_status & ~0x10000000000U
14277 printf " LV_WRITEMOSTLY"
14278 end
14279
14280 if ($_s_status)
14281 printf " 0x%x", $_s_status
14282 end
14283end
14284
14285#
14286# __print_indent <num indents> [No marks]
14287define __print_indent
14288 set $_PI_indent = $arg0
14289 set $_PI_lead_mark = 0
14290
14291 while ($_PI_indent)
14292 if ($_PI_indent == 1)
14293 if ($argc > 1)
14294 if ($_PI_lead_mark)
14295 printf " "
14296 else
14297 printf "| "
14298 end
14299 else
14300 printf "|-----> "
14301 end
14302 else
14303 printf "| "
14304 set $_PI_lead_mark = 1
14305 end
14306 set $_PI_indent--
14307 end
14308end
14309
14310define lv_status
14311 # Use __lv because we don't want to overwrite higher functions
14312 set $__lv = (struct logical_volume *)$arg0
14313
14314 if ($argc == 2)
14315 __print_indent $arg1
14316 end
14317 printf "%s->status:", $__lv->name
14318 __status $__lv
14319 printf "\n"
14320end
14321
14322document lv_status
14323Display the flags that are set on an LV.
14324
14325 Usage: lv_status <LV ptr>
14326end
14327
14328define seg_status
14329 set $_seg=(struct lv_segment *)$arg0
14330
14331 if ($argc == 2)
14332 __print_indent $arg1 1
14333 end
14334 printf "[ (%s) seg->status:", $_seg->lv->name
14335 __status $_seg
14336 printf " ]\n"
14337end
14338
14339document seg_status
14340Display the flags that are set on an lv_segment.
14341
14342 Usage: seg_status <(struct lv_segment *)>
14343end
14344
14345#
14346# get_only_segment_using_this_lv <return> <LV>
14347define __get_only_segment_using_this_lv
14348 set $arg0 = 0x0
14349 set $_lv=(struct logical_volume *)$arg1
14350 set $_seg_list_head = &$_lv->segs_using_this_lv
14351 set $_s = $_lv->segs_using_this_lv.n
14352 set $_i = 0
14353
14354 while (($_s != $_seg_list_head) && ($_i < 100))
14355 set $_seg_list = (struct seg_list *)$_s
14356 set $_seg = (struct lv_segment *)$_seg_list->seg
14357
14358 set $_i++
14359 set $_s = $_s->n
14360 end
14361
14362 if ($_i > 1)
14363 printf "More than %s using %s\n", ($_i > 99) ? "100 segments" : "one segment", $_lv->name
14364 end
14365 if ($_i == 1)
14366 set $arg0 = $_seg
14367 end
14368end
14369
14370define segs_using_this_lv
14371 set $_lv=(struct logical_volume *)$arg0
14372 set $_seg_list_head = &$_lv->segs_using_this_lv
14373 set $_s = $_lv->segs_using_this_lv.n
14374 set $_i = 0
14375
14376 if ($_s != $_seg_list_head)
14377 printf "Segments using %s\n", $_lv->name
14378 else
14379 printf "No segments using %s\n", $_lv->name
14380 end
14381 while ($_s != $_seg_list_head)
14382 set $_seg_list = (struct seg_list *)$_s
14383 set $_seg = (struct lv_segment *)$_seg_list->seg
14384 printf " %d) seg: %p", $_i, $_seg
14385 if ($_seg->lv < 0x200)
14386 printf " [BAD LV POINTER FROM THIS SEG]\n"
14387 else
14388 printf " [seg found in %s]\n", $_seg->lv->name
14389 end
14390 set $_i++
14391 set $_s = $_s->n
14392 end
14393end
14394
14395document segs_using_this_lv
14396Display the segments (and their associated LV) using an LV
14397
14398 Usage: segs_using_this_lv <LV ptr>
14399
14400Example:
14401 (gdb) lv_is_mirrored lv
14402 lv is mirrored ('core' log)
14403
14404 (gdb) segs_using_this_lv lv
14405 No segments using lv
14406
14407 (gdb) first_seg lv
14408 $1 = (struct lv_segment *) 0x92d360
14409
14410 (gdb) seg_item $1 0
14411 $2 = (struct logical_volume *) 0x928f58
14412
14413 (gdb) segs_using_this_lv $2
14414 Segments using lv_mimage_0
14415 0) seg: 0x92d360 [seg found in lv]
14416end
14417
14418#
14419# __next_area_index <return> <seg> <seg_item>
14420define __next_area_index
14421 set $arg0 = 0x0
14422 set $_seg = (struct lv_segment *)$arg1
14423 set $_item = 0x0
14424 set $_i = 0
14425
14426 __seg_item $_item $_seg $_i
14427 while ($_item && ($_item != $arg2))
14428 set $_i++
14429 __seg_item $_item $_seg $_i
14430 end
14431
14432 # $_i points to current, now get next (if there)
14433 set $_i++
14434 __seg_item $_item $_seg $_i
14435
14436 if ($_item)
14437 set $arg0 = $_i
14438 end
14439end
14440
14441#
14442# __lv_status_r <LV>
14443# Decend tree, printing LV and seg status as we go. This
14444# performs a depth first approach (but can't come up)
14445#
14446# or
14447#
14448# __lv_status_r <sub_lv> <seg using sub_lv>
14449# Try continuing decent of tree by first shifting to the
14450# next 'area' in the seg ($arg1). If no more areas, then
14451# try going to the next segment.
14452define __lv_status_r
14453 if ($argc == 1)
14454 set $_lv=(struct logical_volume *)$arg0
14455 set $_seg_list_head = &$_lv->segments
14456 set $_s = $_lv->segments.n
14457 set $_area_index = 0
14458
14459# printf "\n"
14460 lv_status $_lv $indent
14461 else
14462 set $_seg = (struct lv_segment *)$arg1
14463
14464 __next_area_index $_area_index $_seg $arg0
14465
14466 # Don't fuck this up. We need the next two lines here.
14467 set $_lv=(struct logical_volume *)$_seg->lv
14468 set $_seg_list_head = &$_lv->segments
14469 set $_s = (struct dm_list *)$_seg
14470
14471 if (!$_area_index)
14472 set $_s = $_s->n
14473 end
14474 end
14475
14476 if ($_s == $_seg_list_head)
14477 if ($argc == 1)
14478 __print_indent $indent 1
14479 printf "[ No segments for %s ]\n", $_lv->name
14480 end
14481 __get_only_segment_using_this_lv $_seg $_lv
14482
14483 if ($_seg && $indent)
14484 set $indent--
14485 __lv_status_r $_lv $_seg
14486 end
14487 else
14488 set $_seg = (struct lv_segment *)$_s
14489 set $_type = 0x0
14490
14491 if (!$_area_index)
14492 seg_status $_seg $indent
14493 end
14494 __seg_type $_type $_seg $_area_index
14495 if ($_type == AREA_LV)
14496 set $indent++
14497
14498 __seg_metaitem $_lv $_seg $_area_index
14499 if ($_lv)
14500 set $rindent = $indent
14501 set $rseg = $_seg
14502 set $rarea_index = $_area_index
14503 set $rlv = $_lv
14504
14505 __lv_status_r $_lv
14506
14507 set $indent = $rindent
14508 set $_seg = $rseg
14509 set $_area_index = $rarea_index
14510 set $_lv = $rlv
14511 end
14512
14513 __seg_item $_lv $_seg $_area_index
14514 __lv_status_r $_lv
14515 else
14516 if ($_seg->log_lv)
14517 set $indent++
14518 set $_log_seg = 0x0
14519
14520 __first_seg $_log_seg $_seg->log_lv
14521 lv_status $_seg->log_lv $indent
14522 seg_status $_log_seg $indent
14523
14524 set $indent--
14525 end
14526 __get_only_segment_using_this_lv $_seg $_lv
14527 if ($_seg)
14528 set $indent--
14529 __lv_status_r $_lv $_seg
14530 end
14531 end
14532 end
14533end
14534
14535define lv_status_r
14536 set $indent = 0
14537 __lv_status_r $arg0
14538end
14539
14540document lv_status_r
14541Display the status flags of an LV and its sub_lvs.
14542
14543 Usage: lv_status_r <LV ptr>
14544
14545This function is useful for checking that all the LVs that
14546compose a logical volume have the correct flags set (and also
14547their associated lv_segments)
14548end
14549
14550define lv_is_mirrored
14551 set $_lv=(struct logical_volume *)$arg0
14552 set $_fs=(struct lv_segment *)$_lv->segments.n
14553 set $_log_lv=(struct logical_volume *)$_fs->log_lv
14554
14555# if ($_lv->status & MIRRORED)
14556 if ($_lv->status & 0x00008000U)
14557 printf "%s is mirrored (", $_lv->name
14558 if ($_log_lv)
14559 if ($_log_lv->status & 0x00008000U)
14560 printf "'mirrored' log)\n"
14561 else
14562 printf "'disk' log)\n"
14563 end
14564 else
14565 printf "'core' log)\n"
14566 end
14567 else
14568 printf "%s is not mirrored\n", $_lv->name
14569 end
14570end
14571
14572document lv_is_mirrored
14573Report whether the given LV is mirrored (and its log type).
14574
14575 Usage: lv_is_mirrored <LV ptr>
14576end
14577\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmdbusd_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000270\013062740170\0026542\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
14578Description=LVM2 D-Bus service
14579Documentation=man:lvmdbusd(8)
14580
14581[Service]
14582Type=dbus
14583BusName=com.redhat.lvmdbus1
14584ExecStart=@sbindir@/lvmdbusd
14585
14586[Install]
14587WantedBy=multi-user.target
14588\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0022153\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/Makefile\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000306\013062740170\0023612\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0all:
14589 echo "Nothing to do for make all"
14590
14591manpage:
14592 pod2man --center="create LVM2 initrd" --name='lvm2create_initrd' --section=8 -r 'lvm2create_initrd' ./lvm2create_initrd.pod > lvm2create_initrd.8
14593
14594\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/lvm2create_initrd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000037246\013062740170\0025527\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
14595#
14596# lvm2create_initrd
14597#
14598# Miguel Cabeca
14599# cabeca (at) ist (dot) utl (dot) pt
14600#
14601# Inspiration to write this script came from various sources
14602#
14603# Original LVM lvmcreate_initrd: ftp://ftp.sistina.com/pub/LVM/1.0/
14604# Kernel initrd.txt: http://www.kernel.org/
14605# EVMS INSTALL.initrd & linuxrc: http://evms.sourceforge.net/
14606# Jeffrey Layton's lvm2create_initrd: http://poochiereds.net/svn/lvm2create_initrd/
14607# Christophe Saout's initrd & linuxrc: http://www.saout.de/misc/
14608#
14609# This script was only tested with kernel 2.6 with everything required to boot
14610# the root filesystem built-in (not as modules). Ex: SCSI or IDE, RAID, device mapper
14611# It does not support devfs as it is deprecated in the 2.6 kernel series
14612#
14613# It needs lvm2 tools, busybox, pivot_root, MAKEDEV
14614#
14615# It has been tested on Debian sid (unstable) only
14616#
14617# Changelog
14618# 26/02/2004 Initial release -- Miguel Cabeca
14619# 27/02/2004 Removed the BUSYBOXSYMLINKS var. The links are now determined at runtime.
14620# some changes in init script to call a shell if something goes wrong. -- Miguel Cabeca
14621# 19/04/2004 Several small changes. Pass args to init so single user mode works. Add some
14622# PATH entries to /sbin/init shell script so chroot works without /usr mounted. Remove
14623# mkdir /initrd so we don't cause problems if root filesystem is corrupted. -- Jeff Layton
14624# 15/05/2004 initial support for modules, create lvm.conf from lvm dumpconfig, other cleanups -- Jeff Layton
14625# 14/11/2006 Update handling of ldd output to handle hardcoded library links and virtual dll linux-gate.
14626# Add support for Gentoo-style MAKEDEV. Remove hardcoded BINUTILS paths -- Douglas Mayle
14627#
14628# Copyright Miguel Cabeca, Jeffrey Layton, 2004
14629#
14630# This program is free software; you can redistribute it and/or modify
14631# it under the terms of the GNU General Public License as published by
14632# the Free Software Foundation; either version 2 of the License, or
14633# (at your option) any later version.
14634#
14635# This program is distributed in the hope that it will be useful,
14636# but WITHOUT ANY WARRANTY; without even the implied warranty of
14637# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14638# GNU General Public License for more details.
14639#
14640# You should have received a copy of the GNU General Public License
14641# along with this program; if not, write to the Free Software
14642# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14643#
14644# $Id$
14645
14646TMPMNT=/tmp/mnt.$$
14647DEVRAM=/tmp/initrd.$$
14648
14649# set defaults
14650BINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"}
14651BASICDEVICES=${BASICDEVICES:-"std consoleonly fd"}
14652BLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"}
14653MAKEDEV=${MAKEDEV:-"debian"}
14654
14655# Uncomment this if you want to disable automatic size detection
14656#INITRDSIZE=4096
14657
14658PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
14659
14660usage () {
14661 echo "Create an initial ramdisk image for LVM2 root filesystem"
14662 echo "$cmd: [-h] [-v] [-c lvm.conf] [-m modulelist] [-e extrafiles] -r [raiddevs] [-R mdadm.conf] [-M style] [kernel version]"
14663 echo " -h|--help print this usage message"
14664 echo " -v|--verbose verbose progress messages"
14665 echo " -c|--lvmconf path to lvm.conf (/etc/lvm/lvm.conf)"
14666 echo " -m|--modules modules to copy to initrd image"
14667 echo " -e|--extra extra files to add to initrd"
14668 echo " -r|--raid raid devices to start in initrd"
14669 echo " -R|--raidconf location of mdadm.conf file to include"
14670 echo " -M|--makedev set MAKEDEV type (debian, redhat, gentoo)"
14671}
14672
14673verbose () {
14674 [ "$VERBOSE" ] && echo "`echo $cmd | tr '[a-z0-9/_]' ' '` -- $1" || true
14675}
14676
14677cleanup () {
14678 [ "`mount | grep $DEVRAM`" ] && verbose "unmounting $DEVRAM" && umount $DEVRAM
14679 [ -f $DEVRAM ] && verbose "removing $DEVRAM" && rm $DEVRAM
14680 [ -d $TMPMNT ] && verbose "removing $TMPMNT" && rmdir $TMPMNT
14681 verbose "exit with code $1"
14682 exit $1
14683}
14684
14685trap "
14686 verbose 'Caught interrupt'
14687 echo 'Bye bye...'
14688 cleanup 1
14689" 1 2 3 15
14690
14691create_init () {
14692 cat << 'INIT' > $TMPMNT/sbin/init
14693#!/bin/bash
14694
14695# include in the path some dirs from the real root filesystem
14696# for chroot, blockdev
14697PATH="/sbin:/bin:/usr/sbin:/usr/bin:/lib/lvm-200:/initrd/bin:/initrd/sbin"
14698PRE="initrd:"
14699
14700do_shell(){
14701 /bin/echo
14702 /bin/echo "*** Entering LVM2 rescue shell. Exit shell to continue booting. ***"
14703 /bin/echo
14704 /bin/bash
14705}
14706
14707echo "$PRE Remounting / read/write"
14708mount -t ext2 -o remount,rw /dev/ram0 /
14709
14710
14711# We need /proc for device mapper
14712echo "$PRE Mounting /proc"
14713mount -t proc none /proc
14714
14715# plug in modules listed in /etc/modules
14716if [ -f /etc/modules ]; then
14717 echo -n "$PRE plugging in kernel modules:"
14718 cat /etc/modules |
14719 while read module; do
14720 echo -n " $module"
14721 modprobe $module
14722 done
14723 echo '.'
14724fi
14725
14726# start raid devices if raid_autostart file exists
14727if [ -f /etc/raid_autostart ]; then
14728 if [ ! -f /etc/mdadm/mdadm.conf ]; then
14729 mdoptions='--super-minor=dev'
14730 fi
14731 cat /etc/raid_autostart|
14732 while read dev; do
14733 echo "Starting RAID device $dev"
14734 /sbin/mdadm --assemble $dev $mdoptions
14735 done
14736fi
14737
14738# Create the /dev/mapper/control device for the ioctl
14739# interface using the major and minor numbers that have been allocated
14740# dynamically.
14741
14742echo -n "$PRE Finding device mapper major and minor numbers "
14743
14744MAJOR=$(sed -n 's/^ *\([0-9]\+\) \+misc$/\1/p' /proc/devices)
14745MINOR=$(sed -n 's/^ *\([0-9]\+\) \+device-mapper$/\1/p' /proc/misc)
14746if test -n "$MAJOR" -a -n "$MINOR" ; then
14747 mkdir -p -m 755 /dev/mapper
14748 mknod -m 600 /dev/mapper/control c $MAJOR $MINOR
14749fi
14750
14751echo "($MAJOR,$MINOR)"
14752
14753# Device-Mapper dynamically allocates all device numbers. This means it is possible
14754# that the root volume specified to LILO or Grub may have a different number when the
14755# initrd runs than when the system was last running. In order to make sure the
14756# correct volume is mounted as root, the init script must determine what the
14757# desired root volume name is by getting the LVM2 root volume name from the kernel command line. In order for
14758# this to work correctly, "lvm2root=/dev/Volume_Group_Name/Root_Volume_Name" needs to be passed
14759# to the kernel command line (where Root_Volume_Name is replaced by your actual
14760# root volume's name.
14761for arg in `cat /proc/cmdline`; do
14762 echo $arg | grep '^lvm2root=' > /dev/null
14763 if [ $? -eq 0 ]; then
14764 rootvol=${arg#lvm2root=}
14765 break
14766 fi
14767done
14768
14769echo "$PRE Activating LVM2 volumes"
14770
14771
14772# run a shell if we're passed lvm2rescue on commandline
14773grep lvm2rescue /proc/cmdline 1>/dev/null 2>&1
14774if [ $? -eq 0 ]; then
14775 lvm vgchange --ignorelockingfailure -P -a y
14776 do_shell
14777else
14778 lvm vgchange --ignorelockingfailure -a y
14779fi
14780
14781echo "$PRE Mounting root filesystem $rootvol ro"
14782mkdir /rootvol
14783if ! mount -t auto -o ro $rootvol /rootvol; then
14784 echo "\t*FAILED*";
14785 do_shell
14786fi
14787
14788echo "$PRE Umounting /proc"
14789umount /proc
14790
14791echo "$PRE Changing roots"
14792cd /rootvol
14793if ! pivot_root . initrd ; then
14794 echo "\t*FAILED*"
14795 do_shell
14796fi
14797
14798echo "$PRE Proceeding with boot..."
14799
14800exec chroot . /bin/sh -c "umount /initrd; blockdev --flushbufs /dev/ram0 ; exec /sbin/init $*" < dev/console > dev/console 2>&1
14801
14802INIT
14803 chmod 555 $TMPMNT/sbin/init
14804}
14805
14806# create lvm.conf file from dumpconfig. Just use filter options
14807create_lvmconf () {
14808 echo 'devices {' > $TMPMNT/etc/lvm/lvm.conf
14809 lvm dumpconfig | grep 'filter=' >> $TMPMNT/etc/lvm/lvm.conf
14810 echo '}' >> $TMPMNT/etc/lvm/lvm.conf
14811}
14812
14813#
14814# Main
14815#
14816
14817cmd=`basename $0`
14818
14819VERSION=`uname -r`
14820
14821while [ $# -gt 0 ]; do
14822 case $1 in
14823 -h|--help) usage; exit 0;;
14824 -v|--verbose) VERBOSE="y";;
14825 -c|--lvmconf) LVMCONF=$2; shift;;
14826 -m|--modules) MODULES=$2; shift;;
14827 -e|--extra) EXTRAFILES=$2; shift;;
14828 -r|--raid) RAID=$2; shift;;
14829 -R|--raidconf) RAIDCONF=$2; shift;;
14830 -M|--makedev) MAKEDEV=$2; shift;;
14831 [2-9].[0-9]*.[0-9]*) VERSION=$1;;
14832 *) echo "$cmd -- invalid option '$1'"; usage; exit 0;;
14833 esac
14834 shift
14835done
14836
14837INITRD=${INITRD:-"/boot/initrd-lvm2-$VERSION.gz"}
14838
14839echo "$cmd -- make LVM initial ram disk $INITRD"
14840echo ""
14841
14842if [ -n "$RAID" ]; then
14843 BINFILES="$BINFILES /sbin/mdadm"
14844 RAIDCONF=${RAIDCONF:-"/etc/mdadm/mdadm.conf"}
14845 if [ -r $RAIDCONF ]; then
14846 EXTRAFILES="$EXTRAFILES $RAIDCONF"
14847 else
14848 echo "$cmd -- WARNING: No $RAIDCONF! Your RAID device minor numbers must match their superblock values!"
14849 fi
14850fi
14851
14852# add modprobe if we declared any modules
14853if [ -n "$MODULES" ]; then
14854 BINFILES="$BINFILES /sbin/modprobe /sbin/insmod /sbin/rmmod"
14855fi
14856
14857for a in $BINFILES $EXTRAFILES; do
14858 if [ ! -r "$a" ] ; then
14859 echo "$cmd -- ERROR: you need $a"
14860 exit 1;
14861 fi;
14862done
14863
14864# Figure out which shared libraries we actually need in our initrd
14865echo "$cmd -- finding required shared libraries"
14866verbose "BINFILES: `echo $BINFILES`"
14867
14868# We need to strip certain lines from ldd output. This is the full output of an example ldd:
14869#lvmhost~ # ldd /sbin/lvm /bin/bash
14870#/sbin/lvm:
14871# not a dynamic executable
14872#/bin/bash:
14873# linux-gate.so.1 => (0xbfffe000)
14874# libncurses.so.5 => /lib/libncurses.so.5 (0xb7ee3000)
14875# libdl.so.2 => /lib/libdl.so.2 (0xb7edf000)
14876# libc.so.6 => /lib/libc.so.6 (0xb7dc1000)
14877# /lib/ld-linux.so.2 (0xb7f28000)
14878#
14879# 1) Lines with a ":" contain the name of the original binary we're examining, and so are unnecessary.
14880# We need to strip them because they contain "/", and can be confused with links with a hardcoded path.
14881# 2) The linux-gate library is a virtual dll that does not exist on disk, but is instead loaded automatically
14882# into the process space, and can't be copied to the ramdisk
14883#
14884# After these lines have been stripped, we're interested in the lines remaining if they
14885# 1) Contain "=>" because they are pathless links, and the value following the token is the path on the disk
14886# 2) Contain "/" because it's a link with a hardcoded path, and so we're interested in the link itself.
14887LIBFILES=`ldd $BINFILES 2>/dev/null |grep -v -E \(linux-gate\|:\) | awk '{if (/=>/) { print $3 } else if (/\//) { print $1 }}' | sort -u`
14888if [ $? -ne 0 ]; then
14889 echo "$cmd -- ERROR figuring out needed shared libraries"
14890 exit 1
14891fi
14892
14893verbose "Shared libraries needed: `echo $LIBFILES`"
14894
14895INITRDFILES="$BINFILES $LIBFILES $MODULES $EXTRAFILES"
14896
14897# tack on stuff for modules if we declared any and the files exist
14898if [ -n "$MODULES" ]; then
14899 if [ -f "/etc/modprobe.conf" ]; then
14900 INITRDFILES="$INITRDFILES /etc/modprobe.conf"
14901 fi
14902 if [ -f "/lib/modules/modprobe.conf" ]; then
14903 INITRDFILES="$INITRDFILES /lib/modules/modprobe.conf"
14904 fi
14905fi
14906
14907# Calculate the the size of the ramdisk image.
14908# Don't forget that inodes take up space too, as does the filesystem metadata.
14909echo "$cmd -- calculating initrd filesystem parameters"
14910if [ -z "$INITRDSIZE" ]; then
14911 echo "$cmd -- calculating loopback file size"
14912 verbose "finding size"
14913 INITRDSIZE="`du -Lck $INITRDFILES | tail -1 | cut -f 1`"
14914 verbose "minimum: $INITRDSIZE kB for files + inodes + filesystem metadata"
14915 INITRDSIZE=`expr $INITRDSIZE + 512` # enough for ext2 fs + a bit
14916fi
14917
14918echo "$cmd -- making loopback file ($INITRDSIZE kB)"
14919verbose "using $DEVRAM as a temporary loopback file"
14920dd if=/dev/zero of=$DEVRAM count=$INITRDSIZE bs=1024 > /dev/null 2>&1
14921if [ $? -ne 0 ]; then
14922 echo "$cmd -- ERROR creating loopback file"
14923 cleanup 1
14924fi
14925
14926echo "$cmd -- making ram disk filesystem"
14927verbose "mke2fs -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE"
14928[ "$VERBOSE" ] && OPT_Q="" || OPT_Q="-q"
14929mke2fs $OPT_Q -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE
14930if [ $? -ne 0 ]; then
14931 echo "$cmd -- ERROR making ram disk filesystem"
14932 echo "$cmd -- ERROR you need to use mke2fs >= 1.14 or increase INITRDSIZE"
14933 cleanup 1
14934fi
14935
14936verbose "creating mountpoint $TMPMNT"
14937mkdir $TMPMNT
14938if [ $? -ne 0 ]; then
14939 echo "$cmd -- ERROR making $TMPMNT"
14940 cleanup 1
14941fi
14942
14943echo "$cmd -- mounting ram disk filesystem"
14944verbose "mount -o loop $DEVRAM $TMPMNT"
14945mount -oloop $DEVRAM $TMPMNT
14946if [ $? -ne 0 ]; then
14947 echo "$cmd -- ERROR mounting $DEVRAM on $TMPMNT"
14948 cleanup 1
14949fi
14950
14951verbose "creating basic set of directories in $TMPMNT"
14952(cd $TMPMNT; mkdir bin dev etc lib proc sbin var)
14953if [ $? -ne 0 ]; then
14954 echo "$cmd -- ERROR creating directories in $TMPMNT"
14955 cleanup 1
14956fi
14957
14958# Add some /dev files. We have to handle different types of MAKEDEV invocations
14959# here, so this is rather messy.
14960RETCODE=0
14961echo "$cmd -- adding required /dev files"
14962verbose "BASICDEVICES: `echo $BASICDEVICES`"
14963verbose "BLOCKDEVICES: `echo $BLOCKDEVICES`"
14964[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
14965case "$MAKEDEV" in
14966debian)
14967 (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
14968 RETCODE=$?
14969 ;;
14970redhat)
14971 (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q -d $TMPMNT/dev -m 2)
14972 RETCODE=$?
14973 ;;
14974gentoo)
14975 (cd $TMPMNT/dev; /sbin/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
14976 RETCODE=$?
14977 ;;
14978*)
14979 echo "$cmd -- ERROR: $MAKEDEV is not a known MAKEDEV style."
14980 RETCODE=1
14981 ;;
14982esac
14983
14984
14985if [ $RETCODE -ne 0 ]; then
14986 echo "$cmd -- ERROR adding /dev files"
14987 cleanup 1
14988fi
14989
14990
14991# copy necessary files to ram disk
14992echo "$cmd -- copying initrd files to ram disk"
14993[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q="--quiet"
14994verbose "find \$INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT"
14995find $INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT
14996if [ $? -ne 0 ]; then
14997 echo "$cmd -- ERROR cpio to ram disk"
14998 cleanup 1
14999fi
15000
15001
15002echo "$cmd -- creating symlinks to busybox"
15003shopt -s extglob
15004[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
15005BUSYBOXSYMLINKS=`busybox 2>&1| awk '/^Currently defined functions:$/ {i++;next} i'|tr ',\t\n' ' '`
15006for link in ${BUSYBOXSYMLINKS//@(linuxrc|init|busybox)}; do
15007 ln -s $OPT_Q busybox $TMPMNT/bin/$link;
15008done
15009shopt -u extglob
15010
15011echo "$cmd -- creating new $TMPMNT/sbin/init"
15012create_init
15013if [ $? -ne 0 ]; then
15014 echo "$cmd -- ERROR creating init"
15015 cleanup
15016 exit 1
15017fi
15018
15019# copy LVMCONF into place or create a stripped down one from lvm dumpconfig
15020mkdir -p $TMPMNT/etc/lvm
15021if [ -n "$LVMCONF" ]; then
15022 echo "$cmd -- copying $LVMCONF to $TMPMNT/etc/lvm/lvm.conf"
15023 if [ -f "$LVMCONF" ]; then
15024 cp $LVMCONF $TMPMNT/etc/lvm/lvm.conf
15025 else
15026 echo "$cmd -- ERROR: $LVMCONF does not exist!"
15027 cleanup
15028 exit 1
15029 fi
15030else
15031 echo "$cmd -- creating new $TMPMNT/etc/lvm/lvm.conf"
15032 create_lvmconf
15033fi
15034
15035if [ -n "$RAID" ]; then
15036 RAIDLIST="$TMPMNT/etc/raid_autostart"
15037 echo "$cmd -- creating $RAIDLIST file."
15038 for device in $RAID; do
15039 echo $device >> $RAIDLIST
15040 done
15041fi
15042
15043# create modules.dep and /etc/modules files if needed
15044if [ -n "$MODULES" ]; then
15045 echo "$cmd -- creating $MODDIR/modules.dep file and $TMPMNT/etc/modules"
15046 depmod -b $TMPMNT $VERSION
15047 for module in $MODULES; do
15048 basename $module | sed 's/\.k\{0,1\}o$//' >> $TMPMNT/etc/modules
15049 done
15050fi
15051
15052verbose "removing $TMPMNT/lost+found"
15053rmdir $TMPMNT/lost+found
15054
15055echo "$cmd -- ummounting ram disk"
15056umount $DEVRAM
15057if [ $? -ne 0 ]; then
15058 echo "$cmd -- ERROR umounting $DEVRAM"
15059 cleanup 1
15060fi
15061
15062echo "$cmd -- creating compressed initrd $INITRD"
15063verbose "dd if=$DEVRAM bs=1k count=$INITRDSIZE | gzip -9"
15064dd if=$DEVRAM bs=1k count=$INITRDSIZE 2>/dev/null | gzip -9 > $INITRD
15065if [ $? -ne 0 ]; then
15066 echo "$cmd -- ERROR creating $INITRD"
15067 cleanup 1
15068fi
15069
15070
15071cat << FINALTXT
15072--------------------------------------------------------
15073Your initrd is ready in $INITRD
15074
15075Don't forget to set root=/dev/ram0 in kernel parameters
15076Don't forget to set lvm2root=/dev/VG/LV in kernel parameters, where LV is your root volume
15077If you use lilo try adding/modifying an entry similar to this one in lilo.conf:
15078
15079image=/boot/vmlinuz-lvm2-$VERSION
15080 label="ramdisk_LVM"
15081 initrd=/boot/initrd-lvm2-$VERSION.gz
15082 append="root=/dev/ram0 lvm2root=/dev/system/root <other parameters>"
15083
15084If using grub try adding/modifying an entry similar to this one in menu.lst
15085
15086title ramdisk LVM
15087 kernel /boot/vmlinuz-lvm2-$VERSION root=/dev/ram0 lvm2root=/dev/system/root <other parameters>
15088 initrd /boot/initrd-lvm2-$VERSION.gz
15089
15090You can also pass lvm2rescue to the kernel to get a shell
15091--------------------------------------------------------
15092FINALTXT
15093
15094cleanup 0
15095
15096\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/README\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003633\013062740170\0023040\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0http://poochiereds.net/svn/lvm2/
15097
15098This is the lvm2create_initrd script written by Miguel Cabeca, with some small
15099modifications by myself.
15100
15101Here are some other requirements and tips for using it:
15102
151031) this script uses busybox on the initrd image, hence busybox needs to be
15104installed when you create your initrd.
15105
151062) Make sure /etc/lvm/lvm.conf is set up correctly before running this. In
15107particular, if you're using LVM on RAID, make sure that you have a filter that
15108excludes the RAID component devices (this may not be necessary with the latest
15109patch by Luca Berra, but it doesn't hurt).
15110
151113) This initrd image does not support modules. If you need to plug in any
15112kernel modules during the initrd phase, then you'll need to hand-modify the
15113image.
15114
151154) The generated initrd image supports an 'lvm2rescue' mode as well. If you add
15116the parameter 'lvmrescue' on the kernel command line, it will run a shell at
15117the end of the initrd 'init' script. This can be helpful when trying to fix a
15118corrupt root volume or root LVM2 volume group.
15119
151205) No userspace md tools are installed, so if you're using LVM on RAID, then
15121you'll probably want to mark your RAID partitions as type 'fd' so that the
15122kernel will start them automagically (or hand-modify the image).
15123
151246) I'm not sure if devfs will work with this or not. udev, however does work,
15125and is recommended. Because the dm-* devices use dynamically allocated major
15126and minor numbers, kernel upgrades and the like can renumber your devices. To
15127fix this, you need to run a 'vgscan --mknodes' prior to fscking and mounting
15128your rootfs. Doing this with a static /dev creates a problem though -- you
15129will be modifying the root filesystem before it has been fsck'ed. udev gets
15130around this by mounting a ramdisk over /dev, but you'll probably need to add
15131a startup script that creates devices in /dev. The lvm2udev script in this
15132directory is an example of such a beast.
15133
15134--
15135Jeffrey Layton <jtlayton@poochiereds.net>
15136\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/lvm2create_initrd.pod\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000014561\013062740170\0026303\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0=head1 NAME
15137
15138lvm2create_initrd - create initrd image for booting to root\-on\-LVM2
15139
15140=head1 SYNOPSIS
15141
15142B<lvm2create_initrd> [ B<-h|--help> ] [ B<-v|--verbose> ] [ B<-c|--lvmconf> I</path/to/lvm.conf> ] [ B<-m|--modules> "I<module1 module2 ...>" ] [ B<-e|--extra> "I<file1 file2 ...>" ] [ B<-r|--raid> "I</dev/md1 /dev/md2 ...>" ]
15143[ B<-R|--raidconf> I</path/to/mdadm.conf> ] [ B<-M|--makedev> I<style> ]
15144
15145=head1 DESCRIPTION
15146
15147lvm2create_initrd creates an initial ramdisk (initrd) image suitable for booting to system that has an LVM2 volume as its root filesystem.
15148
15149To boot to such a setup, you'll
15150either need a bootloader that understands LVM2 volumes, or you'll need a
15151filesystem on a regular volume to act as a boot partition (typically mounted
15152on /boot).
15153
15154The resulting initrd image is fairly full-featured. It can harbor and load
15155kernel modules, start MD devices, and boot to a shell to perform rescue
15156operations.
15157
15158=head2 Booting to your initrd Image:
15159
15160The filesystem image created is an ext2fs filesystem, hence your kernel must have
15161ext2fs built into it statically in order to boot to the image.
15162
15163Once you create your initrd image, you must pass the correct options to the kernel when
15164you boot using it. Your kernel command line should look something like this:
15165
15166B<root=/dev/ram0 lvm2root=/dev/rootvg/root [ lvm2rescue ]>
15167
15168of course there may be other options.
15169
15170=over
15171
15172=item B<root=/dev/ram0>
15173
15174This option is required. It tells the kernel that the root filesystem should initially
15175be set to the ramdisk (/dev/ram0).
15176
15177=item B<lvm2root=/dev/rootvg/root>
15178
15179This option is also required. It tells the initrd image which LVM2 device the root filesystem is located on.
15180
15181=item B<lvm2rescue>
15182
15183Causes the initrd image to run a shell prior to mounting the root filesystem. This is
15184helpful in disaster situations where your initrd image is accessable, but there is
15185a problem with the root filesystem (corrupted image, incorrect device setup, etc.). This
15186option is (of course) optional.
15187
15188=back
15189
15190=head1 OPTIONS
15191
15192Most of parameters that can be set via command-line options can also be set
15193via environment variables. Options specified on the command-line always take
15194precedence.
15195
15196=over
15197
15198=item B<-h|--help>
15199
15200Display short help text and exit. If used, other options are ignored.
15201
15202=item B<-v|--verbose>
15203
15204Turn on extra verbosity for debugging, etc.
15205
15206=item B<-c|--lvmconf> I</path/to/lvm.conf>
15207
15208Specify an lvm.conf file to include in the image. This is useful if you have
15209special device filters or other options you wish to use during the initrd
15210stage. If this option is not
15211included, then a lvm.conf file is created that contains only the current
15212device filter from an B<lvm dumpconfig>. This can also be set via the B<$LVMCONF>
15213environment variable.
15214
15215=item B<-m|--modules> "I</path/to/module1.ko /path/to/module2.ko ...>"
15216
15217Specify modules to include and plug in during the initrd phase. This option
15218takes a quoted, space-separated list of modules. Full pathnames are required.
15219These modules are loaded into the kernel early in the initrd phase of the boot
15220process. The current modprobe.conf file is also copied to the initrd image
15221as well. This can also be specified via the B<$MODULES> environment variable.
15222
15223=item B<-e|--extra> "I</path/to/file1 /path/to/file2 ...>"
15224
15225Extra files that should be included in the initrd image. These files will be
15226copied to the same location in the initrd image that they are in the current
15227filesystem. Again full pathnames are required. This can also be specified via
15228the B<$EXTRAFILES> environment variable.
15229
15230=item B<-r|--raid> "I</dev/md1 /dev/md2...>"
15231
15232RAID devices to be started prior to scanning for LVM2 volume groups. If this
15233option is used then then B<mdadm> program must be installed. This can also be
15234specified via the B<$RAID> environment variable.
15235
15236=item B<-R|--raidconf> "I</path/to/mdadm.conf>"
15237
15238Location of a mdadm.conf file to include. If this is not specified, then no
15239files are included, and any devices specified with the B<-r> option above
15240must have minor numbers that match their superblock values. This can also be
15241specified via the B<$RAIDCONF> environment variable.
15242
15243=item B<-M|--makedev> I<style>
15244
15245Set MAKEDEV invocation style. The script currently supports 3 styles of
15246MAKEDEV programs I<debian>, I<redhat> and I<gentoo>. The default is I<debian>.
15247Set to I<redhat> if using the RedHat/Fedora binary MAKEDEV program. I<gentoo>
15248has the same binary but in /sbin instead of /dev. Please send a bug report to
15249maintainer if your distribution doesn't work with any of the current options.
15250
15251=back
15252
15253=head1 ENVIRONMENT VARIABLES
15254
15255Most of the options to this script can be set via environment variables. In
15256situations where both are set, then the command-line options take precedence.
15257
15258=over
15259
15260=item B<$LVMCONF>
15261
15262Same as -c option.
15263
15264=item B<$MODULES>
15265
15266Same as -m option.
15267
15268=item B<$EXTRAFILES>
15269
15270Same as -e option.
15271
15272=item B<$RAID>
15273
15274Same as -r option.
15275
15276=item B<$RAIDCONF>
15277
15278Same as -R option.
15279
15280=item B<$MAKEDEV>
15281
15282Same as -M option.
15283
15284=item B<$BASICDEVICES>
15285
15286Overrides the default value of $BASICDEVICES in the script (which is "std consoleonly fd"). These values are passed to the B<MAKEDEV> program to create device
15287entries in the initrd image.
15288
15289=item B<$BLOCKDEVICES>
15290
15291Overrides the default value of $BLOCKDEVICES in the script (which is "md hda hdb hdc hdd sda sdb sdc sdd"). This value is passed to the B<MAKEDEV> program to
15292create device entries in the initrd image.
15293
15294=item B<$BINFILES>
15295
15296Overrides the default value of $BINFILES (which is "/lib/lvm-200/lvm /bin/bash /bin/busybox /sbin/pivot_root"). The difference between using this and adding
15297a file to the $EXTRAFILES list above is that libraries that these depend upon are also included. You can still use $EXTRAFILES to achieve the same effect, but
15298you must resolve library dependencies youself.
15299
15300=item B<$INITRDSIZE>
15301
15302Force a particular size for your initrd image. The default is to total up the size of
15303the included files and to add 512K as a buffer.
15304
15305=back
15306
15307=head1 BUGS
15308
15309I don't like having to specify a -M option to set the MAKEDEV style, but I know
15310of no way to reliably detect what type of MAKEDEV is being used. We'll probably
15311have to add other MAKEDEV styles in the future as this script is tested on
15312other distributions.
15313
15314=head1 AUTHORS
15315
15316The script was originally written by Miguel Cabeca, with significant
15317improvements by Jeffrey Layton. Comments, bug reports and patches should be
15318sent to Jeffrey Layton at S<B<jtlayton@poochiereds.net>>.
15319
15320=head1 SEE ALSO
15321
15322B<MAKEDEV>(8), B<mdadm>(8), B<busybox>(8), B<lvm.conf>(5)
15323\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/lvm2udev\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001324\013062740170\0023642\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/sh
15324
15325# $Id$
15326
15327# simple startup script to create lvm2 devices if /dev is a mountpoint, there
15328# are active dm- devices, and an executable /sbin/vgscan.
15329
15330# this script is licensed under GPLv2.
15331# See http://www.gnu.org/licenses/gpl.html
15332
15333case $1 in
15334start)
15335 # is /dev a mountpoint?
15336 mountpoint -q /dev
15337 DEVMNTPOINT=$?
15338
15339 # check to see if there are active dm entries under /sys
15340 ls /sys/block/dm-*/dev 1>/dev/null 2>&1
15341 ACTIVEDMDEVS=$?
15342
15343 # mknodes if conditions are right
15344 if [ $DEVMNTPOINT -eq 0 -a $ACTIVEDMDEVS -eq 0 -a -x /sbin/vgscan ]; then
15345 /sbin/vgscan --mknodes --ignorelockingfailure
15346 fi
15347 ;;
15348stop)
15349 exit 0
15350 ;;
15351*)
15352 echo "usage:"
15353 echo " $0 start|stop"
15354 ;;
15355esac
15356\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2create_initrd/lvm2create_initrd.8\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000030151\013062740170\0025661\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
15357.\"
15358.\" Standard preamble:
15359.\" ========================================================================
15360.de Sp \" Vertical space (when we can't use .PP)
15361.if t .sp .5v
15362.if n .sp
15363..
15364.de Vb \" Begin verbatim text
15365.ft CW
15366.nf
15367.ne \\$1
15368..
15369.de Ve \" End verbatim text
15370.ft R
15371.fi
15372..
15373.\" Set up some character translations and predefined strings. \*(-- will
15374.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
15375.\" double quote, and \*(R" will give a right double quote. \*(C+ will
15376.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
15377.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
15378.\" nothing in troff, for use with C<>.
15379.tr \(*W-
15380.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
15381.ie n \{\
15382. ds -- \(*W-
15383. ds PI pi
15384. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
15385. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
15386. ds L" ""
15387. ds R" ""
15388. ds C` ""
15389. ds C' ""
15390'br\}
15391.el\{\
15392. ds -- \|\(em\|
15393. ds PI \(*p
15394. ds L" ``
15395. ds R" ''
15396'br\}
15397.\"
15398.\" Escape single quotes in literal strings from groff's Unicode transform.
15399.ie \n(.g .ds Aq \(aq
15400.el .ds Aq '
15401.\"
15402.\" If the F register is turned on, we'll generate index entries on stderr for
15403.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
15404.\" entries marked with X<> in POD. Of course, you'll have to process the
15405.\" output yourself in some meaningful fashion.
15406.ie \nF \{\
15407. de IX
15408. tm Index:\\$1\t\\n%\t"\\$2"
15409..
15410. nr % 0
15411. rr F
15412.\}
15413.el \{\
15414. de IX
15415..
15416.\}
15417.\"
15418.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
15419.\" Fear. Run. Save yourself. No user-serviceable parts.
15420. \" fudge factors for nroff and troff
15421.if n \{\
15422. ds #H 0
15423. ds #V .8m
15424. ds #F .3m
15425. ds #[ \f1
15426. ds #] \fP
15427.\}
15428.if t \{\
15429. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
15430. ds #V .6m
15431. ds #F 0
15432. ds #[ \&
15433. ds #] \&
15434.\}
15435. \" simple accents for nroff and troff
15436.if n \{\
15437. ds ' \&
15438. ds ` \&
15439. ds ^ \&
15440. ds , \&
15441. ds ~ ~
15442. ds /
15443.\}
15444.if t \{\
15445. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
15446. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
15447. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
15448. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
15449. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
15450. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
15451.\}
15452. \" troff and (daisy-wheel) nroff accents
15453.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
15454.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
15455.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
15456.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
15457.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
15458.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
15459.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
15460.ds ae a\h'-(\w'a'u*4/10)'e
15461.ds Ae A\h'-(\w'A'u*4/10)'E
15462. \" corrections for vroff
15463.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
15464.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
15465. \" for low resolution devices (crt and lpr)
15466.if \n(.H>23 .if \n(.V>19 \
15467\{\
15468. ds : e
15469. ds 8 ss
15470. ds o a
15471. ds d- d\h'-1'\(ga
15472. ds D- D\h'-1'\(hy
15473. ds th \o'bp'
15474. ds Th \o'LP'
15475. ds ae ae
15476. ds Ae AE
15477.\}
15478.rm #[ #] #H #V #F C
15479.\" ========================================================================
15480.\"
15481.IX Title "lvm2create_initrd 8"
15482.TH lvm2create_initrd 8 "2011-11-12" "lvm2create_initrd" "create LVM2 initrd"
15483.\" For nroff, turn off justification. Always turn off hyphenation; it makes
15484.\" way too many mistakes in technical documents.
15485.if n .ad l
15486.nh
15487.SH "NAME"
15488lvm2create_initrd \- create initrd image for booting to root\e\-on\e\-LVM2
15489.SH "SYNOPSIS"
15490.IX Header "SYNOPSIS"
15491\&\fBlvm2create_initrd\fR [ \fB\-h|\-\-help\fR ] [ \fB\-v|\-\-verbose\fR ] [ \fB\-c|\-\-lvmconf\fR \fI/path/to/lvm.conf\fR ] [ \fB\-m|\-\-modules\fR "\fImodule1 module2 ...\fR" ] [ \fB\-e|\-\-extra\fR "\fIfile1 file2 ...\fR" ] [ \fB\-r|\-\-raid\fR "\fI/dev/md1 /dev/md2 ...\fR" ]
15492[ \fB\-R|\-\-raidconf\fR \fI/path/to/mdadm.conf\fR ] [ \fB\-M|\-\-makedev\fR \fIstyle\fR ]
15493.SH "DESCRIPTION"
15494.IX Header "DESCRIPTION"
15495lvm2create_initrd creates an initial ramdisk (initrd) image suitable for booting to system that has an \s-1LVM2\s0 volume as its root filesystem.
15496.PP
15497To boot to such a setup, you'll
15498either need a bootloader that understands \s-1LVM2\s0 volumes, or you'll need a
15499filesystem on a regular volume to act as a boot partition (typically mounted
15500on /boot).
15501.PP
15502The resulting initrd image is fairly full-featured. It can harbor and load
15503kernel modules, start \s-1MD\s0 devices, and boot to a shell to perform rescue
15504operations.
15505.SS "Booting to your initrd Image:"
15506.IX Subsection "Booting to your initrd Image:"
15507The filesystem image created is an ext2fs filesystem, hence your kernel must have
15508ext2fs built into it statically in order to boot to the image.
15509.PP
15510Once you create your initrd image, you must pass the correct options to the kernel when
15511you boot using it. Your kernel command line should look something like this:
15512.PP
15513\&\fBroot=/dev/ram0 lvm2root=/dev/rootvg/root [ lvm2rescue ]\fR
15514.PP
15515of course there may be other options.
15516.IP "\fBroot=/dev/ram0\fR" 4
15517.IX Item "root=/dev/ram0"
15518This option is required. It tells the kernel that the root filesystem should initially
15519be set to the ramdisk (/dev/ram0).
15520.IP "\fBlvm2root=/dev/rootvg/root\fR" 4
15521.IX Item "lvm2root=/dev/rootvg/root"
15522This option is also required. It tells the initrd image which \s-1LVM2\s0 device the root filesystem is located on.
15523.IP "\fBlvm2rescue\fR" 4
15524.IX Item "lvm2rescue"
15525Causes the initrd image to run a shell prior to mounting the root filesystem. This is
15526helpful in disaster situations where your initrd image is accessable, but there is
15527a problem with the root filesystem (corrupted image, incorrect device setup, etc.). This
15528option is (of course) optional.
15529.SH "OPTIONS"
15530.IX Header "OPTIONS"
15531Most of parameters that can be set via command-line options can also be set
15532via environment variables. Options specified on the command-line always take
15533precedence.
15534.IP "\fB\-h|\-\-help\fR" 4
15535.IX Item "-h|--help"
15536Display short help text and exit. If used, other options are ignored.
15537.IP "\fB\-v|\-\-verbose\fR" 4
15538.IX Item "-v|--verbose"
15539Turn on extra verbosity for debugging, etc.
15540.IP "\fB\-c|\-\-lvmconf\fR \fI/path/to/lvm.conf\fR" 4
15541.IX Item "-c|--lvmconf /path/to/lvm.conf"
15542Specify an lvm.conf file to include in the image. This is useful if you have
15543special device filters or other options you wish to use during the initrd
15544stage. If this option is not
15545included, then a lvm.conf file is created that contains only the current
15546device filter from an \fBlvm dumpconfig\fR. This can also be set via the \fB\f(CB$LVMCONF\fB\fR
15547environment variable.
15548.ie n .IP "\fB\-m|\-\-modules\fR ""\fI/path/to/module1.ko /path/to/module2.ko ...\fR""" 4
15549.el .IP "\fB\-m|\-\-modules\fR ``\fI/path/to/module1.ko /path/to/module2.ko ...\fR''" 4
15550.IX Item "-m|--modules ""/path/to/module1.ko /path/to/module2.ko ..."""
15551Specify modules to include and plug in during the initrd phase. This option
15552takes a quoted, space-separated list of modules. Full pathnames are required.
15553These modules are loaded into the kernel early in the initrd phase of the boot
15554process. The current modprobe.conf file is also copied to the initrd image
15555as well. This can also be specified via the \fB\f(CB$MODULES\fB\fR environment variable.
15556.ie n .IP "\fB\-e|\-\-extra\fR ""\fI/path/to/file1 /path/to/file2 ...\fR""" 4
15557.el .IP "\fB\-e|\-\-extra\fR ``\fI/path/to/file1 /path/to/file2 ...\fR''" 4
15558.IX Item "-e|--extra ""/path/to/file1 /path/to/file2 ..."""
15559Extra files that should be included in the initrd image. These files will be
15560copied to the same location in the initrd image that they are in the current
15561filesystem. Again full pathnames are required. This can also be specified via
15562the \fB\f(CB$EXTRAFILES\fB\fR environment variable.
15563.ie n .IP "\fB\-r|\-\-raid\fR ""\fI/dev/md1 /dev/md2...\fR""" 4
15564.el .IP "\fB\-r|\-\-raid\fR ``\fI/dev/md1 /dev/md2...\fR''" 4
15565.IX Item "-r|--raid ""/dev/md1 /dev/md2..."""
15566\&\s-1RAID\s0 devices to be started prior to scanning for \s-1LVM2\s0 volume groups. If this
15567option is used then then \fBmdadm\fR program must be installed. This can also be
15568specified via the \fB\f(CB$RAID\fB\fR environment variable.
15569.ie n .IP "\fB\-R|\-\-raidconf\fR ""\fI/path/to/mdadm.conf\fR""" 4
15570.el .IP "\fB\-R|\-\-raidconf\fR ``\fI/path/to/mdadm.conf\fR''" 4
15571.IX Item "-R|--raidconf ""/path/to/mdadm.conf"""
15572Location of a mdadm.conf file to include. If this is not specified, then no
15573files are included, and any devices specified with the \fB\-r\fR option above
15574must have minor numbers that match their superblock values. This can also be
15575specified via the \fB\f(CB$RAIDCONF\fB\fR environment variable.
15576.IP "\fB\-M|\-\-makedev\fR \fIstyle\fR" 4
15577.IX Item "-M|--makedev style"
15578Set \s-1MAKEDEV\s0 invocation style. The script currently supports 3 styles of
15579\&\s-1MAKEDEV\s0 programs \fIdebian\fR, \fIredhat\fR and \fIgentoo\fR. The default is \fIdebian\fR.
15580Set to \fIredhat\fR if using the RedHat/Fedora binary \s-1MAKEDEV\s0 program. \fIgentoo\fR
15581has the same binary but in /sbin instead of /dev. Please send a bug report to
15582maintainer if your distribution doesn't work with any of the current options.
15583.SH "ENVIRONMENT VARIABLES"
15584.IX Header "ENVIRONMENT VARIABLES"
15585Most of the options to this script can be set via environment variables. In
15586situations where both are set, then the command-line options take precedence.
15587.ie n .IP "\fB\fB$LVMCONF\fB\fR" 4
15588.el .IP "\fB\f(CB$LVMCONF\fB\fR" 4
15589.IX Item "$LVMCONF"
15590Same as \-c option.
15591.ie n .IP "\fB\fB$MODULES\fB\fR" 4
15592.el .IP "\fB\f(CB$MODULES\fB\fR" 4
15593.IX Item "$MODULES"
15594Same as \-m option.
15595.ie n .IP "\fB\fB$EXTRAFILES\fB\fR" 4
15596.el .IP "\fB\f(CB$EXTRAFILES\fB\fR" 4
15597.IX Item "$EXTRAFILES"
15598Same as \-e option.
15599.ie n .IP "\fB\fB$RAID\fB\fR" 4
15600.el .IP "\fB\f(CB$RAID\fB\fR" 4
15601.IX Item "$RAID"
15602Same as \-r option.
15603.ie n .IP "\fB\fB$RAIDCONF\fB\fR" 4
15604.el .IP "\fB\f(CB$RAIDCONF\fB\fR" 4
15605.IX Item "$RAIDCONF"
15606Same as \-R option.
15607.ie n .IP "\fB\fB$MAKEDEV\fB\fR" 4
15608.el .IP "\fB\f(CB$MAKEDEV\fB\fR" 4
15609.IX Item "$MAKEDEV"
15610Same as \-M option.
15611.ie n .IP "\fB\fB$BASICDEVICES\fB\fR" 4
15612.el .IP "\fB\f(CB$BASICDEVICES\fB\fR" 4
15613.IX Item "$BASICDEVICES"
15614Overrides the default value of \f(CW$BASICDEVICES\fR in the script (which is \*(L"std consoleonly fd\*(R"). These values are passed to the \fB\s-1MAKEDEV\s0\fR program to create device
15615entries in the initrd image.
15616.ie n .IP "\fB\fB$BLOCKDEVICES\fB\fR" 4
15617.el .IP "\fB\f(CB$BLOCKDEVICES\fB\fR" 4
15618.IX Item "$BLOCKDEVICES"
15619Overrides the default value of \f(CW$BLOCKDEVICES\fR in the script (which is \*(L"md hda hdb hdc hdd sda sdb sdc sdd\*(R"). This value is passed to the \fB\s-1MAKEDEV\s0\fR program to
15620create device entries in the initrd image.
15621.ie n .IP "\fB\fB$BINFILES\fB\fR" 4
15622.el .IP "\fB\f(CB$BINFILES\fB\fR" 4
15623.IX Item "$BINFILES"
15624Overrides the default value of \f(CW$BINFILES\fR (which is \*(L"/lib/lvm\-200/lvm /bin/bash /bin/busybox /sbin/pivot_root\*(R"). The difference between using this and adding
15625a file to the \f(CW$EXTRAFILES\fR list above is that libraries that these depend upon are also included. You can still use \f(CW$EXTRAFILES\fR to achieve the same effect, but
15626you must resolve library dependencies youself.
15627.ie n .IP "\fB\fB$INITRDSIZE\fB\fR" 4
15628.el .IP "\fB\f(CB$INITRDSIZE\fB\fR" 4
15629.IX Item "$INITRDSIZE"
15630Force a particular size for your initrd image. The default is to total up the size of
15631the included files and to add 512K as a buffer.
15632.SH "BUGS"
15633.IX Header "BUGS"
15634I don't like having to specify a \-M option to set the \s-1MAKEDEV\s0 style, but I know
15635of no way to reliably detect what type of \s-1MAKEDEV\s0 is being used. We'll probably
15636have to add other \s-1MAKEDEV\s0 styles in the future as this script is tested on
15637other distributions.
15638.SH "AUTHORS"
15639.IX Header "AUTHORS"
15640The script was originally written by Miguel Cabeca, with significant
15641improvements by Jeffrey Layton. Comments, bug reports and patches should be
15642sent to Jeffrey Layton at \fBjtlayton@poochiereds.net\fR.
15643.SH "SEE ALSO"
15644.IX Header "SEE ALSO"
15645\&\fB\s-1MAKEDEV\s0\fR(8), \fBmdadm\fR(8), \fBbusybox\fR(8), \fBlvm.conf\fR(5)
15646\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_cluster_activation_red_hat.sh.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002562\013062740170\0026034\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
15647
15648sbindir=@sbindir@
15649
15650lvm_vgchange=${sbindir}/vgchange
15651lvm_vgscan=${sbindir}/vgscan
15652lvm_vgs=${sbindir}/vgs
15653lvm_lvm=${sbindir}/lvm
15654
15655clustered_vgs() {
15656 ${lvm_vgs} --noheadings -o vg_name -S 'vg_clustered=1' 2>/dev/null
15657}
15658
15659activate() {
15660 eval local $(${lvm_lvm} dumpconfig devices/obtain_device_list_from_udev 2>/dev/null) 2>/dev/null
15661 if [ $? -ne 0 ]; then
15662 echo "Warning: expected single couple of key=value in output of dumpconfig"
15663 fi
15664
15665 if [ -z $obtain_device_list_from_udev -o $obtain_device_list_from_udev -ne 1 ]; then
15666 echo -n "lvm.conf option obtain_device_list_from_udev!=1: Executing vgscan"
15667 ${lvm_vgscan} > /dev/null 2>&1
15668 fi
15669
15670 echo -n "Activating ${LVM_VGS:-"all VG(s)"}: "
15671 # Respect activation/auto_activation_volume_list!
15672 # Call "-aay" which is equal to "-aly" but respects this list.
15673 ${lvm_vgchange} -aay $LVM_VGS || return 1
15674
15675 return 0
15676}
15677
15678deactivate()
15679{
15680 # NOTE: following section will be replaced by blkdeactivate script
15681 # with option supporting request to deactivate all clustered volume
15682 # groups in the system
15683 [ -z $LVM_VGS ] && LVM_VGS="$(clustered_vgs)"
15684 if [ -n "$LVM_VGS" ]; then
15685 echo -n "Deactivating clustered VG(s): "
15686 ${lvm_vgchange} -anl $LVM_VGS || return 1
15687 fi
15688
15689 return 0
15690}
15691
15692case "$1" in
15693 deactivate)
15694 deactivate
15695 rtrn=$?
15696 ;;
15697 activate)
15698 activate
15699 rtrn=$?
15700 ;;
15701 *)
15702 echo $"Usage: $0 {activate|deactivate}"
15703 rtrn=3
15704 ;;
15705esac
15706
15707exit $rtrn
15708\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/VolumeGroup.ocf\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015412\013062740170\0021516\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/sh
15709#
15710# VolumeGroup
15711#
15712# Description: Manages an LVM2 volume group as an HA resource in
15713# an OCF-compliant cluster
15714#
15715#
15716# Authors: Alan Robertson, Lars Marowsky-Bree, Florian Haas,
15717# and others from the Linux-HA project
15718# License: GNU General Public License (GPL)
15719# Copyright: (C) 2002 - 2005 International Business Machines, Inc.
15720# (C) 2010 LINBIT HA-Solutions GmbH
15721#
15722# This code significantly inspired by the LVM resource
15723# in FailSafe by Lars Marowsky-Bree
15724#
15725#######################################################################
15726# Initialization:
15727
15728: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
15729. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
15730
15731#######################################################################
15732
15733
15734usage() {
15735 methods=`VolumeGroup_methods`
15736 methods=`echo $methods | tr ' ' '|'`
15737 cat <<EOF
15738 usage: $0 $methods
15739
15740 $0 manages an LVM Volume Group (VG) as an HA resource
15741
15742 The 'start' operation brings the given volume online
15743 The 'stop' operation takes the given volume offline
15744 The 'status' operation reports whether the volume is available
15745 The 'monitor' operation reports whether the volume seems present
15746 The 'validate-all' operation checks whether the OCF parameters are valid
15747 The 'methods' operation reports on the methods $0 supports
15748
15749EOF
15750}
15751
15752meta_data() {
15753 cat <<EOF
15754<?xml version="1.0"?>
15755<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
15756<resource-agent name="VolumeGroup">
15757<version>1.0</version>
15758
15759<longdesc lang="en">
15760Resource script for an LVM Volume Group.
15761</longdesc>
15762<shortdesc lang="en">Controls the availability of an LVM Volume Group</shortdesc>
15763
15764<parameters>
15765<parameter name="volgrpname" unique="0" required="1">
15766<longdesc lang="en">
15767The name of volume group.
15768</longdesc>
15769<shortdesc lang="en">Volume group name</shortdesc>
15770<content type="string" default="" />
15771</parameter>
15772<parameter name="exclusive" unique="0" required="0">
15773<longdesc lang="en">
15774If set, the volume group will be activated exclusively.
15775</longdesc>
15776<shortdesc lang="en">Exclusive activation</shortdesc>
15777<content type="boolean" default="false" />
15778</parameter>
15779</parameters>
15780
15781<actions>
15782<action name="start" timeout="30" />
15783<action name="stop" timeout="30" />
15784<action name="status" timeout="30" />
15785<action name="monitor" depth="0" timeout="30" interval="10" />
15786<action name="methods" timeout="5" />
15787<action name="meta-data" timeout="5" />
15788<action name="validate-all" timeout="5" />
15789</actions>
15790</resource-agent>
15791EOF
15792}
15793
15794#
15795# methods: What methods/operations do we support?
15796#
15797VolumeGroup_methods() {
15798 cat <<EOF
15799 start
15800 stop
15801 status
15802 monitor
15803 methods
15804 validate-all
15805 usage
15806EOF
15807}
15808
15809#
15810# Report on LVM volume status. VG may be reported as active
15811# ($OCF_SUCCESS) or inactive ($OCF_NOT_RUNNING)
15812#
15813VolumeGroup_status() {
15814
15815 VGOUT=`vgdisplay -v $OCF_RESKEY_volgrpname 2>&1` || exit $OCF_ERR_GENERIC
15816 echo "$VGOUT" | grep -i 'Status[ \t]*available' >/dev/null
15817 rc=$?
15818
15819 if [ $rc -eq 0 ]; then
15820 ocf_log debug "LVM Volume Group $OCF_RESKEY_volgrpname is available (started)"
15821 else
15822 ocf_log debug "LVM Volume Group $OCF_RESKEY_volgrpname is not available (stopped)"
15823 return $OCF_NOT_RUNNING
15824 fi
15825
15826 if echo "$VGOUT" | grep -i 'Access.*read/write' >/dev/null; then
15827 ocf_log debug "Volume $OCF_RESKEY_volgrpname is available read/write (running)"
15828 else
15829 ocf_log debug "Volume $OCF_RESKEY_volgrpname is available read-only (running)"
15830 fi
15831
15832 return $OCF_SUCCESS
15833}
15834
15835#
15836# Monitor the volume - does it really seem to be working? May report
15837# $OCF_SUCCESS or $OCF_NOT_RUNNING like VolumeGroup_status, plus
15838# $OCF_ERR_GENERIC in case vgck reports an error.
15839#
15840VolumeGroup_monitor() {
15841 if ! VolumeGroup_status $OCF_RESKEY_volgrpname; then
15842 ocf_log info "LVM Volume Group $OCF_RESKEY_volgrpname is offline"
15843 return $OCF_NOT_RUNNING
15844 fi
15845
15846 ocf_run vgck $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC
15847
15848 return $OCF_SUCCESS
15849}
15850
15851#
15852# Activate the volume group, either locally (if $OCF_RESKEY_exclusive
15853# is false or unset), or exclusively (if $OCF_RESKEY_exclusive is
15854# true).
15855# Either returns successfully, or exits with $OCF_ERR_GENERIC.
15856#
15857VolumeGroup_start() {
15858
15859 ocf_log info "Activating volume group $OCF_RESKEY_volgrpname"
15860 ocf_run vgscan
15861
15862 local active_mode
15863 active_mode="ly"
15864 if ocf_is_true "$OCF_RESKEY_exclusive" ; then
15865 active_mode="ey"
15866 fi
15867
15868 ocf_run vgchange -a $active_mode $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC
15869
15870 if ! VolumeGroup_status $OCF_RESKEY_volgrpname; then
15871 ocf_log err "LVM: $OCF_RESKEY_volgrpname did not activate correctly"
15872 exit $OCF_ERR_GENERIC
15873 fi
15874
15875 return $OCF_SUCCESS
15876}
15877
15878#
15879# Deactivate the volume group.
15880# Either returns successfully, or exits with $OCF_ERR_GENERIC.
15881#
15882VolumeGroup_stop() {
15883 if ! VolumeGroup_status; then
15884 ocf_log debug "Volume Group $OCF_RESKEY_volgrpname already stopped"
15885 return $OCF_SUCCESS
15886 fi
15887
15888 ocf_log info "Deactivating volume group $OCF_RESKEY_volgrpname"
15889 ocf_run vgchange -a ln $OCF_RESKEY_volgrpname || exit $OCF_ERR_GENERIC
15890
15891 if VolumeGroup_status; then
15892 ocf_log err "LVM: $OCF_RESKEY_volgrpname did not stop correctly"
15893 exit $OCF_ERR_GENERIC
15894 fi
15895
15896 return $OCF_SUCCESS
15897}
15898
15899#
15900# Check whether the OCF instance parameters are valid.
15901# Either returns successfully, or exits with
15902# $OCF_ERR_CONFIGURED if required parameters are missing;
15903# $OCF_ERR_INSTALLED if required binaries are missing;
15904# $OCF_ERR_GENERIC in case of any other error.
15905#
15906VolumeGroup_validate_all() {
15907
15908 if [ -z $OCF_RESKEY_volgrpname ]; then
15909 ocf_log err 'Missing required parameter "volgrpname"!'
15910 exit $OCF_ERR_CONFIGURED
15911 fi
15912
15913 check_binary vgchange
15914 check_binary vgck
15915 check_binary vgdisplay
15916
15917 # Run the following tests only if we're not invoked by a probe
15918 # operation
15919 if ! ocf_is_probe; then
15920 # Off-the-shelf tests...
15921 vgck "$OCF_RESKEY_volgrpname" >/dev/null 2>&1
15922 if [ $? -ne 0 ]; then
15923 ocf_log err "Volume group $OCF_RESKEY_volgrpname does not exist or contains error!"
15924 exit $OCF_ERR_GENERIC
15925 fi
15926
15927 # Double-check
15928 vgdisplay -v "$OCF_RESKEY_volgrpname" >/dev/null 2>&1
15929 if [ $? -ne 0 ]; then
15930 ocf_log err "Volume group $OCF_RESKEY_volgrpname does not exist or contains error!"
15931 exit $OCF_ERR_GENERIC
15932 fi
15933 fi
15934
15935 return $OCF_SUCCESS
15936}
15937
15938#
15939# 'main' starts here...
15940#
15941if [ $# -ne 1 ]; then
15942 usage
15943 exit $OCF_ERR_ARGS
15944fi
15945
15946case $1 in
15947 meta-data) meta_data
15948 exit $OCF_SUCCESS;;
15949
15950 methods) VolumeGroup_methods
15951 exit $OCF_SUCCESS;;
15952
15953 usage) usage
15954 exit $OCF_SUCCESS;;
15955 *) ;;
15956esac
15957
15958# Everything except usage and meta-data must pass the validate test
15959VolumeGroup_validate_all
15960
15961# What kind of method was invoked?
15962case "$1" in
15963 start)
15964 VolumeGroup_start
15965 ;;
15966 stop)
15967 VolumeGroup_stop
15968 ;;
15969 status)
15970 VolumeGroup_status
15971 ;;
15972 monitor)
15973 VolumeGroup_monitor
15974 ;;
15975 validate-all)
15976 ;;
15977 notify|promote|demote|migrate_from|migrate_to)
15978 usage
15979 exit $OCF_ERR_UNIMPLEMENTED
15980 ;;
15981 *) usage
15982 exit $OCF_ERR_ARGS
15983 ;;
15984esac
15985
15986exit $?
15987\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_cluster_activation_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000703\013062740170\0030625\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
15988Description=Clustered LVM volumes activation service
15989Requires=lvm2-clvmd.service
15990After=lvm2-clvmd.service lvm2-cmirrord.service
15991OnFailure=lvm2-clvmd.service
15992DefaultDependencies=no
15993Conflicts=shutdown.target
15994
15995[Service]
15996Type=simple
15997RemainAfterExit=yes
15998EnvironmentFile=-/etc/default/clvmd
15999ExecStart=@systemdutildir@/lvm2-cluster-activation activate
16000ExecStop=@systemdutildir@/lvm2-cluster-activation deactivate
16001
16002[Install]
16003WantedBy=multi-user.target
16004\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_pvscan_systemd_red_hat@.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000633\013062740170\0026317\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
16005Description=LVM2 PV scan on device %i
16006Documentation=man:pvscan(8)
16007DefaultDependencies=no
16008StartLimitInterval=0
16009BindsTo=dev-block-%i.device
16010Requires=lvm2-lvmetad.socket
16011After=lvm2-lvmetad.socket lvm2-lvmetad.service
16012Before=shutdown.target
16013Conflicts=shutdown.target
16014
16015[Service]
16016Type=oneshot
16017RemainAfterExit=yes
16018ExecStart=@sbindir@/lvm pvscan --cache --activate ay %i
16019ExecStop=@sbindir@/lvm pvscan --cache %i
16020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_lvmpolld_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000524\013062740170\0026555\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
16021Description=LVM2 poll daemon
16022Documentation=man:lvmpolld(8)
16023Requires=lvm2-lvmpolld.socket
16024After=lvm2-lvmpolld.socket
16025DefaultDependencies=no
16026Conflicts=shutdown.target
16027
16028[Service]
16029Type=simple
16030NonBlocking=true
16031ExecStart=@sbindir@/lvmpolld -t 60 -f
16032Environment=SD_ACTIVATION=1
16033PIDFile=@LVMPOLLD_PIDFILE@
16034
16035[Install]
16036WantedBy=sysinit.target
16037\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/relpath.awk\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000002150\013062740170\0020702\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/usr/bin/awk -f
16038#
16039# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
16040#
16041# This file is part of LVM2.
16042#
16043# This copyrighted material is made available to anyone wishing to use,
16044# modify, copy, or redistribute it subject to the terms and conditions
16045# of the GNU General Public License v.2.
16046#
16047# You should have received a copy of the GNU General Public License
16048# along with this program; if not, write to the Free Software Foundation,
16049# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16050
16051# relpath.awk: Script is used to calculate relative path
16052# between two real absolute paths.
16053#
16054# echo /a/b/c/d /a/b/e/f | relpath.awk
16055# -> ../../e/f/
16056
16057{
16058 length_from = split($1, from, "/");
16059 length_to = split($2, to, "/") ;
16060 l = 1;
16061 while (l <= length_from && l <= length_to && from[l] == to[l])
16062 l++;
16063 for (i = l; i <= length_from && length(from[i]); i++) {
16064 if (i > l)
16065 p = sprintf("%s/", p);
16066 p = sprintf("%s..", p);
16067 }
16068 for (i = l; i <= length_to && length(to[i]); i++) {
16069 if (length(p) > 0)
16070 p = sprintf("%s/", p);
16071 p = sprintf("%s%s", p, to[i]);
16072 }
16073 if (length(p))
16074 p = sprintf("%s/", p);
16075 print p
16076}
16077\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/scripts/lvm2_clvmd_systemd_red_hat.service.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001040\013062740170\0026023\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0[Unit]
16078Description=Clustered LVM daemon
16079Documentation=man:clvmd(8)
16080After=dlm.service corosync.service
16081Before=remote-fs-pre.target
16082Requires=network.target dlm.service corosync.service
16083RefuseManualStart=true
16084RefuseManualStop=true
16085StopWhenUnneeded=true
16086DefaultDependencies=no
16087Conflicts=shutdown.target
16088
16089[Service]
16090Type=forking
16091Environment=CLVMD_OPTS=-T30
16092EnvironmentFile=-/etc/default/clvmd
16093ExecStart=/usr/sbin/clvmd $CLVMD_OPTS
16094SuccessExitStatus=5
16095TimeoutStartSec=30
16096TimeoutStopSec=10
16097OOMScoreAdjust=-1000
16098Restart=on-abort
16099PIDFile=@CLVMD_PIDFILE@
16100\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0016012\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/69-dm-lvm-metad.rules.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010125\013062740170\0022212\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
16101#
16102# This file is part of LVM2.
16103
16104# Udev rules for LVM.
16105#
16106# Scan all block devices having a PV label for LVM metadata.
16107# Store this information in LVMetaD (the LVM metadata daemon) and maintain LVM
16108# metadata state for improved performance by avoiding further scans while
16109# running subsequent LVM commands or while using lvm2app library.
16110# Also, notify LVMetaD about any relevant block device removal.
16111#
16112# This rule is essential for having the information in LVMetaD up-to-date.
16113# It also requires blkid to be called on block devices before so only devices
16114# used as LVM PVs are processed (ID_FS_TYPE="LVM2_member" or "LVM1_member").
16115
16116SUBSYSTEM!="block", GOTO="lvm_end"
16117(LVM_EXEC_RULE)
16118
16119ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end"
16120
16121# XXX: Properly call blkid on md devices. Workaround for #793631
16122KERNEL!="md[0-9]*", GOTO="next"
16123IMPORT{builtin}="blkid"
16124LABEL="next"
16125
16126# If the PV label got lost, inform lvmetad immediately.
16127# Detect the lost PV label by comparing previous ID_FS_TYPE value with current one.
16128ENV{.ID_FS_TYPE_NEW}="$env{ID_FS_TYPE}"
16129IMPORT{db}="ID_FS_TYPE"
16130ENV{ID_FS_TYPE}=="LVM2_member|LVM1_member", ENV{.ID_FS_TYPE_NEW}!="LVM2_member|LVM1_member", ENV{LVM_PV_GONE}="1"
16131ENV{ID_FS_TYPE}="$env{.ID_FS_TYPE_NEW}"
16132ENV{LVM_PV_GONE}=="1", GOTO="lvm_scan"
16133
16134# Only process devices already marked as a PV - this requires blkid to be called before.
16135ENV{ID_FS_TYPE}!="LVM2_member|LVM1_member", GOTO="lvm_end"
16136ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
16137
16138# Inform lvmetad about any PV that is gone.
16139ACTION=="remove", GOTO="lvm_scan"
16140
16141# Create /dev/disk/by-id/lvm-pv-uuid-<PV_UUID> symlink for each PV
16142ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}"
16143
16144# If the PV is a special device listed below, scan only if the device is
16145# properly activated. These devices are not usable after an ADD event,
16146# but they require an extra setup and they are ready after a CHANGE event.
16147# Also support coldplugging with ADD event but only if the device is already
16148# properly activated.
16149# This logic should be eventually moved to rules where those particular
16150# devices are processed primarily (MD and loop).
16151
16152# DM device:
16153KERNEL!="dm-[0-9]*", GOTO="next"
16154ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}=="1", GOTO="lvm_scan"
16155GOTO="lvm_end"
16156
16157# MD device:
16158LABEL="next"
16159KERNEL!="md[0-9]*", GOTO="next"
16160IMPORT{db}="LVM_MD_PV_ACTIVATED"
16161ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan"
16162ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan"
16163ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan"
16164ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
16165GOTO="lvm_end"
16166
16167# Loop device:
16168LABEL="next"
16169KERNEL!="loop[0-9]*", GOTO="next"
16170ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan"
16171ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan"
16172ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0"
16173GOTO="lvm_end"
16174
16175# If the PV is not a special device listed above, scan only after device addition (ADD event)
16176LABEL="next"
16177ACTION!="add", GOTO="lvm_end"
16178
16179LABEL="lvm_scan"
16180
16181# The table below summarises the situations in which we reach the LABEL="lvm_scan".
16182# Marked by X, X* means only if the special dev is properly set up.
16183# The artificial ADD is supported for coldplugging. We avoid running the pvscan
16184# on artificial CHANGE so there's no unexpected autoactivation when WATCH rule fires.
16185# N.B. MD and loop never actually reaches lvm_scan on REMOVE as the PV label is gone
16186# within a CHANGE event (these are caught by the "LVM_PV_GONE" rule at the beginning).
16187#
16188# | real ADD | real CHANGE | artificial ADD | artificial CHANGE | REMOVE
16189# =============================================================================
16190# DM | | X | X* | | X
16191# MD | | X | X* | |
16192# loop | | X | X* | |
16193# other | X | | X | | X
16194ENV{SYSTEMD_READY}="1"
16195(PVSCAN_RULE)
16196
16197LABEL="lvm_end"
16198\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/12-dm-permissions.rules\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006162\013062740170\0022264\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
16199#
16200# This file is part of LVM2.
16201
16202# Udev rules for device-mapper devices.
16203#
16204# These rules set permissions for DM devices.
16205#
16206# This file is considered to be a template where users can put their
16207# own entries and then put a copy of it manually to a usual place with
16208# user-edited udev rules (usually /etc/udev/rules.d).
16209#
16210# There are some environment variables set that can be used:
16211# DM_UDEV_RULES_VSN - DM udev rules version
16212# DM_NAME - actual DM device's name
16213# DM_UUID - UUID set for DM device (blank if not specified)
16214# DM_SUSPENDED - suspended state of DM device (0 or 1)
16215# DM_LV_NAME - logical volume name (not set if LVM device not present)
16216# DM_VG_NAME - volume group name (not set if LVM device not present)
16217# DM_LV_LAYER - logical volume layer (not set if LVM device not present)
16218
16219# "add" event is processed on coldplug only!
16220ACTION!="add|change", GOTO="dm_end"
16221ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="dm_end"
16222
16223# A few demonstrational examples...
16224
16225
16226# PLAIN DM DEVICES
16227#
16228# Set permissions for a DM device named 'my_device' exactly
16229# ENV{DM_NAME}=="my_device", OWNER:="root", GROUP:="root", MODE:="660"
16230
16231# Set permissions for all DM devices having 'MY_UUID-' UUID prefix
16232# ENV{DM_UUID}=="MY_UUID-?*", OWNER:="root", GROUP:="root", MODE:="660"
16233
16234
16235# LVM DEVICES
16236#
16237# Set permissions for all LVM devices
16238# ENV{DM_UUID}=="LVM-?*", OWNER:="root", GROUP:="root", MODE:="660"
16239
16240# Set permissions for all devices that belong to one LVM VG
16241# ENV{DM_VG_NAME}=="VolGroup00", OWNER:="root", GROUP:="root", MODE:="660"
16242
16243# Set permissions for an LVM device with VG named VolGroup00 and LV named LogVol00 exactly
16244# ENV{DM_VG_NAME}=="VolGroup00", ENV{DM_LV_NAME}=="LogVol00", OWNER:="root", GROUP:="root", MODE:="660"
16245
16246# Set permissions for all LVM devices that does not belong to a VG named VolGroup00
16247# ENV{DM_VG_NAME}!="VolGroup00", OWNER:="root", GROUP:="root", MODE:="660"
16248
16249
16250# ENCRYPTED DEVICES (using cryptsetup >= 1.1)
16251#
16252# Set permissions for all encrypted devices created by cryptsetup (plain devices)
16253# ENV{DM_UUID}=="CRYPT-PLAIN-?*", OWNER:="root", GROUP:="root", MODE:="660"
16254
16255# Set permissions for all encrypted devices created by cryptsetup (LUKS extension)
16256# ENV{DM_UUID}=="CRYPT-LUKS1-?*", OWNER:="root", GROUP:="root", MODE:="660"
16257
16258# Set permissions for an encrypted device created by cryptsetup and having an exact luks UUID
16259# ENV{DM_UUID}=="CRYPT-LUKS1-22fce5c8313c43c68d84b50a3b0fee78-?*", OWNER:="root", GROUP:="root", MODE:="660"
16260
16261
16262# MULTIPATH DEVICES
16263#
16264# Set permissions for all multipath devices
16265# ENV{DM_UUID}=="mpath-?*", OWNER:="root", GROUP:="root", MODE:="660"
16266
16267# Set permissions for first two partitions created on a multipath device (and detected by kpartx)
16268# ENV{DM_UUID}=="part[1-2]-mpath-?*", OWNER:="root", GROUP:="root", MODE:="660"
16269
16270
16271# ...you can use any combination of the comparisons with the environment variables
16272# listed at the beginning of this file (udev provides simple pattern matching by
16273# using *, ? and [] that you can use, see 'man udev' for more information).
16274
16275# Set default permissions for all DM devices if not set before.
16276# OWNER:="root", GROUP:="root", MODE:="660"
16277
16278LABEL="dm_end"
16279\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/10-dm.rules.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015425\013062740170\0020320\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
16280#
16281# This file is part of LVM2.
16282
16283# Udev rules for device-mapper devices.
16284#
16285# These rules create a DM control node in /dev/(DM_DIR) directory.
16286# The rules also create nodes named dm-x (x is a number) in /dev
16287# directory and symlinks to these nodes with names given by
16288# the actual DM names. Some udev environment variables are set
16289# for use in later rules:
16290# DM_NAME - actual DM device's name
16291# DM_UUID - UUID set for DM device (blank if not specified)
16292# DM_SUSPENDED - suspended state of DM device (0 or 1)
16293#
16294# These rules cover only basic device-mapper functionality in udev.
16295#
16296# Various DM subsystems may contain further subsystem-specific rules
16297# in 11-dm-<subsystem_name>.rules which should be installed together
16298# with the DM subsystem and which extend these basic rules.
16299# For example:
16300# 11-dm-lvm.rules for LVM subsystem
16301# 11-dm-mpath.rules for multipath subsystem (since version 0.6.0, recommended!)
16302#
16303# Even more specific rules may be required by subsystems so always
16304# check subsystem's upstream repository for recent set of rules.
16305# Also, keep in mind that recent rules may also require recent
16306# subsystem-specific binaries.
16307
16308KERNEL=="device-mapper", NAME="(DM_DIR)/control"
16309
16310# Decode udev control flags and set environment variables appropriately.
16311# These flags are encoded in DM_COOKIE variable that was introduced in
16312# kernel version 2.6.31. Therefore, we can use this feature with
16313# kernels >= 2.6.31 only.
16314ENV{DM_COOKIE}=="?*", IMPORT{program}="/sbin/dmsetup udevflags $env{DM_COOKIE}"
16315ENV{DM_COOKIE}=="?*", RUN+="/sbin/dmsetup udevcomplete $env{DM_COOKIE}"
16316
16317SUBSYSTEM!="block", GOTO="dm_end"
16318KERNEL!="dm-[0-9]*", GOTO="dm_end"
16319
16320# Device created, major and minor number assigned - "add" event generated.
16321# Table loaded - no event generated.
16322# Device resumed (or renamed) - "change" event generated.
16323# Device removed - "remove" event generated.
16324#
16325# The dm-X nodes are always created, even on "add" event, we can't suppress
16326# that (the node is created even earlier with devtmpfs). All the symlinks
16327# (e.g. /dev/mapper) are created in right time after a device has its table
16328# loaded and is properly resumed. For this reason, direct use of dm-X nodes
16329# is not recommended.
16330ACTION!="add|change", GOTO="dm_end"
16331
16332# Rule out easy-to-detect inappropriate events first.
16333ENV{DISK_RO}=="1", GOTO="dm_disable"
16334
16335# There is no cookie set nor any flags encoded in events not originating
16336# in libdevmapper so we need to detect this and try to behave correctly.
16337# For such spurious events, regenerate all flags from current udev database content
16338# (this information would normally be inaccessible for spurious ADD and CHANGE events).
16339ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}="1", GOTO="dm_flags_done"
16340IMPORT{db}="DM_UDEV_DISABLE_DM_RULES_FLAG"
16341IMPORT{db}="DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG"
16342IMPORT{db}="DM_UDEV_DISABLE_DISK_RULES_FLAG"
16343IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG"
16344IMPORT{db}="DM_UDEV_LOW_PRIORITY_FLAG"
16345IMPORT{db}="DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG"
16346IMPORT{db}="DM_UDEV_PRIMARY_SOURCE_FLAG"
16347IMPORT{db}="DM_UDEV_FLAG7"
16348IMPORT{db}="DM_UDEV_RULES"
16349LABEL="dm_flags_done"
16350
16351# Normally, we operate on "change" events. But when coldplugging, there's an
16352# "add" event present. We have to recognize this and do our actions in this
16353# particular situation, too. Also, we don't want the nodes to be created
16354# prematurely on "add" events while not coldplugging. We check
16355# DM_UDEV_PRIMARY_SOURCE_FLAG to see if the device was activated correctly
16356# before and if not, we ignore the "add" event totally. This way we can support
16357# udev triggers generating "add" events (e.g. "udevadm trigger --action=add" or
16358# "echo add > /sys/block/<dm_device>/uevent"). The trigger with "add" event is
16359# also used at boot to reevaluate udev rules for all existing devices activated
16360# before (e.g. in initrd). If udev is used in initrd, we require the udev init
16361# script to not remove the existing udev database so we can reuse the information
16362# stored at the time of device activation in the initrd.
16363ACTION!="add", GOTO="dm_no_coldplug"
16364ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="dm_disable"
16365ENV{DM_ACTIVATION}="1"
16366LABEL="dm_no_coldplug"
16367
16368# Putting it together, following table is used to recognize genuine and spurious events.
16369# N.B. Spurious events are generated based on use of the WATCH udev
16370# rule or by triggering an event manually by "udevadm trigger" call
16371# or by "echo <event_name> > /sys/block/dm-X/uevent".
16372#
16373# EVENT DM_UDEV_PRIMARY_SOURCE_FLAG DM_ACTIVATION
16374# ======================================================================
16375# add event (genuine) 0 0
16376# change event (genuine) 1 1
16377# add event (spurious)
16378# |_ dev still not active 0 0
16379# \_ dev already active 1 1
16380# change event (spurious)
16381# |_ dev still not active 0 0
16382# \_ dev already active 1 0
16383
16384# "dm" sysfs subdirectory is available in newer versions of DM
16385# only (kernels >= 2.6.29). We have to check for its existence
16386# and use dmsetup tool instead to get the DM name, uuid and
16387# suspended state if the "dm" subdirectory is not present.
16388# The "suspended" item was added even later (kernels >= 2.6.31),
16389# so we also have to call dmsetup if the kernel version used
16390# is in between these releases.
16391TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{DM_SUSPENDED}="$attr{dm/suspended}"
16392TEST!="dm", IMPORT{program}="(DM_EXEC)/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o name,uuid,suspended"
16393ENV{DM_SUSPENDED}!="?*", IMPORT{program}="(DM_EXEC)/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
16394
16395# dmsetup tool provides suspended state information in textual
16396# form with values "Suspended"/"Active". We translate it to
16397# 0/1 respectively to be consistent with sysfs values.
16398ENV{DM_SUSPENDED}=="Active", ENV{DM_SUSPENDED}="0"
16399ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1"
16400
16401# This variable provides a reliable way to check that device-mapper
16402# rules were installed. It means that all needed variables are set
16403# by these rules directly so there's no need to acquire them again
16404# later.
16405ENV{DM_UDEV_RULES}="1"
16406
16407ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}"
16408
16409# Avoid processing and scanning a DM device in the other (foreign)
16410# rules if it is in suspended state. However, we still keep 'disk'
16411# and 'DM subsystem' related rules enabled in this case.
16412ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
16413
16414GOTO="dm_end"
16415
16416LABEL="dm_disable"
16417ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
16418ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
16419ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
16420OPTIONS:="nowatch"
16421
16422LABEL="dm_end"
16423\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005241\013062740170\0020061\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
16424# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
16425#
16426# This file is part of LVM2.
16427#
16428# This copyrighted material is made available to anyone wishing to use,
16429# modify, copy, or redistribute it subject to the terms and conditions
16430# of the GNU General Public License v.2.
16431#
16432# You should have received a copy of the GNU General Public License
16433# along with this program; if not, write to the Free Software Foundation,
16434# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16435
16436srcdir = @srcdir@
16437top_srcdir = @top_srcdir@
16438top_builddir = @top_builddir@
16439
16440include $(top_builddir)/make.tmpl
16441
16442DM_RULES=55-dm.rules 60-persistent-storage-dm.rules
16443LVM_RULES=56-lvm.rules
16444ifeq ("@BUILD_LVMETAD@", "yes")
16445LVM_RULES+=69-lvm-metad.rules
16446endif
16447
16448DM_DIR=$(shell grep "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | awk '{print $$3}')
16449
16450ifeq ("@UDEV_RULE_EXEC_DETECTION@", "yes")
16451SBIN=\$$env{DM_SBIN_PATH}
16452DM_EXEC_RULE=ENV{DM_SBIN_PATH}=\"\/sbin\"\\nTEST!=\"\$$env{DM_SBIN_PATH}\/dmsetup\", ENV{DM_SBIN_PATH}=\"\/usr\/sbin\"
16453DM_EXEC=\$$env{DM_SBIN_PATH}
16454LVM_EXEC_RULE=ENV{LVM_SBIN_PATH}=\"\/sbin\"\\nTEST!=\"\$$env{LVM_SBIN_PATH}\/lvm\", ENV{LVM_SBIN_PATH}=\"\/usr\/sbin\"
16455LVM_EXEC=\$$env{LVM_SBIN_PATH}
16456else
16457SBIN="@sbindir@"
16458DM_EXEC_RULE=""
16459DM_EXEC=${SBIN}
16460LVM_EXEC_RULE=""
16461LVM_EXEC=${SBIN}
16462endif
16463
16464ifeq ("@UDEV_HAS_BUILTIN_BLKID@", "yes")
16465BLKID_RULE=IMPORT{builtin}=\"blkid\"
16466else
16467BLKID_RULE=IMPORT{program}=\"${SBIN}\/blkid -o udev -p \$$tempnode\"
16468endif
16469
16470ifeq ("@UDEV_SYSTEMD_BACKGROUND_JOBS@", "yes")
16471PVSCAN_RULE=ACTION\!=\"remove\", ENV{LVM_PV_GONE}==\"1\", RUN\+=\"@bindir@/systemd-run $(LVM_EXEC)\/lvm pvscan --cache \$$major\:\$$minor\", GOTO=\"lvm_end\"\nENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}\+=\"lvm2-pvscan@\$$major:\$$minor.service\"
16472else
16473PVSCAN_RULE=RUN\+\=\"$(LVM_EXEC)/lvm pvscan --cache --activate ay --major \$$major --minor \$$minor\", ENV{LVM_SCANNED}=\"1\"
16474endif
16475
16476%.rules: $(srcdir)/%.rules.in
16477 $(SED) -e "s+(DM_DIR)+$(DM_DIR)+;s+(BLKID_RULE)+$(BLKID_RULE)+;s+(PVSCAN_RULE)+$(PVSCAN_RULE)+;s+(DM_EXEC_RULE)+$(DM_EXEC_RULE)+;s+(DM_EXEC)+$(DM_EXEC)+;s+(LVM_EXEC_RULE)+$(LVM_EXEC_RULE)+;s+(LVM_EXEC)+$(LVM_EXEC)+;" $< >$@
16478
1647955-dm.rules: 10-dm.rules
16480 ln -s $< $@
16481
1648256-lvm.rules: 11-dm-lvm.rules
16483 ln -s $< $@
16484
1648560-persistent-storage-dm.rules: 13-dm-disk.rules
16486 ln -s $< $@
16487
1648869-lvm-metad.rules: 69-dm-lvm-metad.rules
16489 ln -s $< $@
16490
16491%_install: %.rules
16492 $(INSTALL_DATA) -D $< $(udevdir)/$(<F)
16493
16494all: $(DM_RULES) $(LVM_RULES)
16495CLEAN_TARGETS = $(DM_RULES) $(LVM_RULES)
16496install_device-mapper: $(DM_RULES:.rules=_install)
16497install_lvm2: $(LVM_RULES:.rules=_install)
16498
16499install: install_lvm2 install_device-mapper
16500\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/95-dm-notify.rules.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000743\013062740170\0021640\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
16501#
16502# This file is part of LVM2.
16503
16504# Udev rules for device-mapper devices.
16505#
16506# These rules are responsible for sending a notification to a process
16507# waiting for completion of udev rules. The process is identified by
16508# a cookie value sent within "change" and "remove" events (the cookie
16509# value is set before by that process for every action requested).
16510
16511ENV{DM_COOKIE}=="?*", RUN+="(DM_EXEC)/dmsetup udevcomplete $env{DM_COOKIE}"
16512\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/11-dm-lvm.rules.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004622\013062740170\0021112\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
16513#
16514# This file is part of LVM2.
16515
16516# Udev rules for LVM.
16517#
16518# These rules create symlinks for LVM logical volumes in
16519# /dev/VG directory (VG is an actual VG name). Some udev
16520# environment variables are set (they can be used in later
16521# rules as well):
16522# DM_LV_NAME - logical volume name
16523# DM_VG_NAME - volume group name
16524# DM_LV_LAYER - logical volume layer (blank if not set)
16525
16526# "add" event is processed on coldplug only!
16527ACTION!="add|change", GOTO="lvm_end"
16528ENV{DM_UDEV_RULES}!="?*", GOTO="lvm_end"
16529ENV{DM_UUID}!="LVM-?*", GOTO="lvm_end"
16530
16531# Use DM name and split it up into its VG/LV/layer constituents.
16532IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows $env{DM_NAME}"
16533
16534# DM_SUBSYSTEM_UDEV_FLAG0 is the 'NOSCAN' flag for LVM subsystem.
16535# This flag is used to temporarily disable selected rules to prevent any
16536# processing or scanning done on the LVM volume before LVM has any chance
16537# to zero any stale metadata found within the LV data area. Such stale
16538# metadata could cause false claim of the LV device, keeping it open etc.
16539#
16540# If the NOSCAN flag is present, backup selected existing flags used to
16541# disable rules, then set them firmly so those selected rules are surely skipped.
16542# Restore these flags once the NOSCAN flag is dropped (which is normally any
16543# uevent that follows for this LV, even an artificially generated one).
16544ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
16545ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD"
16546ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \
16547 ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="", ENV{DM_NOSCAN}=""
16548
16549ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end"
16550
16551OPTIONS+="event_timeout=180"
16552
16553# Do not create symlinks for inappropriate subdevices.
16554ENV{DM_LV_NAME}=="pvmove?*|?*_vorigin", GOTO="lvm_disable"
16555ENV{DM_LV_LAYER}=="?*", GOTO="lvm_disable"
16556
16557# Create symlinks for top-level devices only.
16558ENV{DM_VG_NAME}=="?*", ENV{DM_LV_NAME}=="?*", SYMLINK+="$env{DM_VG_NAME}/$env{DM_LV_NAME}", GOTO="lvm_end"
16559
16560LABEL="lvm_disable"
16561ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
16562ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
16563OPTIONS:="nowatch"
16564
16565LABEL="lvm_end"
16566\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/udev/13-dm-disk.rules.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002714\013062740170\0021250\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
16567#
16568# This file is part of LVM2.
16569
16570# Udev rules for device-mapper devices.
16571#
16572# These rules create symlinks in /dev/disk directory.
16573# Symlinks that depend on probing filesystem type,
16574# label and uuid are created only if the device is not
16575# suspended.
16576
16577# "add" event is processed on coldplug only!
16578ACTION!="add|change", GOTO="dm_end"
16579ENV{DM_UDEV_RULES}!="?*", GOTO="dm_end"
16580ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}=="1", GOTO="dm_end"
16581
16582SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}"
16583ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}"
16584
16585ENV{DM_SUSPENDED}=="1", GOTO="dm_end"
16586ENV{DM_NOSCAN}=="1", GOTO="dm_watch"
16587
16588(BLKID_RULE)
16589ENV{DM_UDEV_LOW_PRIORITY_FLAG}=="1", OPTIONS="link_priority=-100"
16590ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
16591ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
16592
16593# Add inotify watch to track changes on this device.
16594# Using the watch rule is not optimal - it generates a lot of spurious
16595# and useless events whenever the device opened for read-write is closed.
16596# The best would be to generete the event directly in the tool changing
16597# relevant information so only relevant events will be processed
16598# (like creating a filesystem, changing filesystem label etc.).
16599#
16600# But let's use this until we have something better...
16601LABEL="dm_watch"
16602OPTIONS+="watch"
16603
16604LABEL="dm_end"
16605\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0015614\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/lvmetad_design.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000024350\013062740170\0021346\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0The design of LVMetaD
16606=====================
16607
16608Invocation and setup
16609--------------------
16610
16611The daemon should be started automatically by the first LVM command issued on
16612the system, when needed. The usage of the daemon should be configurable in
16613lvm.conf, probably with its own section. Say
16614
16615 lvmetad {
16616 enabled = 1 # default
16617 autostart = 1 # default
16618 socket = "/path/to/socket" # defaults to /var/run/lvmetad or such
16619 }
16620
16621Library integration
16622-------------------
16623
16624When a command needs to access metadata, it currently needs to perform a scan
16625of the physical devices available in the system. This is a possibly quite
16626expensive operation, especially if many devices are attached to the system. In
16627most cases, LVM needs a complete image of the system's PVs to operate
16628correctly, so all devices need to be read, to at least determine presence (and
16629content) of a PV label. Additional IO is done to obtain or write metadata
16630areas, but this is only marginally related and addressed by Dave's
16631metadata-balancing work.
16632
16633In the existing scanning code, a cache layer exists, under
16634lib/cache/lvmcache.[hc]. This layer is keeping a textual copy of the metadata
16635for a given volume group, in a format_text form, as a character string. We can
16636plug the lvmetad interface at this level: in lvmcache_get_vg, which is
16637responsible for looking up metadata in a local cache, we can, if the metadata
16638is not available in the local cache, query lvmetad. Under normal circumstances,
16639when a VG is not cached yet, this operation fails and prompts the caller to
16640perform a scan. Under the lvmetad enabled scenario, this would never happen and
16641the fall-through would only be activated when lvmetad is disabled, which would
16642lead to local cache being populated as usual through a locally executed scan.
16643
16644Therefore, existing stand-alone (i.e. no lvmetad) functionality of the tools
16645would be not compromised by adding lvmetad. With lvmetad enabled, however,
16646significant portions of the code would be short-circuited.
16647
16648Scanning
16649--------
16650
16651Initially (at least), the lvmetad will be not allowed to read disks: it will
16652rely on an external program to provide the metadata. In the ideal case, this
16653will be triggered by udev. The role of lvmetad is then to collect and maintain
16654an accurate (up to the data it has received) image of the VGs available in the
16655system. I imagine we could extend the pvscan command (or add a new one, say
16656lvmetad_client, if pvscan is found to be inappropriate):
16657
16658 $ pvscan --cache /dev/foo
16659 $ pvscan --cache --remove /dev/foo
16660
16661These commands would simply read the label and the MDA (if applicable) from the
16662given PV and feed that data to the running lvmetad, using
16663lvmetad_{add,remove}_pv (see lvmetad_client.h).
16664
16665We however need to ensure a couple of things here:
16666
166671) only LVM commands ever touch PV labels and VG metadata
166682) when a device is added or removed, udev fires a rule to notify lvmetad
16669
16670While the latter is straightforward, there are issues with the first. We
16671*might* want to invoke the dreaded "watch" udev rule in this case, however it
16672ends up being implemented. Of course, we can also rely on the sysadmin to be
16673reasonable and not write over existing LVM metadata without first telling LVM
16674to let go of the respective device(s).
16675
16676Even if we simply ignore the problem, metadata write should fail in these
16677cases, so the admin should be unable to do substantial damage to the system. If
16678there were active LVs on top of the vanished PV, they are in trouble no matter
16679what happens there.
16680
16681Incremental scan
16682----------------
16683
16684There are some new issues arising with the "udev" scan mode. Namely, the
16685devices of a volume group will be appearing one by one. The behaviour in this
16686case will be very similar to the current behaviour when devices are missing:
16687the volume group, until *all* its physical volumes have been discovered and
16688announced by udev, will be in a state with some of its devices flagged as
16689MISSING_PV. This means that the volume group will be, for most purposes,
16690read-only until it is complete and LVs residing on yet-unknown PVs won't
16691activate without --partial. Under usual circumstances, this is not a problem
16692and the current code for dealing with MISSING_PVs should be adequate.
16693
16694However, the code for reading volume groups from disks will need to be adapted,
16695since it currently does not work incrementally. Such support will need to track
16696metadata-less PVs that have been encountered so far and to provide a way to
16697update an existing volume group. When the first PV with metadata of a given VG
16698is encountered, the VG is created in lvmetad (probably in the form of "struct
16699volume_group") and it is assigned any previously cached metadata-less PVs it is
16700referencing. Any PVs that were not yet encountered will be marked as MISSING_PV
16701in the "struct volume_group". Upon scanning a new PV, if it belongs to any
16702already-known volume group, this PV is checked for consistency with the already
16703cached metadata (in a case of mismatch, the VG needs to be recovered or
16704declared conflicted), and is subsequently unmarked MISSING_PV. Care need be
16705taken not to unmark MISSING_PV on PVs that have this flag in their persistent
16706metadata, though.
16707
16708The most problematic aspect of the whole design may be orphan PVs. At any given
16709point, a metadata-less PV may appear orphaned, if a PV of its VG with metadata
16710has not been scanned yet. Eventually, we will have to decide that this PV is
16711really an orphan and enable its usage for creating or extending VGs. In
16712practice, the decision might be governed by a timeout or assumed immediately --
16713the former case is a little safer, the latter is probably more transparent. I
16714am not very keen on using timeouts and we can probably assume that the admin
16715won't blindly try to re-use devices in a way that would trip up LVM in this
16716respect. I would be in favour of just assuming that metadata-less VGs with no
16717known referencing VGs are orphans -- after all, this is the same approach as we
16718use today. The metadata balancing support may stress this a bit more than the
16719usual contemporary setups do, though.
16720
16721Automatic activation
16722--------------------
16723
16724It may also be prudent to provide a command that will block until a volume
16725group is complete, so that scripts can reliably activate/mount LVs and such. Of
16726course, some PVs may never appear, so a timeout is necessary. Again, this is
16727something not handled by current tools, but may become more important in
16728future. It probably does not need to be implemented right away though.
16729
16730The other aspect of the progressive VG assembly is automatic activation. The
16731currently only problem with that is that we would like to avoid having
16732activation code in lvmetad, so we would prefer to fire up an event of some sort
16733and let someone else handle the activation and whatnot.
16734
16735Cluster support
16736---------------
16737
16738When working in a cluster, clvmd integration will be necessary: clvmd will need
16739to instruct lvmetad to re-read metadata as appropriate due to writes on remote
16740hosts. Overall, this is not hard, but the devil is in the details. I would
16741possibly disable lvmetad for clustered volume groups in the first phase and
16742only proceed when the local mode is robust and well tested.
16743
16744With lvmlockd, lvmetad state is kept up to date by flagging either an
16745individual VG as "invalid", or the global state as "invalid". When either
16746the VG or the global state are read, this invalid flag is returned along
16747with the data. The client command can check for this invalid state and
16748decide to read the information from disk rather than use the stale cached
16749data. After the latest data is read from disk, the command may choose to
16750send it to lvmetad to update the cache. lvmlockd uses version numbers
16751embedded in its VG and global locks to detect when cached data becomes
16752invalid, and it then tells lvmetad to set the related invalid flag.
16753dct, 2015-06-23
16754
16755Protocol & co.
16756--------------
16757
16758I expect a simple text-based protocol executed on top of an Unix Domain Socket
16759to be the communication interface for lvmetad. Ideally, the requests and
16760replies will be well-formed "config file" style strings, so we can re-use
16761existing parsing infrastructure.
16762
16763Since we already have two daemons, I would probably look into factoring some
16764common code for daemon-y things, like sockets, communication (including thread
16765management) and maybe logging and re-using it in all the daemons (clvmd,
16766dmeventd and lvmetad). This shared infrastructure should live under
16767daemons/common, and the existing daemons shall be gradually migrated to the
16768shared code.
16769
16770Future extensions
16771-----------------
16772
16773The above should basically cover the use of lvmetad as a cache-only
16774daemon. Writes could still be executed locally, and the new metadata version
16775can be provided to lvmetad through the socket the usual way. This is fairly
16776natural and in my opinion reasonable. The lvmetad acts like a cache that will
16777hold metadata, no more no less.
16778
16779Above this, there is a couple of things that could be worked on later, when the
16780above basic design is finished and implemented.
16781
16782_Metadata writing_: We may want to support writing new metadata through
16783lvmetad. This may or may not be a better design, but the write itself should be
16784more or less orthogonal to the rest of the story outlined above.
16785
16786_Locking_: Other than directing metadata writes through lvmetad, one could
16787conceivably also track VG/LV locking through the same.
16788
16789_Clustering_: A deeper integration of lvmetad with clvmd might be possible and
16790maybe desirable. Since clvmd communicates over the network with other clvmd
16791instances, this could be extended to metadata exchange between lvmetad's,
16792further cutting down scanning costs. This would combine well with the
16793write-through-lvmetad approach.
16794
16795Testing
16796-------
16797
16798Since (at least bare-bones) lvmetad has no disk interaction and is fed metadata
16799externally, it should be very amenable to automated testing. We need to provide
16800a client that can feed arbitrary, synthetic metadata to the daemon and request
16801the data back, providing reasonable (nearly unit-level) testing infrastructure.
16802
16803Battle plan & code layout
16804=========================
16805
16806- config_tree from lib/config needs to move to libdm/
16807- daemon/common *client* code can go to libdm/ as well (say
16808 libdm/libdm-daemon.{h,c} or such)
16809- daemon/common *server* code stays, is built in daemon/ toplevel as a static
16810 library, say libdaemon-common.a
16811- daemon/lvmetad *client* code goes to lib/lvmetad
16812- daemon/lvmetad *server* code stays (links in daemon/libdaemon_common.a)
16813\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/lvmpolld_overview.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006335\013062740170\0022143\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM poll daemon overview
16814========================
16815
16816(last updated: 2015-05-09)
16817
16818LVM poll daemon (lvmpolld) is the alternative for lvm2 classical polling
16819mechanisms. The motivation behind new lvmpolld was to create persistent
16820system service that would be more durable and transparent. It's suited
16821particularly for any systemd enabled distribution.
16822
16823Before lvmpolld any background polling process originating in a lvm2 command
16824initiated inside cgroup of a systemd service could get killed if the main
16825process (service) exited in such cgroup. That could lead to premature termination
16826of such lvm2 polling process.
16827
16828Also without lvmpolld there were no means to detect a particular polling process
16829suited for monitoring of specific operation is already in-progress and therefore
16830it's not desirable to start next one with exactly same task. lvmpolld is able to
16831detect such duplicate requests and not spawn such redundant process.
16832
16833lvmpolld is primarily targeted for systems with systemd as init process. For systems
16834without systemd there's no need to install lvmpolld because there is no issue
16835with observation described in second paragraph. You can still benefit from
16836avoiding duplicate polling process being spawned, but without systemd lvmpolld
16837can't easily be run on-demand (activated by a socket maintained by systemd).
16838
16839lvmpolld implement shutdown on idle and can shutdown automatically when idle
16840for requested time. 60 second is recommended default here. This behaviour can be
16841turned off if found useless.
16842
16843Data structures
16844---------------
16845
16846a) Logical Volume (struct lvmpolld_lv)
16847
16848Each operation is identified by LV. Internal identifier within lvmpolld
16849is full LV uuid (vg_uuid+lv_uuid) prefixed with LVM_SYSTEM_DIR if set by client.
16850
16851such full identifier may look like:
16852
16853 "/etc/lvm/lvm.confWFd2dU67S8Av29IcJCnYzqQirdfElnxzhCdzEh7EJrfCn9R1TIQjIj58weUZDre4"
16854
16855or without LVM_SYSTEM_DIR being set explicitly:
16856
16857 "WFd2dU67S8Av29IcJCnYzqQirdfElnxzhCdzEh7EJrfCn9R1TIQjIj58weUZDre4"
16858
16859
16860LV carries various metadata about polling operation. The most significant are:
16861
16862VG name
16863LV name
16864polling interval (usually --interval passed to lvm2 command or default from lvm2
16865 configuration)
16866operation type (one of: pvmove, convert, merge, thin_merge)
16867LVM_SYSTEM_DIR (if set, this is also passed among environment variables of lvpoll
16868 command spawned by lvmpolld)
16869
16870b) LV stores (struct lvmpolld_store)
16871
16872lvmpolld uses two stores for Logical volumes (struct lvmpolld_lv). One store for polling
16873operations in-progress. These operations are as of now: PV move, mirror up-conversion,
16874classical snapshot merge, thin snapshot merge.
16875
16876The second store is suited only for pvmove --abort operations in-progress. Both
16877stores are independent and identical LVs (pvmove /dev/sda3 and pvmove --abort /dev/sda3)
16878can be run concurently from lvmpolld point of view (on lvm2 side the consistency is
16879guaranteed by lvm2 locking mechanism).
16880
16881Locking order
16882-------------
16883
16884There are two types of locks in lvmpolld. Each store has own store lock and each LV has
16885own lv lock.
16886
16887Locking order is:
168881) store lock
168892) LV lock
16890
16891Each LV has to be inside a store. When daemon requires to take both locks it has
16892to take a store lock first and LV lock has to be taken afterwards (after the
16893appropriate store lock where the LV is being stored :))
16894\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/testing.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002264\013062740170\0020036\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Here's how I test new LVM2 builds without interfering with the stable
16895LVM2 that is running the LV's on my development box.
16896
168971) Create a set of loopback devices.
16898
168992) Create a new directory to contain the LVM2 configuration files for
16900 this setup. (I use /etc/lvm_loops)
16901
169023) Write a suitable lvm.conf file, this goes in the directory you just
16903 created. eg, my /etc/lvm_loops/lvm.conf looks like:
16904
16905 log {
16906 file="/tmp/lvm2_loop.log"
16907 level=9
16908 verbose=0
16909 overwrite=1
16910 }
16911
16912 devices {
16913 scan = "/dev"
16914 filter = ["a/loop/", "r/.*/"]
16915 }
16916
16917
16918 The important thing to note is the devices section which makes sure
16919 that only the loopback devices are considered for LVM2 operations.
16920
169214) When you want to use this test setup just set the environment
16922 variable LVM_SYSTEM_DIR to point to your config directory
16923 (/etc/lvm_loops in my case).
16924
169255) It's a good idea to do a vgscan to initialise the filters:
16926
16927 export LVM_SYSTEM_DIR=/etc/lvm_loops
16928 ./lvm vgscan
16929
16930 where ./lvm is the new build of LVM2 that I'm trying out.
16931
169327) Test away. Make sure that you are explicit about which lvm
16933 executable you want to execute (eg, ./lvm if you are in
16934 LVM2/tools).
16935\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/udev_assembly.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007736\013062740170\0021234\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Automatic device assembly by udev
16936=================================
16937
16938We want to asynchronously assemble and activate devices as their components
16939become available. Eventually, the complete storage stack should be covered,
16940including: multipath, cryptsetup, LVM, mdadm. Each of these can be addressed
16941more or less separately.
16942
16943The general plan of action is to simply provide udev rules for each of the
16944device "type": for MD component devices, PVs, LUKS/crypto volumes and for
16945multipathed SCSI devices. There's no compelling reason to have a daemon do these
16946things: all systems that actually need to assemble multiple devices into a
16947single entity already either support incremental assembly or will do so shortly.
16948
16949Whenever in this document we talk about udev rules, these may include helper
16950programs that implement a multi-step process. In many cases, it can be expected
16951that the functionality can be implemented in couple lines of shell (or couple
16952hundred of C).
16953
16954Multipath
16955---------
16956
16957For multipath, we will need to rely on SCSI IDs for now, until we have a better
16958scheme of things, since multipath devices can't be identified until the second
16959path appears, and unfortunately we need to decide whether a device is multipath
16960when the *first* path appears. Anyway, the multipath folks need to sort this
16961out, but it shouldn't bee too hard. Just bring up multipathing on anything that
16962appears and is set up for multipathing.
16963
16964LVM
16965---
16966
16967For LVM, the crucial piece of the puzzle is lvmetad, which allows us to build up
16968VGs from PVs as they appear, and at the same time collect information on what is
16969already available. A command, pvscan --cache is expected to be used to
16970implement udev rules. It is relatively easy to make this command print out a
16971list of VGs (and possibly LVs) that have been made available by adding any
16972particular device to the set of visible devices. In othe words, udev says "hey,
16973/dev/sdb just appeared", calls pvscan --cache, which talks to lvmetad, which
16974says "cool, that makes vg0 complete". Pvscan takes this info and prints it out,
16975and the udev rule can then somehow decide whether anything needs to be done
16976about this "vg0". Presumably a table of devices that need to be activated
16977automatically is made available somewhere in /etc (probably just a simple list
16978of volume groups or logical volumes, given by name or UUID, globbing
16979possible). The udev rule can then consult this file.
16980
16981Cryptsetup
16982----------
16983
16984This may be the trickiest of the lot: the obvious hurdle here is that crypto
16985volumes need to somehow obtain a key (passphrase, physical token or such),
16986meaning there is interactivity involved. On the upside, dm-crypt is a 1:1
16987system: one encrypted device results in one decrypted device, so no assembly or
16988notification needs to be done. While interactivity is a challenge, there are at
16989least partial solutions around. (TODO: Milan should probably elaborate here.)
16990
16991(For LUKS devices, these can probably be detected automatically. I suppose that
16992non-LUKS devices can be looked up in crypttab by the rule, to decide what is the
16993appropriate action to take.)
16994
16995MD
16996--
16997
16998Fortunately, MD (namely mdadm) already comes with a mechanism for incremental
16999assembly (mdadm -I or such). We can assume that this fits with the rest of stack
17000nicely.
17001
17002
17003Filesystem &c. discovery
17004========================
17005
17006Considering other requirements that exist for storage systems (namely
17007large-scale storage deployments), it is absolutely not feasible to have the
17008system hunt automatically for filesystems based on their UUIDs. In a number of
17009cases, this could mean activating tens of thousands of volumes. On small
17010systems, asking for all volumes to be brought up automatically is probably the
17011best route anyway, and once all storage devices are activated, scanning for
17012filesystems is no different from today.
17013
17014In effect, no action is required on this count: only filesystems that are
17015available on already active devices can be mounted by their UUID. Activating
17016volumes by naming a filesystem UUID is useless, since to read the UUID the
17017volume needs to be active first.
17018\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/lvm_fault_handling.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000026072\013062740170\0022221\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM device fault handling
17019=========================
17020
17021Introduction
17022------------
17023This document is to serve as the definitive source for information
17024regarding the policies and procedures surrounding device failures
17025in LVM. It codifies LVM's responses to device failures as well as
17026the responsibilities of administrators.
17027
17028Device failures can be permanent or transient. A permanent failure
17029is one where a device becomes inaccessible and will never be
17030revived. A transient failure is a failure that can be recovered
17031from (e.g. a power failure, intermittent network outage, block
17032relocation, etc). The policies for handling both types of failures
17033is described herein.
17034
17035Users need to be aware that there are two implementations of RAID1 in LVM.
17036The first is defined by the "mirror" segment type. The second is defined by
17037the "raid1" segment type. The characteristics of each of these are defined
17038in lvm.conf under 'mirror_segtype_default' - the configuration setting used to
17039identify the default RAID1 implementation used for LVM operations.
17040
17041Available Operations During a Device Failure
17042--------------------------------------------
17043When there is a device failure, LVM behaves somewhat differently because
17044only a subset of the available devices will be found for the particular
17045volume group. The number of operations available to the administrator
17046is diminished. It is not possible to create new logical volumes while
17047PVs cannot be accessed, for example. Operations that create, convert, or
17048resize logical volumes are disallowed, such as:
17049- lvcreate
17050- lvresize
17051- lvreduce
17052- lvextend
17053- lvconvert (unless '--repair' is used)
17054Operations that activate, deactivate, remove, report, or repair logical
17055volumes are allowed, such as:
17056- lvremove
17057- vgremove (will remove all LVs, but not the VG until consistent)
17058- pvs
17059- vgs
17060- lvs
17061- lvchange -a [yn]
17062- vgchange -a [yn]
17063Operations specific to the handling of failed devices are allowed and
17064are as follows:
17065
17066- 'vgreduce --removemissing <VG>': This action is designed to remove
17067 the reference of a failed device from the LVM metadata stored on the
17068 remaining devices. If there are (portions of) logical volumes on the
17069 failed devices, the ability of the operation to proceed will depend
17070 on the type of logical volumes found. If an image (i.e leg or side)
17071 of a mirror is located on the device, that image/leg of the mirror
17072 is eliminated along with the failed device. The result of such a
17073 mirror reduction could be a no-longer-redundant linear device. If
17074 a linear, stripe, or snapshot device is located on the failed device
17075 the command will not proceed without a '--force' option. The result
17076 of using the '--force' option is the entire removal and complete
17077 loss of the non-redundant logical volume. If an image or metadata area
17078 of a RAID logical volume is on the failed device, the sub-LV affected is
17079 replace with an error target device - appearing as <unknown> in 'lvs'
17080 output. RAID logical volumes cannot be completely repaired by vgreduce -
17081 'lvconvert --repair' (listed below) must be used. Once this operation is
17082 complete on volume groups not containing RAID logical volumes, the volume
17083 group will again have a complete and consistent view of the devices it
17084 contains. Thus, all operations will be permitted - including creation,
17085 conversion, and resizing operations. It is currently the preferred method
17086 to call 'lvconvert --repair' on the individual logical volumes to repair
17087 them followed by 'vgreduce --removemissing' to extract the physical volume's
17088 representation in the volume group.
17089
17090- 'lvconvert --repair <VG/LV>': This action is designed specifically
17091 to operate on individual logical volumes. If, for example, a failed
17092 device happened to contain the images of four distinct mirrors, it would
17093 be necessary to run 'lvconvert --repair' on each of them. The ultimate
17094 result is to leave the faulty device in the volume group, but have no logical
17095 volumes referencing it. (This allows for 'vgreduce --removemissing' to
17096 removed the physical volumes cleanly.) In addition to removing mirror or
17097 RAID images that reside on failed devices, 'lvconvert --repair' can also
17098 replace the failed device if there are spare devices available in the
17099 volume group. The user is prompted whether to simply remove the failed
17100 portions of the mirror or to also allocate a replacement, if run from the
17101 command-line. Optionally, the '--use-policies' flag can be specified which
17102 will cause the operation not to prompt the user, but instead respect
17103 the policies outlined in the LVM configuration file - usually,
17104 /etc/lvm/lvm.conf. Once this operation is complete, the logical volumes
17105 will be consistent. However, the volume group will still be inconsistent -
17106 due to the refernced-but-missing device/PV - and operations will still be
17107 restricted to the aformentioned actions until either the device is
17108 restored or 'vgreduce --removemissing' is run.
17109
17110Device Revival (transient failures):
17111------------------------------------
17112During a device failure, the above section describes what limitations
17113a user can expect. However, if the device returns after a period of
17114time, what to expect will depend on what has happened during the time
17115period when the device was failed. If no automated actions (described
17116below) or user actions were necessary or performed, then no change in
17117operations or logical volume layout will occur. However, if an
17118automated action or one of the aforementioned repair commands was
17119manually run, the returning device will be perceived as having stale
17120LVM metadata. In this case, the user can expect to see a warning
17121concerning inconsistent metadata. The metadata on the returning
17122device will be automatically replaced with the latest copy of the
17123LVM metadata - restoring consistency. Note, while most LVM commands
17124will automatically update the metadata on a restored devices, the
17125following possible exceptions exist:
17126- pvs (when it does not read/update VG metadata)
17127
17128Automated Target Response to Failures:
17129--------------------------------------
17130The only LVM target types (i.e. "personalities") that have an automated
17131response to failures are the mirror and RAID logical volumes. The other target
17132types (linear, stripe, snapshot, etc) will simply propagate the failure.
17133[A snapshot becomes invalid if its underlying device fails, but the
17134origin will remain valid - presuming the origin device has not failed.]
17135
17136Starting with the "mirror" segment type, there are three types of errors that
17137a mirror can suffer - read, write, and resynchronization errors. Each is
17138described in depth below.
17139
17140Mirror read failures:
17141If a mirror is 'in-sync' (i.e. all images have been initialized and
17142are identical), a read failure will only produce a warning. Data is
17143simply pulled from one of the other images and the fault is recorded.
17144Sometimes - like in the case of bad block relocation - read errors can
17145be recovered from by the storage hardware. Therefore, it is up to the
17146user to decide whether to reconfigure the mirror and remove the device
17147that caused the error. Managing the composition of a mirror is done with
17148'lvconvert' and removing a device from a volume group can be done with
17149'vgreduce'.
17150
17151If a mirror is not 'in-sync', a read failure will produce an I/O error.
17152This error will propagate all the way up to the applications above the
17153logical volume (e.g. the file system). No automatic intervention will
17154take place in this case either. It is up to the user to decide what
17155can be done/salvaged in this senario. If the user is confident that the
17156images of the mirror are the same (or they are willing to simply attempt
17157to retreive whatever data they can), 'lvconvert' can be used to eliminate
17158the failed image and proceed.
17159
17160Mirror resynchronization errors:
17161A resynchronization error is one that occurs when trying to initialize
17162all mirror images to be the same. It can happen due to a failure to
17163read the primary image (the image considered to have the 'good' data), or
17164due to a failure to write the secondary images. This type of failure
17165only produces a warning, and it is up to the user to take action in this
17166case. If the error is transient, the user can simply reactivate the
17167mirrored logical volume to make another attempt at resynchronization.
17168If attempts to finish resynchronization fail, 'lvconvert' can be used to
17169remove the faulty device from the mirror.
17170
17171TODO...
17172Some sort of response to this type of error could be automated.
17173Since this document is the definitive source for how to handle device
17174failures, the process should be defined here. If the process is defined
17175but not implemented, it should be noted as such. One idea might be to
17176make a single attempt to suspend/resume the mirror in an attempt to
17177redo the sync operation that failed. On the other hand, if there is
17178a permanent failure, it may simply be best to wait for the user or the
17179automated response that is sure to follow from a write failure.
17180...TODO
17181
17182Mirror write failures:
17183When a write error occurs on a mirror constituent device, an attempt
17184to handle the failure is automatically made. This is done by calling
17185'lvconvert --repair --use-policies'. The policies implied by this
17186command are set in the LVM configuration file. They are:
17187- mirror_log_fault_policy: This defines what action should be taken
17188 if the device containing the log fails. The available options are
17189 "remove" and "allocate". Either of these options will cause the
17190 faulty log device to be removed from the mirror. The "allocate"
17191 policy will attempt the further action of trying to replace the
17192 failed disk log by using space that might be available in the
17193 volume group. If the allocation fails (or the "remove" policy
17194 is specified), the mirror log will be maintained in memory. Should
17195 the machine be rebooted or the logical volume deactivated, a
17196 complete resynchronization of the mirror will be necessary upon
17197 the follow activation - such is the nature of a mirror with a 'core'
17198 log. The default policy for handling log failures is "allocate".
17199 The service disruption incurred by replacing the failed log is
17200 negligible, while the benefits of having persistent log is
17201 pronounced.
17202- mirror_image_fault_policy: This defines what action should be taken
17203 if a device containing an image fails. Again, the available options
17204 are "remove" and "allocate". Both of these options will cause the
17205 faulty image device to be removed - adjusting the logical volume
17206 accordingly. For example, if one image of a 2-way mirror fails, the
17207 mirror will be converted to a linear device. If one image of a
17208 3-way mirror fails, the mirror will be converted to a 2-way mirror.
17209 The "allocate" policy takes the further action of trying to replace
17210 the failed image using space that is available in the volume group.
17211 Replacing a failed mirror image will incure the cost of
17212 resynchronizing - degrading the performance of the mirror. The
17213 default policy for handling an image failure is "remove". This
17214 allows the mirror to still function, but gives the administrator the
17215 choice of when to incure the extra performance costs of replacing
17216 the failed image.
17217
17218RAID logical volume device failures are handled differently from the "mirror"
17219segment type. Discussion of this can be found in lvm2-raid.txt.
17220\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/example_cmdlib.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002063\013062740170\0020726\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
17221 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
17222 *
17223 * This file is part of LVM2.
17224 *
17225 * This copyrighted material is made available to anyone wishing to use,
17226 * modify, copy, or redistribute it subject to the terms and conditions
17227 * of the GNU General Public License v.2.
17228 *
17229 * You should have received a copy of the GNU General Public License
17230 * along with this program; if not, write to the Free Software Foundation,
17231 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17232 */
17233
17234#include "lvm2cmd.h"
17235#include <stdio.h>
17236
17237/* All output gets passed to this function line-by-line */
17238void test_log_fn(int level, const char *file, int line,
17239 int dm_errno, const char *format)
17240{
17241 /* Extract and process output here rather than printing it */
17242
17243 if (level != 4)
17244 return;
17245
17246 printf("%s\n", format);
17247 return;
17248}
17249
17250int main(int argc, char **argv)
17251{
17252 void *handle;
17253 int r;
17254
17255 lvm2_log_fn(test_log_fn);
17256
17257 handle = lvm2_init();
17258
17259 lvm2_log_level(handle, 1);
17260 r = lvm2_run(handle, "vgs --noheadings vg1");
17261
17262 /* More commands here */
17263
17264 lvm2_exit(handle);
17265
17266 return r;
17267}
17268
17269\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/lvm2-raid.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000054741\013062740170\0020165\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0=======================
17270= LVM RAID Design Doc =
17271=======================
17272
17273#############################
17274# Chapter 1: User-Interface #
17275#############################
17276
17277***************** CREATING A RAID DEVICE ******************
17278
1727901: lvcreate --type <RAID type> \
1728002: [--regionsize <size>] \
1728103: [-i/--stripes <#>] [-I,--stripesize <size>] \
1728204: [-m/--mirrors <#>] \
1728305: [--[min|max]recoveryrate <kB/sec/disk>] \
1728406: [--stripecache <size>] \
1728507: [--writemostly <devices>] \
1728608: [--maxwritebehind <size>] \
1728709: [[no]sync] \
1728810: <Other normal args, like: -L 5G -n lv vg> \
1728911: [devices]
17290
17291Line 01:
17292I don't intend for there to be shorthand options for specifying the
17293segment type. The available RAID types are:
17294 "raid0" - Stripe [NOT IMPLEMENTED]
17295 "raid1" - should replace DM Mirroring
17296 "raid10" - striped mirrors, [NOT IMPLEMENTED]
17297 "raid4" - RAID4
17298 "raid5" - Same as "raid5_ls" (Same default as MD)
17299 "raid5_la" - RAID5 Rotating parity 0 with data continuation
17300 "raid5_ra" - RAID5 Rotating parity N with data continuation
17301 "raid5_ls" - RAID5 Rotating parity 0 with data restart
17302 "raid5_rs" - RAID5 Rotating parity N with data restart
17303 "raid6" - Same as "raid6_zr"
17304 "raid6_zr" - RAID6 Rotating parity 0 with data restart
17305 "raid6_nr" - RAID6 Rotating parity N with data restart
17306 "raid6_nc" - RAID6 Rotating parity N with data continuation
17307The exception to 'no shorthand options' will be where the RAID implementations
17308can displace traditional tagets. This is the case with 'mirror' and 'raid1'.
17309In this case, "mirror_segtype_default" - found under the "global" section in
17310lvm.conf - can be set to "mirror" or "raid1". The segment type inferred when
17311the '-m' option is used will be taken from this setting. The default segment
17312types can be overridden on the command line by using the '--type' argument.
17313
17314Line 02:
17315Region size is relevant for all RAID types. It defines the granularity for
17316which the bitmap will track the active areas of disk. The default is currently
173174MiB. I see no reason to change this unless it is a problem for MD performance.
17318MD does impose a restriction of 2^21 regions for a given device, however. This
17319means two things: 1) we should never need a metadata area larger than
173208kiB+sizeof(superblock)+bitmap_offset (IOW, pretty small) and 2) the region
17321size will have to be upwardly revised if the device is larger than 8TiB
17322(assuming defaults).
17323
17324Line 03/04:
17325The '-m/--mirrors' option is only relevant to RAID1 and will be used just like
17326it is today for DM mirroring. For all other RAID types, -i/--stripes and
17327-I/--stripesize are relevant. The former will specify the number of data
17328devices that will be used for striping. For example, if the user specifies
17329'--type raid0 -i 3', then 3 devices are needed. If the user specifies
17330'--type raid6 -i 3', then 5 devices are needed. The -I/--stripesize may be
17331confusing to MD users, as they use the term "chunksize". I think they will
17332adapt without issue and I don't wish to create a conflict with the term
17333"chunksize" that we use for snapshots.
17334
17335Line 05/06/07:
17336I'm still not clear on how to specify these options. Some are easier than
17337others. '--writemostly' is particularly hard because it involves specifying
17338which devices shall be 'write-mostly' and thus, also have 'max-write-behind'
17339applied to them. It has been suggested that a '--readmostly'/'--readfavored'
17340or similar option could be introduced as a way to specify a primary disk vs.
17341specifying all the non-primary disks via '--writemostly'. I like this idea,
17342but haven't come up with a good name yet. Thus, these will remain
17343unimplemented until future specification.
17344
17345Line 09/10/11:
17346These are familiar.
17347
17348Further creation related ideas:
17349Today, you can specify '--type mirror' without an '-m/--mirrors' argument
17350necessary. The number of devices defaults to two (and the log defaults to
17351'disk'). A similar thing should happen with the RAID types. All of them
17352should default to having two data devices unless otherwise specified. This
17353would mean a total number of 2 devices for RAID 0/1, 3 devices for RAID 4/5,
17354and 4 devices for RAID 6/10.
17355
17356
17357***************** CONVERTING A RAID DEVICE ******************
17358
1735901: lvconvert [--type <RAID type>] \
1736002: [-R/--regionsize <size>] \
1736103: [-i/--stripes <#>] [-I,--stripesize <size>] \
1736204: [-m/--mirrors <#>] \
1736305: [--merge]
1736406: [--splitmirrors <#> [--trackchanges]] \
1736507: [--replace <sub_lv|device>] \
1736608: [--[min|max]recoveryrate <kB/sec/disk>] \
1736709: [--stripecache <size>] \
1736810: [--writemostly <devices>] \
1736911: [--maxwritebehind <size>] \
1737012: vg/lv
1737113: [devices]
17372
17373lvconvert should work exactly as it does now when dealing with mirrors -
17374even if(when) we switch to MD RAID1. Of course, there are no plans to
17375allow the presense of the metadata area to be configurable (e.g. --corelog).
17376It will be simple enough to detect if the LV being up/down-converted is
17377new or old-style mirroring.
17378
17379If we choose to use MD RAID0 as well, it will be possible to change the
17380number of stripes and the stripesize. It is therefore conceivable to see
17381something like, 'lvconvert -i +1 vg/lv'.
17382
17383Line 01:
17384It is possible to change the RAID type of an LV - even if that LV is already
17385a RAID device of a different type. For example, you could change from
17386RAID4 to RAID5 or RAID5 to RAID6.
17387
17388Line 02/03/04:
17389These are familiar options - all of which would now be available as options
17390for change. (However, it'd be nice if we didn't have regionsize in there.
17391It's simple on the kernel side, but is just an extra - often unecessary -
17392parameter to many functions in the LVM codebase.)
17393
17394Line 05:
17395This option is used to merge an LV back into a RAID1 array - provided it was
17396split for temporary read-only use by '--splitmirrors 1 --trackchanges'.
17397
17398Line 06:
17399The '--splitmirrors <#>' argument should be familiar from the "mirror" segment
17400type. It allows RAID1 images to be split from the array to form a new LV.
17401Either the original LV or the split LV - or both - could become a linear LV as
17402a result. If the '--trackchanges' argument is specified in addition to
17403'--splitmirrors', an LV will be split from the array. It will be read-only.
17404This operation does not change the original array - except that it uses an empty
17405slot to hold the position of the split LV which it expects to return in the
17406future (see the '--merge' argument). It tracks any changes that occur to the
17407array while the slot is kept in reserve. If the LV is merged back into the
17408array, only the changes are resync'ed to the returning image. Repeating the
17409'lvconvert' operation without the '--trackchanges' option will complete the
17410split of the LV permanently.
17411
17412Line 07:
17413This option allows the user to specify a sub_lv (e.g. a mirror image) or
17414a particular device for replacement. The device (or all the devices in
17415the sub_lv) will be removed and replaced with different devices from the
17416VG.
17417
17418Line 08/09/10/11:
17419It should be possible to alter these parameters of a RAID device. As with
17420lvcreate, however, I'm not entirely certain how to best define some of these.
17421We don't need all the capabilities at once though, so it isn't a pressing
17422issue.
17423
17424Line 12:
17425The LV to operate on.
17426
17427Line 13:
17428Devices that are to be used to satisfy the conversion request. If the
17429operation removes devices or splits a mirror, then the devices specified
17430form the list of candidates for removal. If the operation adds or replaces
17431devices, then the devices specified form the list of candidates for allocation.
17432
17433
17434
17435###############################################
17436# Chapter 2: LVM RAID internal representation #
17437###############################################
17438
17439The internal representation is somewhat like mirroring, but with alterations
17440for the different metadata components. LVM mirroring has a single log LV,
17441but RAID will have one for each data device. Because of this, I've added a
17442new 'areas' list to the 'struct lv_segment' - 'meta_areas'. There is exactly
17443a one-to-one relationship between 'areas' and 'meta_areas'. The 'areas' array
17444still holds the data sub-lv's (similar to mirroring), while the 'meta_areas'
17445array holds the metadata sub-lv's (akin to the mirroring log device).
17446
17447The sub_lvs will be named '%s_rimage_%d' instead of '%s_mimage_%d' as it is
17448for mirroring, and '%s_rmeta_%d' instead of '%s_mlog'. Thus, you can imagine
17449an LV named 'foo' with the following layout:
17450foo
17451[foo's lv_segment]
17452|
17453|-> foo_rimage_0 (areas[0])
17454| [foo_rimage_0's lv_segment]
17455|-> foo_rimage_1 (areas[1])
17456| [foo_rimage_1's lv_segment]
17457|
17458|-> foo_rmeta_0 (meta_areas[0])
17459| [foo_rmeta_0's lv_segment]
17460|-> foo_rmeta_1 (meta_areas[1])
17461| [foo_rmeta_1's lv_segment]
17462
17463LVM Meta-data format
17464====================
17465The RAID format will need to be able to store parameters that are unique to
17466RAID and unique to specific RAID sub-devices. It will be modeled after that
17467of mirroring.
17468
17469Here is an example of the mirroring layout:
17470lv {
17471 id = "agL1vP-1B8Z-5vnB-41cS-lhBJ-Gcvz-dh3L3H"
17472 status = ["READ", "WRITE", "VISIBLE"]
17473 flags = []
17474 segment_count = 1
17475
17476 segment1 {
17477 start_extent = 0
17478 extent_count = 125 # 500 Megabytes
17479
17480 type = "mirror"
17481 mirror_count = 2
17482 mirror_log = "lv_mlog"
17483 region_size = 1024
17484
17485 mirrors = [
17486 "lv_mimage_0", 0,
17487 "lv_mimage_1", 0
17488 ]
17489 }
17490}
17491
17492The real trick is dealing with the metadata devices. Mirroring has an entry,
17493'mirror_log', in the top-level segment. This won't work for RAID because there
17494is a one-to-one mapping between the data devices and the metadata devices. The
17495mirror devices are layed-out in sub-device/le pairs. The 'le' parameter is
17496redundant since it will always be zero. So for RAID, I have simple put the
17497metadata and data devices in pairs without the 'le' parameter.
17498
17499RAID metadata:
17500lv {
17501 id = "EnpqAM-5PEg-i9wB-5amn-P116-1T8k-nS3GfD"
17502 status = ["READ", "WRITE", "VISIBLE"]
17503 flags = []
17504 segment_count = 1
17505
17506 segment1 {
17507 start_extent = 0
17508 extent_count = 125 # 500 Megabytes
17509
17510 type = "raid1"
17511 device_count = 2
17512 region_size = 1024
17513
17514 raids = [
17515 "lv_rmeta_0", "lv_rimage_0",
17516 "lv_rmeta_1", "lv_rimage_1",
17517 ]
17518 }
17519}
17520
17521The metadata also must be capable of representing the various tunables. We
17522already have a good example for one from mirroring, region_size.
17523'max_write_behind', 'stripe_cache', and '[min|max]_recovery_rate' could also
17524be handled in this way. However, 'write_mostly' cannot be handled in this
17525way, because it is a characteristic associated with the sub_lvs, not the
17526array as a whole. In these cases, the status field of the sub-lv's themselves
17527will hold these flags - the meaning being only useful in the larger context.
17528
17529
17530##############################################
17531# Chapter 3: LVM RAID implementation details #
17532##############################################
17533
17534New Segment Type(s)
17535===================
17536I've created a new file 'lib/raid/raid.c' that will handle the various different
17537RAID types. While there will be a unique segment type for each RAID variant,
17538they will all share a common backend - segtype_handler functions and
17539segtype->flags = SEG_RAID.
17540
17541I'm also adding a new field to 'struct segment_type', parity_devs. For every
17542segment_type except RAID4/5/6, this will be 0. This field facilitates in
17543allocation and size calculations. For example, the lvcreate for RAID5 would
17544look something like:
17545~> lvcreate --type raid5 -L 30G -i 3 -n my_raid5 my_vg
17546or
17547~> lvcreate --type raid5 -n my_raid5 my_vg /dev/sd[bcdef]1
17548
17549In the former case, the stripe count (3) and device size are computed, and
17550then 'segtype->parity_devs' extra devices are allocated of the same size. In
17551the latter case, the number of PVs is determined and 'segtype->parity_devs' is
17552subtracted off to determine the number of stripes.
17553
17554This should also work in the case of RAID10 and doing things in this manor
17555should not affect the way size is calculated via the area_multiple.
17556
17557Allocation
17558==========
17559When a RAID device is created, metadata LVs must be created along with the
17560data LVs that will ultimately compose the top-level RAID array. For the
17561foreseeable future, the metadata LVs must reside on the same device as (or
17562at least one of the devices that compose) the data LV. We use this property
17563to simplify the allocation process. Rather than allocating for the data LVs
17564and then asking for a small chunk of space on the same device (or the other
17565way around), we simply ask for the aggregate size of the data LV plus the
17566metadata LV. Once we have the space allocated, we divide it between the
17567metadata and data LVs. This also greatly simplifies the process of finding
17568parallel space for all the data LVs that will compose the RAID array. When
17569a RAID device is resized, we will not need to take the metadata LV into
17570account, because it will already be present.
17571
17572Apart from the metadata areas, the other unique characteristic of RAID
17573devices is the parity device count. The number of parity devices does nothing
17574to the calculation of size-per-device. The 'area_multiple' means nothing
17575here. The parity devices will simply be the same size as all the other devices
17576and will also require a metadata LV (i.e. it is treated no differently than
17577the other devices).
17578
17579Therefore, to allocate space for RAID devices, we need to know two things:
175801) how many parity devices are required and 2) does an allocated area need to
17581be split out for the metadata LVs after finding the space to fill the request.
17582We simply add these two fields to the 'alloc_handle' data structure as,
17583'parity_count' and 'alloc_and_split_meta'. These two fields get set in
17584'_alloc_init'. The 'segtype->parity_devs' holds the number of parity
17585drives and can be directly copied to 'ah->parity_count' and
17586'alloc_and_split_meta' is set when a RAID segtype is detected and
17587'metadata_area_count' has been specified. With these two variables set, we
17588can calculate how many allocated areas we need. Also, in the routines that
17589find the actual space, they stop not when they have found ah->area_count but
17590when they have found (ah->area_count + ah->parity_count).
17591
17592Conversion
17593==========
17594RAID -> RAID, adding images
17595---------------------------
17596When adding images to a RAID array, metadata and data components must be added
17597as a pair. It is best to perform as many operations as possible before writing
17598new LVM metadata. This allows us to error-out without having to unwind any
17599changes. It also makes things easier if the machine should crash during a
17600conversion operation. Thus, the actions performed when adding a new image are:
17601 1) Allocate the required number of metadata/data pairs using the method
17602 describe above in 'Allocation' (i.e. find the metadata/data space
17603 as one unit and split the space between them after found - this keeps
17604 them together on the same device).
17605 2) Form the metadata/data LVs from the allocated space (leave them
17606 visible) - setting required RAID_[IMAGE | META] flags as appropriate.
17607 3) Write the LVM metadata
17608 4) Activate and clear the metadata LVs. The clearing of the metadata
17609 requires the LVM metadata be written (step 3) and is a requirement
17610 before adding the new metadata LVs to the array. If the metadata
17611 is not cleared, it carry residual superblock state from a previous
17612 array the device may have been part of.
17613 5) Deactivate new sub-LVs and set them "hidden".
17614 6) expand the 'first_seg(raid_lv)->areas' and '->meta_areas' array
17615 for inclusion of the new sub-LVs
17616 7) Add new sub-LVs and update 'first_seg(raid_lv)->area_count'
17617 8) Commit new LVM metadata
17618Failure during any of these steps will not affect the original RAID array. In
17619the worst scenario, the user may have to remove the new sub-LVs that did not
17620yet make it into the array.
17621
17622RAID -> RAID, removing images
17623-----------------------------
17624To remove images from a RAID, the metadata/data LV pairs must be removed
17625together. This is pretty straight-forward, but one place where RAID really
17626differs from the "mirror" segment type is how the resulting "holes" are filled.
17627When a device is removed from a "mirror" segment type, it is identified, moved
17628to the end of the 'mirrored_seg->areas' array, and then removed. This action
17629causes the other images to shift down and fill the position of the device which
17630was removed. While "raid1" could be handled in this way, the other RAID types
17631could not be - it would corrupt the ordering of the data on the array. Thus,
17632when a device is removed from a RAID array, the corresponding metadata/data
17633sub-LVs are removed from the 'raid_seg->meta_areas' and 'raid_seg->areas' arrays.
17634The slot in these 'lv_segment_area' arrays are set to 'AREA_UNASSIGNED'. RAID
17635is perfectly happy to construct a DM table mapping with '- -' if it comes across
17636area assigned in such a way. The pair of dashes is a valid way to tell the RAID
17637kernel target that the slot should be considered empty. So, we can remove
17638devices from a RAID array without affecting the correct operation of the RAID.
17639(It also becomes easy to replace the empty slots properly if a spare device is
17640available.) In the case of RAID1 device removal, the empty slot can be safely
17641eliminated. This is done by shifting the higher indexed devices down to fill
17642the slot. Even the names of the images will be renamed to properly reflect
17643their index in the array. Unlike the "mirror" segment type, you will never have
17644an image named "*_rimage_1" occupying the index position 0.
17645
17646As with adding images, removing images holds off on commiting LVM metadata
17647until all possible changes have been made. This reduces the likelyhood of bad
17648intermediate stages being left due to a failure of operation or machine crash.
17649
17650RAID1 '--splitmirrors', '--trackchanges', and '--merge' operations
17651------------------------------------------------------------------
17652This suite of operations is only available to the "raid1" segment type.
17653
17654Splitting an image from a RAID1 array is almost identical to the removal of
17655an image described above. However, the metadata LV associated with the split
17656image is removed and the data LV is kept and promoted to a top-level device.
17657(i.e. It is made visible and stripped of its RAID_IMAGE status flags.)
17658
17659When the '--trackchanges' option is given along with the '--splitmirrors'
17660argument, the metadata LV is left as part of the original array. The data LV
17661is set as 'VISIBLE' and read-only (~LVM_WRITE). When the array DM table is
17662being created, it notices the read-only, VISIBLE nature of the sub-LV and puts
17663in the '- -' sentinel. Only a single image can be split from the mirror and
17664the name of the sub-LV cannot be changed. Unlike '--splitmirrors' on its own,
17665the '--name' argument must not be specified. Therefore, the name of the newly
17666split LV will remain the same '<lv>_rimage_<N>', where 'N' is the index of the
17667slot in the array for which it is associated.
17668
17669When an LV which was split from a RAID1 array with the '--trackchanges' option
17670is merged back into the array, its read/write status is restored and it is
17671set as "hidden" again. Recycling the array (suspend/resume) restores the sub-LV
17672to its position in the array and begins the process of sync'ing the changes that
17673were made since the time it was split from the array.
17674
17675RAID device replacement with '--replace'
17676----------------------------------------
17677This option is available to all RAID segment types.
17678
17679The '--replace' option can be used to remove a particular device from a RAID
17680logical volume and replace it with a different one in one action (CLI command).
17681The device device to be removed is specified as the argument to the '--replace'
17682option. This option can be specified more than once in a single command,
17683allowing multiple devices to be replaced at the same time - provided the RAID
17684logical volume has the necessary redundancy to allow the action. The devices
17685to be used as replacements can also be specified in the command; similar to the
17686way allocatable devices are specified during an up-convert.
17687
17688Example> lvconvert --replace /dev/sdd1 --replace /dev/sde1 vg/lv /dev/sd[bc]1
17689
17690RAID '--repair'
17691---------------
17692This 'lvconvert' option is available to all RAID segment types and is described
17693under "RAID Fault Handling".
17694
17695
17696RAID Fault Handling
17697===================
17698RAID is not like traditional LVM mirroring (i.e. the "mirror" segment type).
17699LVM mirroring required failed devices to be removed or the logical volume would
17700simply hang. RAID arrays can keep on running with failed devices. In fact, for
17701RAID types other than RAID1 removing a device would mean substituting an error
17702target or converting to a lower level RAID (e.g. RAID6 -> RAID5, or RAID4/5 to
17703RAID0). Therefore, rather than removing a failed device unconditionally, the
17704user has a couple of options to choose from.
17705
17706The automated response to a device failure is handled according to the user's
17707preference defined in lvm.conf:activation.raid_fault_policy. The options are:
17708 # "warn" - Use the system log to warn the user that a device in the RAID
17709 # logical volume has failed. It is left to the user to run
17710 # 'lvconvert --repair' manually to remove or replace the failed
17711 # device. As long as the number of failed devices does not
17712 # exceed the redundancy of the logical volume (1 device for
17713 # raid4/5, 2 for raid6, etc) the logical volume will remain
17714 # usable.
17715 #
17716 # "remove" - NOT CURRENTLY IMPLEMENTED OR DOCUMENTED IN example.conf.in.
17717 # Remove the failed device and reduce the RAID logical volume
17718 # accordingly. If a single device dies in a 3-way mirror,
17719 # remove it and reduce the mirror to 2-way. If a single device
17720 # dies in a RAID 4/5 logical volume, reshape it to a striped
17721 # volume, etc - RAID 6 -> RAID 4/5 -> RAID 0. If devices
17722 # cannot be removed for lack of redundancy, fail.
17723 # THIS OPTION CANNOT YET BE IMPLEMENTED BECAUSE RESHAPE IS NOT
17724 # YET SUPPORTED IN linux/drivers/md/dm-raid.c. The superblock
17725 # does not yet hold enough information to support reshaping.
17726 #
17727 # "allocate" - Attempt to use any extra physical volumes in the volume
17728 # group as spares and replace faulty devices.
17729
17730If manual intervention is taken, either in response to the automated solution's
17731"warn" mode or simply because dmeventd hadn't run, then the user can call
17732'lvconvert --repair vg/lv' and follow the prompts. They will be prompted
17733whether or not to replace the device and cause a full recovery of the failed
17734device.
17735
17736If replacement is chosen via the manual method or "allocate" is the policy taken
17737by the automated response, then 'lvconvert --replace' is the mechanism used to
17738attempt the replacement of the failed device.
17739
17740'vgreduce --removemissing' is ineffectual at repairing RAID logical volumes. It
17741will remove the failed device, but the RAID logical volume will simply continue
17742to operate with an <unknown> sub-LV. The user should clear the failed device
17743with 'lvconvert --repair'.
17744\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/pvmove_outline.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003334\013062740170\0021433\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Let's say we have an LV, made up of three segments of different PV's,
17745I've also added in the device major:minor as this will be useful
17746later:
17747
17748+-----------------------------+
17749| PV1 | PV2 | PV3 | 254:3
17750+----------+---------+--------+
17751
17752
17753Now our hero decides to PV move PV2 to PV4:
17754
177551. Suspend our LV (254:3), this starts queueing all io, and flushes
17756 all pending io. Once the suspend has completed we are free to change
17757 the mapping table.
17758
177592. Set up *another* (254:4) device with the mapping table of our LV.
17760
177613. Load a new mapping table into (254:3) that has identity targets for
17762 parts that aren't moving, and a mirror target for parts that are.
17763
177644. Unsuspend (254:3)
17765
17766So now we have:
17767 destination of copy
17768 +--------------------->--------------+
17769 | |
17770+-----------------------------+ + -----------+
17771| Identity | mirror | Ident. | 254:3 | PV4 |
17772+----------+---------+--------+ +------------+
17773 | | |
17774 \/ \/ \/
17775+-----------------------------+
17776| PV1 | PV2 | PV3 | 254:4
17777+----------+---------+--------+
17778
17779Any writes to segment2 of the LV get intercepted by the mirror target
17780who checks that that chunk has been copied to the new destination, if
17781it hasn't it queues the initial copy and defers the current io until
17782it has finished. Then the current io is written to *both* PV2 and the
17783PV4.
17784
177855. When the copying has completed 254:3 is suspended/pending flushed.
17786
177876. 254:4 is taken down
17788
177897. metadata is updated on disk
17790
177918. 254:3 has new mapping table loaded:
17792
17793+-----------------------------+
17794| PV1 | PV4 | PV3 | 254:3
17795+----------+---------+--------+
17796\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/tagging.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012343\013062740170\0020000\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Tagging aims
17797============
17798 1) Ability to attach an unordered list of tags to LVM metadata objects.
17799 2) Ability to add or remove tags easily.
17800 3) Ability to select LVM objects for processing according to presence/absence
17801 of specific tags.
17802 4) Ability to control through the config file which VGs/LVs are activated
17803 on different machines using names or tags.
17804 5) Ability to overlay settings from different config files e.g. override
17805 some settings in a global config file locally.
17806
17807Clarifications
17808==============
17809 1) Tag character set: A-Za-z0-9_+.-
17810 Can't start with hyphen & max length is 128 (NAME_LEN).
17811 2) LVM object types that can be tagged:
17812 VG, LV, LV segment
17813 PV - tags are stored in VG metadata so disappear when PV becomes orphaned
17814 Snapshots can't be tagged, but their origin may be.
17815 3) A tag can be used in place of any command line LVM object reference that
17816 accepts (a) a list of objects; or (b) a single object as long as the
17817 tag expands to a single object. This is not supported everywhere yet.
17818 Duplicate arguments in a list after argument expansion may get removed
17819 retaining the first copy of each argument.
17820 4) Wherever there may be ambiguity of argument type, a tag must be prefixed
17821 by '@'; elsewhere an '@' prefix is optional.
17822 5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
17823 6) Tags can be added or removed with --addtag or --deltag.
17824
17825Config file Extensions
17826======================
17827 To define host tags in config file:
17828
17829 tags {
17830 # Set a tag with the hostname
17831 hosttags = 1
17832
17833 tag1 { }
17834
17835 tag2 {
17836 # If no exact match, tag is not set.
17837 host_list = [ "hostname", "dbase" ]
17838 }
17839 }
17840
17841Activation config file example
17842==============================
17843 activation {
17844 volume_list = [ "vg1/lvol0", "@database" ]
17845 }
17846
17847 Matches against vgname, vgname/lvname or @tag set in *metadata*.
17848 @* matches exactly against *any* tag set on the host.
17849 The VG or LV only gets activated if a metadata tag matches.
17850 The default if there is no match is not to activate.
17851 If volume_list is not present and any tags are defined on the host
17852 then it only activates if a host tag matches a metadata tag.
17853 If volume_list is not present and no tags are defined on the host
17854 then it does activate.
17855
17856Multiple config files
17857=====================
17858 (a) lvm.conf
17859 (b) lvm_<host_tag>.conf
17860
17861 At startup, load lvm.conf.
17862 Process tag settings.
17863 If any host tags were defined, load lvm_tag.conf for each tag, if present.
17864
17865 When searching for a specific config file entry, search order is (b)
17866 then (a), stopping at the first match.
17867 Within (b) use reverse order tags got set, so file for last tag set is
17868 searched first.
17869 New tags set in (b) *do* trigger additional config file loads.
17870
17871Usage Examples
17872==============
17873 1) Simple activation control via metadata with static config files
17874
17875 lvm.conf: (Identical on every machine - global settings)
17876 tags {
17877 hosttags = 1
17878 }
17879
17880 From any machine in the cluster, add db1 to the list of machines that
17881 activate vg1/lvol2:
17882
17883 lvchange --addtag @db1 vg1/lvol2
17884 (followed by lvchange -ay to actually activate it)
17885
17886
17887 2) Multiple hosts.
17888
17889 Activate vg1 only on the database hosts, db1 and db2.
17890 Activate vg2 only on the fileserver host fs1.
17891 Activate nothing initially on the fileserver backup host fsb1, but be
17892 prepared for it to take over from fs1.
17893
17894 Option (i) - centralised admin, static configuration replicated between hosts
17895 # Add @database tag to vg1's metadata
17896 vgchange --addtag @database vg1
17897
17898 # Add @fileserver tag to vg2's metadata
17899 vgchange --addtag @fileserver vg2
17900
17901 lvm.conf: (Identical on every machine)
17902 tags {
17903 database {
17904 host_list = [ "db1", "db2" ]
17905 }
17906 fileserver {
17907 host_list = [ "fs1" ]
17908 }
17909 fileserverbackup {
17910 host_list = [ "fsb1" ]
17911 }
17912 }
17913
17914 activation {
17915 # Only activate if host has a tag that matches a metadata tag
17916 volume_list = [ "@*" ]
17917 }
17918
17919 In the event of the fileserver host going down, vg2 can be brought up
17920 on fsb1 by running *on any node* 'vgchange --addtag @fileserverbackup vg2'
17921 followed by 'vgchange -ay vg2'
17922
17923
17924 Option (ii) - localised admin & configuation
17925 (i.e. each host holds *locally* which classes of volumes to activate)
17926 # Add @database tag to vg1's metadata
17927 vgchange --addtag @database vg1
17928
17929 # Add @fileserver tag to vg2's metadata
17930 vgchange --addtag @fileserver vg2
17931
17932 lvm.conf: (Identical on every machine - global settings)
17933 tags {
17934 hosttags = 1
17935 }
17936
17937 lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
17938 activation {
17939 volume_list = [ "@database" ]
17940 }
17941
17942 lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
17943 activation {
17944 volume_list = [ "@database" ]
17945 }
17946
17947 lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
17948 activation {
17949 volume_list = [ "@fileserver" ]
17950 }
17951
17952 If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
17953 create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
17954
17955 activation {
17956 volume_list = [ "@fileserver" ]
17957 }
17958
17959 and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
17960
17961\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0017074\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/io.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006342\013062740170\0020251\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-io
17962=====
17963
17964Dm-io provides synchronous and asynchronous I/O services. There are three
17965types of I/O services available, and each type has a sync and an async
17966version.
17967
17968The user must set up an io_region structure to describe the desired location
17969of the I/O. Each io_region indicates a block-device along with the starting
17970sector and size of the region.
17971
17972 struct io_region {
17973 struct block_device *bdev;
17974 sector_t sector;
17975 sector_t count;
17976 };
17977
17978Dm-io can read from one io_region or write to one or more io_regions. Writes
17979to multiple regions are specified by an array of io_region structures.
17980
17981The first I/O service type takes a list of memory pages as the data buffer for
17982the I/O, along with an offset into the first page.
17983
17984 struct page_list {
17985 struct page_list *next;
17986 struct page *page;
17987 };
17988
17989 int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
17990 struct page_list *pl, unsigned int offset,
17991 unsigned long *error_bits);
17992 int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
17993 struct page_list *pl, unsigned int offset,
17994 io_notify_fn fn, void *context);
17995
17996The second I/O service type takes an array of bio vectors as the data buffer
17997for the I/O. This service can be handy if the caller has a pre-assembled bio,
17998but wants to direct different portions of the bio to different devices.
17999
18000 int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
18001 int rw, struct bio_vec *bvec,
18002 unsigned long *error_bits);
18003 int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
18004 int rw, struct bio_vec *bvec,
18005 io_notify_fn fn, void *context);
18006
18007The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
18008data buffer for the I/O. This service can be handy if the caller needs to do
18009I/O to a large region but doesn't want to allocate a large number of individual
18010memory pages.
18011
18012 int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
18013 void *data, unsigned long *error_bits);
18014 int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
18015 void *data, io_notify_fn fn, void *context);
18016
18017Callers of the asynchronous I/O services must include the name of a completion
18018callback routine and a pointer to some context data for the I/O.
18019
18020 typedef void (*io_notify_fn)(unsigned long error, void *context);
18021
18022The "error" parameter in this callback, as well as the "*error" parameter in
18023all of the synchronous versions, is a bitset (instead of a simple error value).
18024In the case of an write-I/O to multiple regions, this bitset allows dm-io to
18025indicate success or failure on each individual region.
18026
18027Before using any of the dm-io services, the user should call dm_io_get()
18028and specify the number of pages they expect to perform I/O on concurrently.
18029Dm-io will attempt to resize its mempool to make sure enough pages are
18030always available in order to avoid unnecessary waiting while performing I/O.
18031
18032When the user is finished using the dm-io services, they should call
18033dm_io_put() and specify the same number of pages that were given on the
18034dm_io_get() call.
18035
18036\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/log-writes.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011360\013062740170\0021732\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-log-writes
18037=============
18038
18039This target takes 2 devices, one to pass all IO to normally, and one to log all
18040of the write operations to. This is intended for file system developers wishing
18041to verify the integrity of metadata or data as the file system is written to.
18042There is a log_write_entry written for every WRITE request and the target is
18043able to take arbitrary data from userspace to insert into the log. The data
18044that is in the WRITE requests is copied into the log to make the replay happen
18045exactly as it happened originally.
18046
18047Log Ordering
18048============
18049
18050We log things in order of completion once we are sure the write is no longer in
18051cache. This means that normal WRITE requests are not actually logged until the
18052next REQ_FLUSH request. This is to make it easier for userspace to replay the
18053log in a way that correlates to what is on disk and not what is in cache, to
18054make it easier to detect improper waiting/flushing.
18055
18056This works by attaching all WRITE requests to a list once the write completes.
18057Once we see a REQ_FLUSH request we splice this list onto the request and once
18058the FLUSH request completes we log all of the WRITEs and then the FLUSH. Only
18059completed WRITEs, at the time the REQ_FLUSH is issued, are added in order to
18060simulate the worst case scenario with regard to power failures. Consider the
18061following example (W means write, C means complete):
18062
18063W1,W2,W3,C3,C2,Wflush,C1,Cflush
18064
18065The log would show the following
18066
18067W3,W2,flush,W1....
18068
18069Again this is to simulate what is actually on disk, this allows us to detect
18070cases where a power failure at a particular point in time would create an
18071inconsistent file system.
18072
18073Any REQ_FUA requests bypass this flushing mechanism and are logged as soon as
18074they complete as those requests will obviously bypass the device cache.
18075
18076Any REQ_DISCARD requests are treated like WRITE requests. Otherwise we would
18077have all the DISCARD requests, and then the WRITE requests and then the FLUSH
18078request. Consider the following example:
18079
18080WRITE block 1, DISCARD block 1, FLUSH
18081
18082If we logged DISCARD when it completed, the replay would look like this
18083
18084DISCARD 1, WRITE 1, FLUSH
18085
18086which isn't quite what happened and wouldn't be caught during the log replay.
18087
18088Target interface
18089================
18090
18091i) Constructor
18092
18093 log-writes <dev_path> <log_dev_path>
18094
18095 dev_path : Device that all of the IO will go to normally.
18096 log_dev_path : Device where the log entries are written to.
18097
18098ii) Status
18099
18100 <#logged entries> <highest allocated sector>
18101
18102 #logged entries : Number of logged entries
18103 highest allocated sector : Highest allocated sector
18104
18105iii) Messages
18106
18107 mark <description>
18108
18109 You can use a dmsetup message to set an arbitrary mark in a log.
18110 For example say you want to fsck a file system after every
18111 write, but first you need to replay up to the mkfs to make sure
18112 we're fsck'ing something reasonable, you would do something like
18113 this:
18114
18115 mkfs.btrfs -f /dev/mapper/log
18116 dmsetup message log 0 mark mkfs
18117 <run test>
18118
18119 This would allow you to replay the log up to the mkfs mark and
18120 then replay from that point on doing the fsck check in the
18121 interval that you want.
18122
18123 Every log has a mark at the end labeled "dm-log-writes-end".
18124
18125Userspace component
18126===================
18127
18128There is a userspace tool that will replay the log for you in various ways.
18129It can be found here: https://github.com/josefbacik/log-writes
18130
18131Example usage
18132=============
18133
18134Say you want to test fsync on your file system. You would do something like
18135this:
18136
18137TABLE="0 $(blockdev --getsz /dev/sdb) log-writes /dev/sdb /dev/sdc"
18138dmsetup create log --table "$TABLE"
18139mkfs.btrfs -f /dev/mapper/log
18140dmsetup message log 0 mark mkfs
18141
18142mount /dev/mapper/log /mnt/btrfs-test
18143<some test that does fsync at the end>
18144dmsetup message log 0 mark fsync
18145md5sum /mnt/btrfs-test/foo
18146umount /mnt/btrfs-test
18147
18148dmsetup remove log
18149replay-log --log /dev/sdc --replay /dev/sdb --end-mark fsync
18150mount /dev/sdb /mnt/btrfs-test
18151md5sum /mnt/btrfs-test/foo
18152<verify md5sum's are correct>
18153
18154Another option is to do a complicated file system operation and verify the file
18155system is consistent during the entire operation. You could do this with:
18156
18157TABLE="0 $(blockdev --getsz /dev/sdb) log-writes /dev/sdb /dev/sdc"
18158dmsetup create log --table "$TABLE"
18159mkfs.btrfs -f /dev/mapper/log
18160dmsetup message log 0 mark mkfs
18161
18162mount /dev/mapper/log /mnt/btrfs-test
18163<fsstress to dirty the fs>
18164btrfs filesystem balance /mnt/btrfs-test
18165umount /mnt/btrfs-test
18166dmsetup remove log
18167
18168replay-log --log /dev/sdc --replay /dev/sdb --end-mark mkfs
18169btrfsck /dev/sdb
18170replay-log --log /dev/sdc --replay /dev/sdb --start-mark mkfs \
18171 --fsck "btrfsck /dev/sdb" --check fua
18172
18173And that will replay the log until it sees a FUA request, run the fsck command
18174and if the fsck passes it will replay to the next FUA, until it is completed or
18175the fsck command exists abnormally.
18176\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/log.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004535\013062740170\0020425\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Device-Mapper Logging
18177=====================
18178The device-mapper logging code is used by some of the device-mapper
18179RAID targets to track regions of the disk that are not consistent.
18180A region (or portion of the address space) of the disk may be
18181inconsistent because a RAID stripe is currently being operated on or
18182a machine died while the region was being altered. In the case of
18183mirrors, a region would be considered dirty/inconsistent while you
18184are writing to it because the writes need to be replicated for all
18185the legs of the mirror and may not reach the legs at the same time.
18186Once all writes are complete, the region is considered clean again.
18187
18188There is a generic logging interface that the device-mapper RAID
18189implementations use to perform logging operations (see
18190dm_dirty_log_type in include/linux/dm-dirty-log.h). Various different
18191logging implementations are available and provide different
18192capabilities. The list includes:
18193
18194Type Files
18195==== =====
18196disk drivers/md/dm-log.c
18197core drivers/md/dm-log.c
18198userspace drivers/md/dm-log-userspace* include/linux/dm-log-userspace.h
18199
18200The "disk" log type
18201-------------------
18202This log implementation commits the log state to disk. This way, the
18203logging state survives reboots/crashes.
18204
18205The "core" log type
18206-------------------
18207This log implementation keeps the log state in memory. The log state
18208will not survive a reboot or crash, but there may be a small boost in
18209performance. This method can also be used if no storage device is
18210available for storing log state.
18211
18212The "userspace" log type
18213------------------------
18214This log type simply provides a way to export the log API to userspace,
18215so log implementations can be done there. This is done by forwarding most
18216logging requests to userspace, where a daemon receives and processes the
18217request.
18218
18219The structure used for communication between kernel and userspace are
18220located in include/linux/dm-log-userspace.h. Due to the frequency,
18221diversity, and 2-way communication nature of the exchanges between
18222kernel and userspace, 'connector' is used as the interface for
18223communication.
18224
18225There are currently two userspace log implementations that leverage this
18226framework - "clustered-disk" and "clustered-core". These implementations
18227provide a cluster-coherent log for shared-storage. Device-mapper mirroring
18228can be used in a shared-storage environment when the cluster log implementations
18229are employed.
18230\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/statistics.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000017051\013062740170\0022033\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0DM statistics
18231=============
18232
18233Device Mapper supports the collection of I/O statistics on user-defined
18234regions of a DM device. If no regions are defined no statistics are
18235collected so there isn't any performance impact. Only bio-based DM
18236devices are currently supported.
18237
18238Each user-defined region specifies a starting sector, length and step.
18239Individual statistics will be collected for each step-sized area within
18240the range specified.
18241
18242The I/O statistics counters for each step-sized area of a region are
18243in the same format as /sys/block/*/stat or /proc/diskstats (see:
18244Documentation/iostats.txt). But two extra counters (12 and 13) are
18245provided: total time spent reading and writing. When the histogram
18246argument is used, the 14th parameter is reported that represents the
18247histogram of latencies. All these counters may be accessed by sending
18248the @stats_print message to the appropriate DM device via dmsetup.
18249
18250The reported times are in milliseconds and the granularity depends on
18251the kernel ticks. When the option precise_timestamps is used, the
18252reported times are in nanoseconds.
18253
18254Each region has a corresponding unique identifier, which we call a
18255region_id, that is assigned when the region is created. The region_id
18256must be supplied when querying statistics about the region, deleting the
18257region, etc. Unique region_ids enable multiple userspace programs to
18258request and process statistics for the same DM device without stepping
18259on each other's data.
18260
18261The creation of DM statistics will allocate memory via kmalloc or
18262fallback to using vmalloc space. At most, 1/4 of the overall system
18263memory may be allocated by DM statistics. The admin can see how much
18264memory is used by reading
18265/sys/module/dm_mod/parameters/stats_current_allocated_bytes
18266
18267Messages
18268========
18269
18270 @stats_create <range> <step>
18271 [<number_of_optional_arguments> <optional_arguments>...]
18272 [<program_id> [<aux_data>]]
18273
18274 Create a new region and return the region_id.
18275
18276 <range>
18277 "-" - whole device
18278 "<start_sector>+<length>" - a range of <length> 512-byte sectors
18279 starting with <start_sector>.
18280
18281 <step>
18282 "<area_size>" - the range is subdivided into areas each containing
18283 <area_size> sectors.
18284 "/<number_of_areas>" - the range is subdivided into the specified
18285 number of areas.
18286
18287 <number_of_optional_arguments>
18288 The number of optional arguments
18289
18290 <optional_arguments>
18291 The following optional arguments are supported
18292 precise_timestamps - use precise timer with nanosecond resolution
18293 instead of the "jiffies" variable. When this argument is
18294 used, the resulting times are in nanoseconds instead of
18295 milliseconds. Precise timestamps are a little bit slower
18296 to obtain than jiffies-based timestamps.
18297 histogram:n1,n2,n3,n4,... - collect histogram of latencies. The
18298 numbers n1, n2, etc are times that represent the boundaries
18299 of the histogram. If precise_timestamps is not used, the
18300 times are in milliseconds, otherwise they are in
18301 nanoseconds. For each range, the kernel will report the
18302 number of requests that completed within this range. For
18303 example, if we use "histogram:10,20,30", the kernel will
18304 report four numbers a:b:c:d. a is the number of requests
18305 that took 0-10 ms to complete, b is the number of requests
18306 that took 10-20 ms to complete, c is the number of requests
18307 that took 20-30 ms to complete and d is the number of
18308 requests that took more than 30 ms to complete.
18309
18310 <program_id>
18311 An optional parameter. A name that uniquely identifies
18312 the userspace owner of the range. This groups ranges together
18313 so that userspace programs can identify the ranges they
18314 created and ignore those created by others.
18315 The kernel returns this string back in the output of
18316 @stats_list message, but it doesn't use it for anything else.
18317 If we omit the number of optional arguments, program id must not
18318 be a number, otherwise it would be interpreted as the number of
18319 optional arguments.
18320
18321 <aux_data>
18322 An optional parameter. A word that provides auxiliary data
18323 that is useful to the client program that created the range.
18324 The kernel returns this string back in the output of
18325 @stats_list message, but it doesn't use this value for anything.
18326
18327 @stats_delete <region_id>
18328
18329 Delete the region with the specified id.
18330
18331 <region_id>
18332 region_id returned from @stats_create
18333
18334 @stats_clear <region_id>
18335
18336 Clear all the counters except the in-flight i/o counters.
18337
18338 <region_id>
18339 region_id returned from @stats_create
18340
18341 @stats_list [<program_id>]
18342
18343 List all regions registered with @stats_create.
18344
18345 <program_id>
18346 An optional parameter.
18347 If this parameter is specified, only matching regions
18348 are returned.
18349 If it is not specified, all regions are returned.
18350
18351 Output format:
18352 <region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
18353 precise_timestamps histogram:n1,n2,n3,...
18354
18355 The strings "precise_timestamps" and "histogram" are printed only
18356 if they were specified when creating the region.
18357
18358 @stats_print <region_id> [<starting_line> <number_of_lines>]
18359
18360 Print counters for each step-sized area of a region.
18361
18362 <region_id>
18363 region_id returned from @stats_create
18364
18365 <starting_line>
18366 The index of the starting line in the output.
18367 If omitted, all lines are returned.
18368
18369 <number_of_lines>
18370 The number of lines to include in the output.
18371 If omitted, all lines are returned.
18372
18373 Output format for each step-sized area of a region:
18374
18375 <start_sector>+<length> counters
18376
18377 The first 11 counters have the same meaning as
18378 /sys/block/*/stat or /proc/diskstats.
18379
18380 Please refer to Documentation/iostats.txt for details.
18381
18382 1. the number of reads completed
18383 2. the number of reads merged
18384 3. the number of sectors read
18385 4. the number of milliseconds spent reading
18386 5. the number of writes completed
18387 6. the number of writes merged
18388 7. the number of sectors written
18389 8. the number of milliseconds spent writing
18390 9. the number of I/Os currently in progress
18391 10. the number of milliseconds spent doing I/Os
18392 11. the weighted number of milliseconds spent doing I/Os
18393
18394 Additional counters:
18395 12. the total time spent reading in milliseconds
18396 13. the total time spent writing in milliseconds
18397
18398 @stats_print_clear <region_id> [<starting_line> <number_of_lines>]
18399
18400 Atomically print and then clear all the counters except the
18401 in-flight i/o counters. Useful when the client consuming the
18402 statistics does not want to lose any statistics (those updated
18403 between printing and clearing).
18404
18405 <region_id>
18406 region_id returned from @stats_create
18407
18408 <starting_line>
18409 The index of the starting line in the output.
18410 If omitted, all lines are printed and then cleared.
18411
18412 <number_of_lines>
18413 The number of lines to process.
18414 If omitted, all lines are printed and then cleared.
18415
18416 @stats_set_aux <region_id> <aux_data>
18417
18418 Store auxiliary data aux_data for the specified region.
18419
18420 <region_id>
18421 region_id returned from @stats_create
18422
18423 <aux_data>
18424 The string that identifies data which is useful to the client
18425 program that created the range. The kernel returns this
18426 string back in the output of @stats_list message, but it
18427 doesn't use this value for anything.
18428
18429Examples
18430========
18431
18432Subdivide the DM device 'vol' into 100 pieces and start collecting
18433statistics on them:
18434
18435 dmsetup message vol 0 @stats_create - /100
18436
18437Set the auxiliary data string to "foo bar baz" (the escape for each
18438space must also be escaped, otherwise the shell will consume them):
18439
18440 dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz
18441
18442List the statistics:
18443
18444 dmsetup message vol 0 @stats_list
18445
18446Print the statistics:
18447
18448 dmsetup message vol 0 @stats_print 0
18449
18450Delete the statistics:
18451
18452 dmsetup message vol 0 @stats_delete 0
18453\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/verity.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000017550\013062740170\0021167\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-verity
18454==========
18455
18456Device-Mapper's "verity" target provides transparent integrity checking of
18457block devices using a cryptographic digest provided by the kernel crypto API.
18458This target is read-only.
18459
18460Construction Parameters
18461=======================
18462 <version> <dev> <hash_dev>
18463 <data_block_size> <hash_block_size>
18464 <num_data_blocks> <hash_start_block>
18465 <algorithm> <digest> <salt>
18466 [<#opt_params> <opt_params>]
18467
18468<version>
18469 This is the type of the on-disk hash format.
18470
18471 0 is the original format used in the Chromium OS.
18472 The salt is appended when hashing, digests are stored continuously and
18473 the rest of the block is padded with zeroes.
18474
18475 1 is the current format that should be used for new devices.
18476 The salt is prepended when hashing and each digest is
18477 padded with zeroes to the power of two.
18478
18479<dev>
18480 This is the device containing data, the integrity of which needs to be
18481 checked. It may be specified as a path, like /dev/sdaX, or a device number,
18482 <major>:<minor>.
18483
18484<hash_dev>
18485 This is the device that supplies the hash tree data. It may be
18486 specified similarly to the device path and may be the same device. If the
18487 same device is used, the hash_start should be outside the configured
18488 dm-verity device.
18489
18490<data_block_size>
18491 The block size on a data device in bytes.
18492 Each block corresponds to one digest on the hash device.
18493
18494<hash_block_size>
18495 The size of a hash block in bytes.
18496
18497<num_data_blocks>
18498 The number of data blocks on the data device. Additional blocks are
18499 inaccessible. You can place hashes to the same partition as data, in this
18500 case hashes are placed after <num_data_blocks>.
18501
18502<hash_start_block>
18503 This is the offset, in <hash_block_size>-blocks, from the start of hash_dev
18504 to the root block of the hash tree.
18505
18506<algorithm>
18507 The cryptographic hash algorithm used for this device. This should
18508 be the name of the algorithm, like "sha1".
18509
18510<digest>
18511 The hexadecimal encoding of the cryptographic hash of the root hash block
18512 and the salt. This hash should be trusted as there is no other authenticity
18513 beyond this point.
18514
18515<salt>
18516 The hexadecimal encoding of the salt value.
18517
18518<#opt_params>
18519 Number of optional parameters. If there are no optional parameters,
18520 the optional paramaters section can be skipped or #opt_params can be zero.
18521 Otherwise #opt_params is the number of following arguments.
18522
18523 Example of optional parameters section:
18524 1 ignore_corruption
18525
18526ignore_corruption
18527 Log corrupted blocks, but allow read operations to proceed normally.
18528
18529restart_on_corruption
18530 Restart the system when a corrupted block is discovered. This option is
18531 not compatible with ignore_corruption and requires user space support to
18532 avoid restart loops.
18533
18534ignore_zero_blocks
18535 Do not verify blocks that are expected to contain zeroes and always return
18536 zeroes instead. This may be useful if the partition contains unused blocks
18537 that are not guaranteed to contain zeroes.
18538
18539use_fec_from_device <fec_dev>
18540 Use forward error correction (FEC) to recover from corruption if hash
18541 verification fails. Use encoding data from the specified device. This
18542 may be the same device where data and hash blocks reside, in which case
18543 fec_start must be outside data and hash areas.
18544
18545 If the encoding data covers additional metadata, it must be accessible
18546 on the hash device after the hash blocks.
18547
18548 Note: block sizes for data and hash devices must match. Also, if the
18549 verity <dev> is encrypted the <fec_dev> should be too.
18550
18551fec_roots <num>
18552 Number of generator roots. This equals to the number of parity bytes in
18553 the encoding data. For example, in RS(M, N) encoding, the number of roots
18554 is M-N.
18555
18556fec_blocks <num>
18557 The number of encoding data blocks on the FEC device. The block size for
18558 the FEC device is <data_block_size>.
18559
18560fec_start <offset>
18561 This is the offset, in <data_block_size> blocks, from the start of the
18562 FEC device to the beginning of the encoding data.
18563
18564
18565Theory of operation
18566===================
18567
18568dm-verity is meant to be set up as part of a verified boot path. This
18569may be anything ranging from a boot using tboot or trustedgrub to just
18570booting from a known-good device (like a USB drive or CD).
18571
18572When a dm-verity device is configured, it is expected that the caller
18573has been authenticated in some way (cryptographic signatures, etc).
18574After instantiation, all hashes will be verified on-demand during
18575disk access. If they cannot be verified up to the root node of the
18576tree, the root hash, then the I/O will fail. This should detect
18577tampering with any data on the device and the hash data.
18578
18579Cryptographic hashes are used to assert the integrity of the device on a
18580per-block basis. This allows for a lightweight hash computation on first read
18581into the page cache. Block hashes are stored linearly, aligned to the nearest
18582block size.
18583
18584If forward error correction (FEC) support is enabled any recovery of
18585corrupted data will be verified using the cryptographic hash of the
18586corresponding data. This is why combining error correction with
18587integrity checking is essential.
18588
18589Hash Tree
18590---------
18591
18592Each node in the tree is a cryptographic hash. If it is a leaf node, the hash
18593of some data block on disk is calculated. If it is an intermediary node,
18594the hash of a number of child nodes is calculated.
18595
18596Each entry in the tree is a collection of neighboring nodes that fit in one
18597block. The number is determined based on block_size and the size of the
18598selected cryptographic digest algorithm. The hashes are linearly-ordered in
18599this entry and any unaligned trailing space is ignored but included when
18600calculating the parent node.
18601
18602The tree looks something like:
18603
18604alg = sha256, num_blocks = 32768, block_size = 4096
18605
18606 [ root ]
18607 / . . . \
18608 [entry_0] [entry_1]
18609 / . . . \ . . . \
18610 [entry_0_0] . . . [entry_0_127] . . . . [entry_1_127]
18611 / ... \ / . . . \ / \
18612 blk_0 ... blk_127 blk_16256 blk_16383 blk_32640 . . . blk_32767
18613
18614
18615On-disk format
18616==============
18617
18618The verity kernel code does not read the verity metadata on-disk header.
18619It only reads the hash blocks which directly follow the header.
18620It is expected that a user-space tool will verify the integrity of the
18621verity header.
18622
18623Alternatively, the header can be omitted and the dmsetup parameters can
18624be passed via the kernel command-line in a rooted chain of trust where
18625the command-line is verified.
18626
18627Directly following the header (and with sector number padded to the next hash
18628block boundary) are the hash blocks which are stored a depth at a time
18629(starting from the root), sorted in order of increasing index.
18630
18631The full specification of kernel parameters and on-disk metadata format
18632is available at the cryptsetup project's wiki page
18633 https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
18634
18635Status
18636======
18637V (for Valid) is returned if every check performed so far was valid.
18638If any check failed, C (for Corruption) is returned.
18639
18640Example
18641=======
18642Set up a device:
18643 # dmsetup create vroot --readonly --table \
18644 "0 2097152 verity 1 /dev/sda1 /dev/sda2 4096 4096 262144 1 sha256 "\
18645 "4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\
18646 "1234000000000000000000000000000000000000000000000000000000000000"
18647
18648A command line tool veritysetup is available to compute or verify
18649the hash tree or activate the kernel device. This is available from
18650the cryptsetup upstream repository https://gitlab.com/cryptsetup/cryptsetup/
18651(as a libcryptsetup extension).
18652
18653Create hash on the device:
18654 # veritysetup format /dev/sda1 /dev/sda2
18655 ...
18656 Root hash: 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
18657
18658Activate the device:
18659 # veritysetup create vroot /dev/sda1 /dev/sda2 \
18660 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
18661\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/flakey.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003552\013062740170\0021115\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-flakey
18662=========
18663
18664This target is the same as the linear target except that it exhibits
18665unreliable behaviour periodically. It's been found useful in simulating
18666failing devices for testing purposes.
18667
18668Starting from the time the table is loaded, the device is available for
18669<up interval> seconds, then exhibits unreliable behaviour for <down
18670interval> seconds, and then this cycle repeats.
18671
18672Also, consider using this in combination with the dm-delay target too,
18673which can delay reads and writes and/or send them to different
18674underlying devices.
18675
18676Table parameters
18677----------------
18678 <dev path> <offset> <up interval> <down interval> \
18679 [<num_features> [<feature arguments>]]
18680
18681Mandatory parameters:
18682 <dev path>: Full pathname to the underlying block-device, or a
18683 "major:minor" device-number.
18684 <offset>: Starting sector within the device.
18685 <up interval>: Number of seconds device is available.
18686 <down interval>: Number of seconds device returns errors.
18687
18688Optional feature parameters:
18689 If no feature parameters are present, during the periods of
18690 unreliability, all I/O returns errors.
18691
18692 drop_writes:
18693 All write I/O is silently ignored.
18694 Read I/O is handled correctly.
18695
18696 corrupt_bio_byte <Nth_byte> <direction> <value> <flags>:
18697 During <down interval>, replace <Nth_byte> of the data of
18698 each matching bio with <value>.
18699
18700 <Nth_byte>: The offset of the byte to replace.
18701 Counting starts at 1, to replace the first byte.
18702 <direction>: Either 'r' to corrupt reads or 'w' to corrupt writes.
18703 'w' is incompatible with drop_writes.
18704 <value>: The value (from 0-255) to write.
18705 <flags>: Perform the replacement only if bio->bi_rw has all the
18706 selected flags set.
18707
18708Examples:
18709 corrupt_bio_byte 32 r 1 0
18710 - replaces the 32nd byte of READ bios with the value 1
18711
18712 corrupt_bio_byte 224 w 0 32
18713 - replaces the 224th byte of REQ_META (=32) bios with the value 0
18714\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/queue-length.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002302\013062740170\0022235\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-queue-length
18715===============
18716
18717dm-queue-length is a path selector module for device-mapper targets,
18718which selects a path with the least number of in-flight I/Os.
18719The path selector name is 'queue-length'.
18720
18721Table parameters for each path: [<repeat_count>]
18722 <repeat_count>: The number of I/Os to dispatch using the selected
18723 path before switching to the next path.
18724 If not given, internal default is used. To check
18725 the default value, see the activated table.
18726
18727Status for each path: <status> <fail-count> <in-flight>
18728 <status>: 'A' if the path is active, 'F' if the path is failed.
18729 <fail-count>: The number of path failures.
18730 <in-flight>: The number of in-flight I/Os on the path.
18731
18732
18733Algorithm
18734=========
18735
18736dm-queue-length increments/decrements 'in-flight' when an I/O is
18737dispatched/completed respectively.
18738dm-queue-length selects a path with the minimum 'in-flight'.
18739
18740
18741Examples
18742========
18743In case that 2 paths (sda and sdb) are used with repeat_count == 128.
18744
18745# echo "0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128" \
18746 dmsetup create test
18747#
18748# dmsetup table
18749test: 0 10 multipath 0 0 1 1 queue-length 0 2 1 8:0 128 8:16 128
18750#
18751# dmsetup status
18752test: 0 10 multipath 2 0 0 0 1 1 E 0 2 1 8:0 A 0 0 8:16 A 0 0
18753\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/switch.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012643\013062740170\0021144\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-switch
18754=========
18755
18756The device-mapper switch target creates a device that supports an
18757arbitrary mapping of fixed-size regions of I/O across a fixed set of
18758paths. The path used for any specific region can be switched
18759dynamically by sending the target a message.
18760
18761It maps I/O to underlying block devices efficiently when there is a large
18762number of fixed-sized address regions but there is no simple pattern
18763that would allow for a compact representation of the mapping such as
18764dm-stripe.
18765
18766Background
18767----------
18768
18769Dell EqualLogic and some other iSCSI storage arrays use a distributed
18770frameless architecture. In this architecture, the storage group
18771consists of a number of distinct storage arrays ("members") each having
18772independent controllers, disk storage and network adapters. When a LUN
18773is created it is spread across multiple members. The details of the
18774spreading are hidden from initiators connected to this storage system.
18775The storage group exposes a single target discovery portal, no matter
18776how many members are being used. When iSCSI sessions are created, each
18777session is connected to an eth port on a single member. Data to a LUN
18778can be sent on any iSCSI session, and if the blocks being accessed are
18779stored on another member the I/O will be forwarded as required. This
18780forwarding is invisible to the initiator. The storage layout is also
18781dynamic, and the blocks stored on disk may be moved from member to
18782member as needed to balance the load.
18783
18784This architecture simplifies the management and configuration of both
18785the storage group and initiators. In a multipathing configuration, it
18786is possible to set up multiple iSCSI sessions to use multiple network
18787interfaces on both the host and target to take advantage of the
18788increased network bandwidth. An initiator could use a simple round
18789robin algorithm to send I/O across all paths and let the storage array
18790members forward it as necessary, but there is a performance advantage to
18791sending data directly to the correct member.
18792
18793A device-mapper table already lets you map different regions of a
18794device onto different targets. However in this architecture the LUN is
18795spread with an address region size on the order of 10s of MBs, which
18796means the resulting table could have more than a million entries and
18797consume far too much memory.
18798
18799Using this device-mapper switch target we can now build a two-layer
18800device hierarchy:
18801
18802 Upper Tier - Determine which array member the I/O should be sent to.
18803 Lower Tier - Load balance amongst paths to a particular member.
18804
18805The lower tier consists of a single dm multipath device for each member.
18806Each of these multipath devices contains the set of paths directly to
18807the array member in one priority group, and leverages existing path
18808selectors to load balance amongst these paths. We also build a
18809non-preferred priority group containing paths to other array members for
18810failover reasons.
18811
18812The upper tier consists of a single dm-switch device. This device uses
18813a bitmap to look up the location of the I/O and choose the appropriate
18814lower tier device to route the I/O. By using a bitmap we are able to
18815use 4 bits for each address range in a 16 member group (which is very
18816large for us). This is a much denser representation than the dm table
18817b-tree can achieve.
18818
18819Construction Parameters
18820=======================
18821
18822 <num_paths> <region_size> <num_optional_args> [<optional_args>...]
18823 [<dev_path> <offset>]+
18824
18825<num_paths>
18826 The number of paths across which to distribute the I/O.
18827
18828<region_size>
18829 The number of 512-byte sectors in a region. Each region can be redirected
18830 to any of the available paths.
18831
18832<num_optional_args>
18833 The number of optional arguments. Currently, no optional arguments
18834 are supported and so this must be zero.
18835
18836<dev_path>
18837 The block device that represents a specific path to the device.
18838
18839<offset>
18840 The offset of the start of data on the specific <dev_path> (in units
18841 of 512-byte sectors). This number is added to the sector number when
18842 forwarding the request to the specific path. Typically it is zero.
18843
18844Messages
18845========
18846
18847set_region_mappings <index>:<path_nr> [<index>]:<path_nr> [<index>]:<path_nr>...
18848
18849Modify the region table by specifying which regions are redirected to
18850which paths.
18851
18852<index>
18853 The region number (region size was specified in constructor parameters).
18854 If index is omitted, the next region (previous index + 1) is used.
18855 Expressed in hexadecimal (WITHOUT any prefix like 0x).
18856
18857<path_nr>
18858 The path number in the range 0 ... (<num_paths> - 1).
18859 Expressed in hexadecimal (WITHOUT any prefix like 0x).
18860
18861R<n>,<m>
18862 This parameter allows repetitive patterns to be loaded quickly. <n> and <m>
18863 are hexadecimal numbers. The last <n> mappings are repeated in the next <m>
18864 slots.
18865
18866Status
18867======
18868
18869No status line is reported.
18870
18871Example
18872=======
18873
18874Assume that you have volumes vg1/switch0 vg1/switch1 vg1/switch2 with
18875the same size.
18876
18877Create a switch device with 64kB region size:
18878 dmsetup create switch --table "0 `blockdev --getsize /dev/vg1/switch0`
18879 switch 3 128 0 /dev/vg1/switch0 0 /dev/vg1/switch1 0 /dev/vg1/switch2 0"
18880
18881Set mappings for the first 7 entries to point to devices switch0, switch1,
18882switch2, switch0, switch1, switch2, switch1:
18883 dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1
18884
18885Set repetitive mapping. This command:
18886 dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10
18887is equivalent to:
18888 dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \
18889 :1 :2 :1 :2 :1 :2 :1 :2 :1 :2
18890
18891\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/persistent-data.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005624\013062740170\0022753\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Introduction
18892============
18893
18894The more-sophisticated device-mapper targets require complex metadata
18895that is managed in kernel. In late 2010 we were seeing that various
18896different targets were rolling their own data structures, for example:
18897
18898- Mikulas Patocka's multisnap implementation
18899- Heinz Mauelshagen's thin provisioning target
18900- Another btree-based caching target posted to dm-devel
18901- Another multi-snapshot target based on a design of Daniel Phillips
18902
18903Maintaining these data structures takes a lot of work, so if possible
18904we'd like to reduce the number.
18905
18906The persistent-data library is an attempt to provide a re-usable
18907framework for people who want to store metadata in device-mapper
18908targets. It's currently used by the thin-provisioning target and an
18909upcoming hierarchical storage target.
18910
18911Overview
18912========
18913
18914The main documentation is in the header files which can all be found
18915under drivers/md/persistent-data.
18916
18917The block manager
18918-----------------
18919
18920dm-block-manager.[hc]
18921
18922This provides access to the data on disk in fixed sized-blocks. There
18923is a read/write locking interface to prevent concurrent accesses, and
18924keep data that is being used in the cache.
18925
18926Clients of persistent-data are unlikely to use this directly.
18927
18928The transaction manager
18929-----------------------
18930
18931dm-transaction-manager.[hc]
18932
18933This restricts access to blocks and enforces copy-on-write semantics.
18934The only way you can get hold of a writable block through the
18935transaction manager is by shadowing an existing block (ie. doing
18936copy-on-write) or allocating a fresh one. Shadowing is elided within
18937the same transaction so performance is reasonable. The commit method
18938ensures that all data is flushed before it writes the superblock.
18939On power failure your metadata will be as it was when last committed.
18940
18941The Space Maps
18942--------------
18943
18944dm-space-map.h
18945dm-space-map-metadata.[hc]
18946dm-space-map-disk.[hc]
18947
18948On-disk data structures that keep track of reference counts of blocks.
18949Also acts as the allocator of new blocks. Currently two
18950implementations: a simpler one for managing blocks on a different
18951device (eg. thinly-provisioned data blocks); and one for managing
18952the metadata space. The latter is complicated by the need to store
18953its own data within the space it's managing.
18954
18955The data structures
18956-------------------
18957
18958dm-btree.[hc]
18959dm-btree-remove.c
18960dm-btree-spine.c
18961dm-btree-internal.h
18962
18963Currently there is only one data structure, a hierarchical btree.
18964There are plans to add more. For example, something with an
18965array-like interface would see a lot of use.
18966
18967The btree is 'hierarchical' in that you can define it to be composed
18968of nested btrees, and take multiple keys. For example, the
18969thin-provisioning target uses a btree with two levels of nesting.
18970The first maps a device id to a mapping tree, and that in turn maps a
18971virtual block to a physical block.
18972
18973Values stored in the btrees can have arbitrary size. Keys are always
1897464bits, although nesting allows you to use multiple keys.
18975\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/linear.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002641\013062740170\0021112\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-linear
18976=========
18977
18978Device-Mapper's "linear" target maps a linear range of the Device-Mapper
18979device onto a linear range of another device. This is the basic building
18980block of logical volume managers.
18981
18982Parameters: <dev path> <offset>
18983 <dev path>: Full pathname to the underlying block-device, or a
18984 "major:minor" device-number.
18985 <offset>: Starting sector within the device.
18986
18987
18988Example scripts
18989===============
18990[[
18991#!/bin/sh
18992# Create an identity mapping for a device
18993echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
18994]]
18995
18996
18997[[
18998#!/bin/sh
18999# Join 2 devices together
19000size1=`blockdev --getsize $1`
19001size2=`blockdev --getsize $2`
19002echo "0 $size1 linear $1 0
19003$size1 $size2 linear $2 0" | dmsetup create joined
19004]]
19005
19006
19007[[
19008#!/usr/bin/perl -w
19009# Split a device into 4M chunks and then join them together in reverse order.
19010
19011my $name = "reverse";
19012my $extent_size = 4 * 1024 * 2;
19013my $dev = $ARGV[0];
19014my $table = "";
19015my $count = 0;
19016
19017if (!defined($dev)) {
19018 die("Please specify a device.\n");
19019}
19020
19021my $dev_size = `blockdev --getsize $dev`;
19022my $extents = int($dev_size / $extent_size) -
19023 (($dev_size % $extent_size) ? 1 : 0);
19024
19025while ($extents > 0) {
19026 my $this_start = $count * $extent_size;
19027 $extents--;
19028 $count++;
19029 my $this_offset = $extents * $extent_size;
19030
19031 $table .= "$this_start $extent_size linear $dev $this_offset\n";
19032}
19033
19034`echo \"$table\" | dmsetup create $name`;
19035]]
19036\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/thin-provisioning.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000034461\013062740170\0023333\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Introduction
19037============
19038
19039This document describes a collection of device-mapper targets that
19040between them implement thin-provisioning and snapshots.
19041
19042The main highlight of this implementation, compared to the previous
19043implementation of snapshots, is that it allows many virtual devices to
19044be stored on the same data volume. This simplifies administration and
19045allows the sharing of data between volumes, thus reducing disk usage.
19046
19047Another significant feature is support for an arbitrary depth of
19048recursive snapshots (snapshots of snapshots of snapshots ...). The
19049previous implementation of snapshots did this by chaining together
19050lookup tables, and so performance was O(depth). This new
19051implementation uses a single data structure to avoid this degradation
19052with depth. Fragmentation may still be an issue, however, in some
19053scenarios.
19054
19055Metadata is stored on a separate device from data, giving the
19056administrator some freedom, for example to:
19057
19058- Improve metadata resilience by storing metadata on a mirrored volume
19059 but data on a non-mirrored one.
19060
19061- Improve performance by storing the metadata on SSD.
19062
19063Status
19064======
19065
19066These targets are very much still in the EXPERIMENTAL state. Please
19067do not yet rely on them in production. But do experiment and offer us
19068feedback. Different use cases will have different performance
19069characteristics, for example due to fragmentation of the data volume.
19070
19071If you find this software is not performing as expected please mail
19072dm-devel@redhat.com with details and we'll try our best to improve
19073things for you.
19074
19075Userspace tools for checking and repairing the metadata are under
19076development.
19077
19078Cookbook
19079========
19080
19081This section describes some quick recipes for using thin provisioning.
19082They use the dmsetup program to control the device-mapper driver
19083directly. End users will be advised to use a higher-level volume
19084manager such as LVM2 once support has been added.
19085
19086Pool device
19087-----------
19088
19089The pool device ties together the metadata volume and the data volume.
19090It maps I/O linearly to the data volume and updates the metadata via
19091two mechanisms:
19092
19093- Function calls from the thin targets
19094
19095- Device-mapper 'messages' from userspace which control the creation of new
19096 virtual devices amongst other things.
19097
19098Setting up a fresh pool device
19099------------------------------
19100
19101Setting up a pool device requires a valid metadata device, and a
19102data device. If you do not have an existing metadata device you can
19103make one by zeroing the first 4k to indicate empty metadata.
19104
19105 dd if=/dev/zero of=$metadata_dev bs=4096 count=1
19106
19107The amount of metadata you need will vary according to how many blocks
19108are shared between thin devices (i.e. through snapshots). If you have
19109less sharing than average you'll need a larger-than-average metadata device.
19110
19111As a guide, we suggest you calculate the number of bytes to use in the
19112metadata device as 48 * $data_dev_size / $data_block_size but round it up
19113to 2MB if the answer is smaller. If you're creating large numbers of
19114snapshots which are recording large amounts of change, you may find you
19115need to increase this.
19116
19117The largest size supported is 16GB: If the device is larger,
19118a warning will be issued and the excess space will not be used.
19119
19120Reloading a pool table
19121----------------------
19122
19123You may reload a pool's table, indeed this is how the pool is resized
19124if it runs out of space. (N.B. While specifying a different metadata
19125device when reloading is not forbidden at the moment, things will go
19126wrong if it does not route I/O to exactly the same on-disk location as
19127previously.)
19128
19129Using an existing pool device
19130-----------------------------
19131
19132 dmsetup create pool \
19133 --table "0 20971520 thin-pool $metadata_dev $data_dev \
19134 $data_block_size $low_water_mark"
19135
19136$data_block_size gives the smallest unit of disk space that can be
19137allocated at a time expressed in units of 512-byte sectors.
19138$data_block_size must be between 128 (64KB) and 2097152 (1GB) and a
19139multiple of 128 (64KB). $data_block_size cannot be changed after the
19140thin-pool is created. People primarily interested in thin provisioning
19141may want to use a value such as 1024 (512KB). People doing lots of
19142snapshotting may want a smaller value such as 128 (64KB). If you are
19143not zeroing newly-allocated data, a larger $data_block_size in the
19144region of 256000 (128MB) is suggested.
19145
19146$low_water_mark is expressed in blocks of size $data_block_size. If
19147free space on the data device drops below this level then a dm event
19148will be triggered which a userspace daemon should catch allowing it to
19149extend the pool device. Only one such event will be sent.
19150Resuming a device with a new table itself triggers an event so the
19151userspace daemon can use this to detect a situation where a new table
19152already exceeds the threshold.
19153
19154A low water mark for the metadata device is maintained in the kernel and
19155will trigger a dm event if free space on the metadata device drops below
19156it.
19157
19158Updating on-disk metadata
19159-------------------------
19160
19161On-disk metadata is committed every time a FLUSH or FUA bio is written.
19162If no such requests are made then commits will occur every second. This
19163means the thin-provisioning target behaves like a physical disk that has
19164a volatile write cache. If power is lost you may lose some recent
19165writes. The metadata should always be consistent in spite of any crash.
19166
19167If data space is exhausted the pool will either error or queue IO
19168according to the configuration (see: error_if_no_space). If metadata
19169space is exhausted or a metadata operation fails: the pool will error IO
19170until the pool is taken offline and repair is performed to 1) fix any
19171potential inconsistencies and 2) clear the flag that imposes repair.
19172Once the pool's metadata device is repaired it may be resized, which
19173will allow the pool to return to normal operation. Note that if a pool
19174is flagged as needing repair, the pool's data and metadata devices
19175cannot be resized until repair is performed. It should also be noted
19176that when the pool's metadata space is exhausted the current metadata
19177transaction is aborted. Given that the pool will cache IO whose
19178completion may have already been acknowledged to upper IO layers
19179(e.g. filesystem) it is strongly suggested that consistency checks
19180(e.g. fsck) be performed on those layers when repair of the pool is
19181required.
19182
19183Thin provisioning
19184-----------------
19185
19186i) Creating a new thinly-provisioned volume.
19187
19188 To create a new thinly- provisioned volume you must send a message to an
19189 active pool device, /dev/mapper/pool in this example.
19190
19191 dmsetup message /dev/mapper/pool 0 "create_thin 0"
19192
19193 Here '0' is an identifier for the volume, a 24-bit number. It's up
19194 to the caller to allocate and manage these identifiers. If the
19195 identifier is already in use, the message will fail with -EEXIST.
19196
19197ii) Using a thinly-provisioned volume.
19198
19199 Thinly-provisioned volumes are activated using the 'thin' target:
19200
19201 dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
19202
19203 The last parameter is the identifier for the thinp device.
19204
19205Internal snapshots
19206------------------
19207
19208i) Creating an internal snapshot.
19209
19210 Snapshots are created with another message to the pool.
19211
19212 N.B. If the origin device that you wish to snapshot is active, you
19213 must suspend it before creating the snapshot to avoid corruption.
19214 This is NOT enforced at the moment, so please be careful!
19215
19216 dmsetup suspend /dev/mapper/thin
19217 dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
19218 dmsetup resume /dev/mapper/thin
19219
19220 Here '1' is the identifier for the volume, a 24-bit number. '0' is the
19221 identifier for the origin device.
19222
19223ii) Using an internal snapshot.
19224
19225 Once created, the user doesn't have to worry about any connection
19226 between the origin and the snapshot. Indeed the snapshot is no
19227 different from any other thinly-provisioned device and can be
19228 snapshotted itself via the same method. It's perfectly legal to
19229 have only one of them active, and there's no ordering requirement on
19230 activating or removing them both. (This differs from conventional
19231 device-mapper snapshots.)
19232
19233 Activate it exactly the same way as any other thinly-provisioned volume:
19234
19235 dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
19236
19237External snapshots
19238------------------
19239
19240You can use an external _read only_ device as an origin for a
19241thinly-provisioned volume. Any read to an unprovisioned area of the
19242thin device will be passed through to the origin. Writes trigger
19243the allocation of new blocks as usual.
19244
19245One use case for this is VM hosts that want to run guests on
19246thinly-provisioned volumes but have the base image on another device
19247(possibly shared between many VMs).
19248
19249You must not write to the origin device if you use this technique!
19250Of course, you may write to the thin device and take internal snapshots
19251of the thin volume.
19252
19253i) Creating a snapshot of an external device
19254
19255 This is the same as creating a thin device.
19256 You don't mention the origin at this stage.
19257
19258 dmsetup message /dev/mapper/pool 0 "create_thin 0"
19259
19260ii) Using a snapshot of an external device.
19261
19262 Append an extra parameter to the thin target specifying the origin:
19263
19264 dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 0 /dev/image"
19265
19266 N.B. All descendants (internal snapshots) of this snapshot require the
19267 same extra origin parameter.
19268
19269Deactivation
19270------------
19271
19272All devices using a pool must be deactivated before the pool itself
19273can be.
19274
19275 dmsetup remove thin
19276 dmsetup remove snap
19277 dmsetup remove pool
19278
19279Reference
19280=========
19281
19282'thin-pool' target
19283------------------
19284
19285i) Constructor
19286
19287 thin-pool <metadata dev> <data dev> <data block size (sectors)> \
19288 <low water mark (blocks)> [<number of feature args> [<arg>]*]
19289
19290 Optional feature arguments:
19291
19292 skip_block_zeroing: Skip the zeroing of newly-provisioned blocks.
19293
19294 ignore_discard: Disable discard support.
19295
19296 no_discard_passdown: Don't pass discards down to the underlying
19297 data device, but just remove the mapping.
19298
19299 read_only: Don't allow any changes to be made to the pool
19300 metadata.
19301
19302 error_if_no_space: Error IOs, instead of queueing, if no space.
19303
19304 Data block size must be between 64KB (128 sectors) and 1GB
19305 (2097152 sectors) inclusive.
19306
19307
19308ii) Status
19309
19310 <transaction id> <used metadata blocks>/<total metadata blocks>
19311 <used data blocks>/<total data blocks> <held metadata root>
19312 [no_]discard_passdown ro|rw
19313
19314 transaction id:
19315 A 64-bit number used by userspace to help synchronise with metadata
19316 from volume managers.
19317
19318 used data blocks / total data blocks
19319 If the number of free blocks drops below the pool's low water mark a
19320 dm event will be sent to userspace. This event is edge-triggered and
19321 it will occur only once after each resume so volume manager writers
19322 should register for the event and then check the target's status.
19323
19324 held metadata root:
19325 The location, in blocks, of the metadata root that has been
19326 'held' for userspace read access. '-' indicates there is no
19327 held root.
19328
19329 discard_passdown|no_discard_passdown
19330 Whether or not discards are actually being passed down to the
19331 underlying device. When this is enabled when loading the table,
19332 it can get disabled if the underlying device doesn't support it.
19333
19334 ro|rw|out_of_data_space
19335 If the pool encounters certain types of device failures it will
19336 drop into a read-only metadata mode in which no changes to
19337 the pool metadata (like allocating new blocks) are permitted.
19338
19339 In serious cases where even a read-only mode is deemed unsafe
19340 no further I/O will be permitted and the status will just
19341 contain the string 'Fail'. The userspace recovery tools
19342 should then be used.
19343
19344 error_if_no_space|queue_if_no_space
19345 If the pool runs out of data or metadata space, the pool will
19346 either queue or error the IO destined to the data device. The
19347 default is to queue the IO until more space is added or the
19348 'no_space_timeout' expires. The 'no_space_timeout' dm-thin-pool
19349 module parameter can be used to change this timeout -- it
19350 defaults to 60 seconds but may be disabled using a value of 0.
19351
19352 needs_check
19353 A metadata operation has failed, resulting in the needs_check
19354 flag being set in the metadata's superblock. The metadata
19355 device must be deactivated and checked/repaired before the
19356 thin-pool can be made fully operational again. '-' indicates
19357 needs_check is not set.
19358
19359iii) Messages
19360
19361 create_thin <dev id>
19362
19363 Create a new thinly-provisioned device.
19364 <dev id> is an arbitrary unique 24-bit identifier chosen by
19365 the caller.
19366
19367 create_snap <dev id> <origin id>
19368
19369 Create a new snapshot of another thinly-provisioned device.
19370 <dev id> is an arbitrary unique 24-bit identifier chosen by
19371 the caller.
19372 <origin id> is the identifier of the thinly-provisioned device
19373 of which the new device will be a snapshot.
19374
19375 delete <dev id>
19376
19377 Deletes a thin device. Irreversible.
19378
19379 set_transaction_id <current id> <new id>
19380
19381 Userland volume managers, such as LVM, need a way to
19382 synchronise their external metadata with the internal metadata of the
19383 pool target. The thin-pool target offers to store an
19384 arbitrary 64-bit transaction id and return it on the target's
19385 status line. To avoid races you must provide what you think
19386 the current transaction id is when you change it with this
19387 compare-and-swap message.
19388
19389 reserve_metadata_snap
19390
19391 Reserve a copy of the data mapping btree for use by userland.
19392 This allows userland to inspect the mappings as they were when
19393 this message was executed. Use the pool's status command to
19394 get the root block associated with the metadata snapshot.
19395
19396 release_metadata_snap
19397
19398 Release a previously reserved copy of the data mapping btree.
19399
19400'thin' target
19401-------------
19402
19403i) Constructor
19404
19405 thin <pool dev> <dev id> [<external origin dev>]
19406
19407 pool dev:
19408 the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
19409
19410 dev id:
19411 the internal device identifier of the device to be
19412 activated.
19413
19414 external origin dev:
19415 an optional block device outside the pool to be treated as a
19416 read-only snapshot origin: reads to unprovisioned areas of the
19417 thin target will be mapped to this device.
19418
19419The pool doesn't store any size against the thin devices. If you
19420load a thin target that is smaller than you've been using previously,
19421then you'll have no access to blocks mapped beyond the end. If you
19422load a target that is bigger than before, then extra blocks will be
19423provisioned as and when needed.
19424
19425ii) Status
19426
19427 <nr mapped sectors> <highest mapped sector>
19428
19429 If the pool has encountered device errors and failed, the status
19430 will just contain the string 'Fail'. The userspace recovery
19431 tools should then be used.
19432\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/cache.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000030721\013062740170\0020703\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Introduction
19433============
19434
19435dm-cache is a device mapper target written by Joe Thornber, Heinz
19436Mauelshagen, and Mike Snitzer.
19437
19438It aims to improve performance of a block device (eg, a spindle) by
19439dynamically migrating some of its data to a faster, smaller device
19440(eg, an SSD).
19441
19442This device-mapper solution allows us to insert this caching at
19443different levels of the dm stack, for instance above the data device for
19444a thin-provisioning pool. Caching solutions that are integrated more
19445closely with the virtual memory system should give better performance.
19446
19447The target reuses the metadata library used in the thin-provisioning
19448library.
19449
19450The decision as to what data to migrate and when is left to a plug-in
19451policy module. Several of these have been written as we experiment,
19452and we hope other people will contribute others for specific io
19453scenarios (eg. a vm image server).
19454
19455Glossary
19456========
19457
19458 Migration - Movement of the primary copy of a logical block from one
19459 device to the other.
19460 Promotion - Migration from slow device to fast device.
19461 Demotion - Migration from fast device to slow device.
19462
19463The origin device always contains a copy of the logical block, which
19464may be out of date or kept in sync with the copy on the cache device
19465(depending on policy).
19466
19467Design
19468======
19469
19470Sub-devices
19471-----------
19472
19473The target is constructed by passing three devices to it (along with
19474other parameters detailed later):
19475
194761. An origin device - the big, slow one.
19477
194782. A cache device - the small, fast one.
19479
194803. A small metadata device - records which blocks are in the cache,
19481 which are dirty, and extra hints for use by the policy object.
19482 This information could be put on the cache device, but having it
19483 separate allows the volume manager to configure it differently,
19484 e.g. as a mirror for extra robustness. This metadata device may only
19485 be used by a single cache device.
19486
19487Fixed block size
19488----------------
19489
19490The origin is divided up into blocks of a fixed size. This block size
19491is configurable when you first create the cache. Typically we've been
19492using block sizes of 256KB - 1024KB. The block size must be between 64
19493(32KB) and 2097152 (1GB) and a multiple of 64 (32KB).
19494
19495Having a fixed block size simplifies the target a lot. But it is
19496something of a compromise. For instance, a small part of a block may be
19497getting hit a lot, yet the whole block will be promoted to the cache.
19498So large block sizes are bad because they waste cache space. And small
19499block sizes are bad because they increase the amount of metadata (both
19500in core and on disk).
19501
19502Cache operating modes
19503---------------------
19504
19505The cache has three operating modes: writeback, writethrough and
19506passthrough.
19507
19508If writeback, the default, is selected then a write to a block that is
19509cached will go only to the cache and the block will be marked dirty in
19510the metadata.
19511
19512If writethrough is selected then a write to a cached block will not
19513complete until it has hit both the origin and cache devices. Clean
19514blocks should remain clean.
19515
19516If passthrough is selected, useful when the cache contents are not known
19517to be coherent with the origin device, then all reads are served from
19518the origin device (all reads miss the cache) and all writes are
19519forwarded to the origin device; additionally, write hits cause cache
19520block invalidates. To enable passthrough mode the cache must be clean.
19521Passthrough mode allows a cache device to be activated without having to
19522worry about coherency. Coherency that exists is maintained, although
19523the cache will gradually cool as writes take place. If the coherency of
19524the cache can later be verified, or established through use of the
19525"invalidate_cblocks" message, the cache device can be transitioned to
19526writethrough or writeback mode while still warm. Otherwise, the cache
19527contents can be discarded prior to transitioning to the desired
19528operating mode.
19529
19530A simple cleaner policy is provided, which will clean (write back) all
19531dirty blocks in a cache. Useful for decommissioning a cache or when
19532shrinking a cache. Shrinking the cache's fast device requires all cache
19533blocks, in the area of the cache being removed, to be clean. If the
19534area being removed from the cache still contains dirty blocks the resize
19535will fail. Care must be taken to never reduce the volume used for the
19536cache's fast device until the cache is clean. This is of particular
19537importance if writeback mode is used. Writethrough and passthrough
19538modes already maintain a clean cache. Future support to partially clean
19539the cache, above a specified threshold, will allow for keeping the cache
19540warm and in writeback mode during resize.
19541
19542Migration throttling
19543--------------------
19544
19545Migrating data between the origin and cache device uses bandwidth.
19546The user can set a throttle to prevent more than a certain amount of
19547migration occurring at any one time. Currently we're not taking any
19548account of normal io traffic going to the devices. More work needs
19549doing here to avoid migrating during those peak io moments.
19550
19551For the time being, a message "migration_threshold <#sectors>"
19552can be used to set the maximum number of sectors being migrated,
19553the default being 204800 sectors (or 100MB).
19554
19555Updating on-disk metadata
19556-------------------------
19557
19558On-disk metadata is committed every time a FLUSH or FUA bio is written.
19559If no such requests are made then commits will occur every second. This
19560means the cache behaves like a physical disk that has a volatile write
19561cache. If power is lost you may lose some recent writes. The metadata
19562should always be consistent in spite of any crash.
19563
19564The 'dirty' state for a cache block changes far too frequently for us
19565to keep updating it on the fly. So we treat it as a hint. In normal
19566operation it will be written when the dm device is suspended. If the
19567system crashes all cache blocks will be assumed dirty when restarted.
19568
19569Per-block policy hints
19570----------------------
19571
19572Policy plug-ins can store a chunk of data per cache block. It's up to
19573the policy how big this chunk is, but it should be kept small. Like the
19574dirty flags this data is lost if there's a crash so a safe fallback
19575value should always be possible.
19576
19577For instance, the 'mq' policy, which is currently the default policy,
19578uses this facility to store the hit count of the cache blocks. If
19579there's a crash this information will be lost, which means the cache
19580may be less efficient until those hit counts are regenerated.
19581
19582Policy hints affect performance, not correctness.
19583
19584Policy messaging
19585----------------
19586
19587Policies will have different tunables, specific to each one, so we
19588need a generic way of getting and setting these. Device-mapper
19589messages are used. Refer to cache-policies.txt.
19590
19591Discard bitset resolution
19592-------------------------
19593
19594We can avoid copying data during migration if we know the block has
19595been discarded. A prime example of this is when mkfs discards the
19596whole block device. We store a bitset tracking the discard state of
19597blocks. However, we allow this bitset to have a different block size
19598from the cache blocks. This is because we need to track the discard
19599state for all of the origin device (compare with the dirty bitset
19600which is just for the smaller cache device).
19601
19602Target interface
19603================
19604
19605Constructor
19606-----------
19607
19608 cache <metadata dev> <cache dev> <origin dev> <block size>
19609 <#feature args> [<feature arg>]*
19610 <policy> <#policy args> [policy args]*
19611
19612 metadata dev : fast device holding the persistent metadata
19613 cache dev : fast device holding cached data blocks
19614 origin dev : slow device holding original data blocks
19615 block size : cache unit size in sectors
19616
19617 #feature args : number of feature arguments passed
19618 feature args : writethrough or passthrough (The default is writeback.)
19619
19620 policy : the replacement policy to use
19621 #policy args : an even number of arguments corresponding to
19622 key/value pairs passed to the policy
19623 policy args : key/value pairs passed to the policy
19624 E.g. 'sequential_threshold 1024'
19625 See cache-policies.txt for details.
19626
19627Optional feature arguments are:
19628 writethrough : write through caching that prohibits cache block
19629 content from being different from origin block content.
19630 Without this argument, the default behaviour is to write
19631 back cache block contents later for performance reasons,
19632 so they may differ from the corresponding origin blocks.
19633
19634 passthrough : a degraded mode useful for various cache coherency
19635 situations (e.g., rolling back snapshots of
19636 underlying storage). Reads and writes always go to
19637 the origin. If a write goes to a cached origin
19638 block, then the cache block is invalidated.
19639 To enable passthrough mode the cache must be clean.
19640
19641A policy called 'default' is always registered. This is an alias for
19642the policy we currently think is giving best all round performance.
19643
19644As the default policy could vary between kernels, if you are relying on
19645the characteristics of a specific policy, always request it by name.
19646
19647Status
19648------
19649
19650<metadata block size> <#used metadata blocks>/<#total metadata blocks>
19651<cache block size> <#used cache blocks>/<#total cache blocks>
19652<#read hits> <#read misses> <#write hits> <#write misses>
19653<#demotions> <#promotions> <#dirty> <#features> <features>*
19654<#core args> <core args>* <policy name> <#policy args> <policy args>*
19655<cache metadata mode>
19656
19657metadata block size : Fixed block size for each metadata block in
19658 sectors
19659#used metadata blocks : Number of metadata blocks used
19660#total metadata blocks : Total number of metadata blocks
19661cache block size : Configurable block size for the cache device
19662 in sectors
19663#used cache blocks : Number of blocks resident in the cache
19664#total cache blocks : Total number of cache blocks
19665#read hits : Number of times a READ bio has been mapped
19666 to the cache
19667#read misses : Number of times a READ bio has been mapped
19668 to the origin
19669#write hits : Number of times a WRITE bio has been mapped
19670 to the cache
19671#write misses : Number of times a WRITE bio has been
19672 mapped to the origin
19673#demotions : Number of times a block has been removed
19674 from the cache
19675#promotions : Number of times a block has been moved to
19676 the cache
19677#dirty : Number of blocks in the cache that differ
19678 from the origin
19679#feature args : Number of feature args to follow
19680feature args : 'writethrough' (optional)
19681#core args : Number of core arguments (must be even)
19682core args : Key/value pairs for tuning the core
19683 e.g. migration_threshold
19684policy name : Name of the policy
19685#policy args : Number of policy arguments to follow (must be even)
19686policy args : Key/value pairs e.g. sequential_threshold
19687cache metadata mode : ro if read-only, rw if read-write
19688 In serious cases where even a read-only mode is deemed unsafe
19689 no further I/O will be permitted and the status will just
19690 contain the string 'Fail'. The userspace recovery tools
19691 should then be used.
19692needs_check : 'needs_check' if set, '-' if not set
19693 A metadata operation has failed, resulting in the needs_check
19694 flag being set in the metadata's superblock. The metadata
19695 device must be deactivated and checked/repaired before the
19696 cache can be made fully operational again. '-' indicates
19697 needs_check is not set.
19698
19699Messages
19700--------
19701
19702Policies will have different tunables, specific to each one, so we
19703need a generic way of getting and setting these. Device-mapper
19704messages are used. (A sysfs interface would also be possible.)
19705
19706The message format is:
19707
19708 <key> <value>
19709
19710E.g.
19711 dmsetup message my_cache 0 sequential_threshold 1024
19712
19713
19714Invalidation is removing an entry from the cache without writing it
19715back. Cache blocks can be invalidated via the invalidate_cblocks
19716message, which takes an arbitrary number of cblock ranges. Each cblock
19717range's end value is "one past the end", meaning 5-10 expresses a range
19718of values from 5 to 9. Each cblock must be expressed as a decimal
19719value, in the future a variant message that takes cblock ranges
19720expressed in hexidecimal may be needed to better support efficient
19721invalidation of larger caches. The cache must be in passthrough mode
19722when invalidate_cblocks is used.
19723
19724 invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
19725
19726E.g.
19727 dmsetup message my_cache 0 invalidate_cblocks 2345 3456-4567 5678-6789
19728
19729Examples
19730========
19731
19732The test suite can be found here:
19733
19734https://github.com/jthornber/device-mapper-test-suite
19735
19736dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
19737 /dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
19738dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
19739 /dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
19740 mq 4 sequential_threshold 1024 random_threshold 8'
19741\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/snapshot.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015254\013062740170\0021503\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Device-mapper snapshot support
19742==============================
19743
19744Device-mapper allows you, without massive data copying:
19745
19746*) To create snapshots of any block device i.e. mountable, saved states of
19747the block device which are also writable without interfering with the
19748original content;
19749*) To create device "forks", i.e. multiple different versions of the
19750same data stream.
19751*) To merge a snapshot of a block device back into the snapshot's origin
19752device.
19753
19754In the first two cases, dm copies only the chunks of data that get
19755changed and uses a separate copy-on-write (COW) block device for
19756storage.
19757
19758For snapshot merge the contents of the COW storage are merged back into
19759the origin device.
19760
19761
19762There are three dm targets available:
19763snapshot, snapshot-origin, and snapshot-merge.
19764
19765*) snapshot-origin <origin>
19766
19767which will normally have one or more snapshots based on it.
19768Reads will be mapped directly to the backing device. For each write, the
19769original data will be saved in the <COW device> of each snapshot to keep
19770its visible content unchanged, at least until the <COW device> fills up.
19771
19772
19773*) snapshot <origin> <COW device> <persistent?> <chunksize>
19774
19775A snapshot of the <origin> block device is created. Changed chunks of
19776<chunksize> sectors will be stored on the <COW device>. Writes will
19777only go to the <COW device>. Reads will come from the <COW device> or
19778from <origin> for unchanged data. <COW device> will often be
19779smaller than the origin and if it fills up the snapshot will become
19780useless and be disabled, returning errors. So it is important to monitor
19781the amount of free space and expand the <COW device> before it fills up.
19782
19783<persistent?> is P (Persistent) or N (Not persistent - will not survive
19784after reboot). O (Overflow) can be added as a persistent store option
19785to allow userspace to advertise its support for seeing "Overflow" in the
19786snapshot status. So supported store types are "P", "PO" and "N".
19787
19788The difference between persistent and transient is with transient
19789snapshots less metadata must be saved on disk - they can be kept in
19790memory by the kernel.
19791
19792
19793* snapshot-merge <origin> <COW device> <persistent> <chunksize>
19794
19795takes the same table arguments as the snapshot target except it only
19796works with persistent snapshots. This target assumes the role of the
19797"snapshot-origin" target and must not be loaded if the "snapshot-origin"
19798is still present for <origin>.
19799
19800Creates a merging snapshot that takes control of the changed chunks
19801stored in the <COW device> of an existing snapshot, through a handover
19802procedure, and merges these chunks back into the <origin>. Once merging
19803has started (in the background) the <origin> may be opened and the merge
19804will continue while I/O is flowing to it. Changes to the <origin> are
19805deferred until the merging snapshot's corresponding chunk(s) have been
19806merged. Once merging has started the snapshot device, associated with
19807the "snapshot" target, will return -EIO when accessed.
19808
19809
19810How snapshot is used by LVM2
19811============================
19812When you create the first LVM2 snapshot of a volume, four dm devices are used:
19813
198141) a device containing the original mapping table of the source volume;
198152) a device used as the <COW device>;
198163) a "snapshot" device, combining #1 and #2, which is the visible snapshot
19817 volume;
198184) the "original" volume (which uses the device number used by the original
19819 source volume), whose table is replaced by a "snapshot-origin" mapping
19820 from device #1.
19821
19822A fixed naming scheme is used, so with the following commands:
19823
19824lvcreate -L 1G -n base volumeGroup
19825lvcreate -L 100M --snapshot -n snap volumeGroup/base
19826
19827we'll have this situation (with volumes in above order):
19828
19829# dmsetup table|grep volumeGroup
19830
19831volumeGroup-base-real: 0 2097152 linear 8:19 384
19832volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
19833volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
19834volumeGroup-base: 0 2097152 snapshot-origin 254:11
19835
19836# ls -lL /dev/mapper/volumeGroup-*
19837brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
19838brw------- 1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
19839brw------- 1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
19840brw------- 1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
19841
19842
19843How snapshot-merge is used by LVM2
19844==================================
19845A merging snapshot assumes the role of the "snapshot-origin" while
19846merging. As such the "snapshot-origin" is replaced with
19847"snapshot-merge". The "-real" device is not changed and the "-cow"
19848device is renamed to <origin name>-cow to aid LVM2's cleanup of the
19849merging snapshot after it completes. The "snapshot" that hands over its
19850COW device to the "snapshot-merge" is deactivated (unless using lvchange
19851--refresh); but if it is left active it will simply return I/O errors.
19852
19853A snapshot will merge into its origin with the following command:
19854
19855lvconvert --merge volumeGroup/snap
19856
19857we'll now have this situation:
19858
19859# dmsetup table|grep volumeGroup
19860
19861volumeGroup-base-real: 0 2097152 linear 8:19 384
19862volumeGroup-base-cow: 0 204800 linear 8:19 2097536
19863volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
19864
19865# ls -lL /dev/mapper/volumeGroup-*
19866brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
19867brw------- 1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
19868brw------- 1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
19869
19870
19871How to determine when a merging is complete
19872===========================================
19873The snapshot-merge and snapshot status lines end with:
19874 <sectors_allocated>/<total_sectors> <metadata_sectors>
19875
19876Both <sectors_allocated> and <total_sectors> include both data and metadata.
19877During merging, the number of sectors allocated gets smaller and
19878smaller. Merging has finished when the number of sectors holding data
19879is zero, in other words <sectors_allocated> == <metadata_sectors>.
19880
19881Here is a practical example (using a hybrid of lvm and dmsetup commands):
19882
19883# lvs
19884 LV VG Attr LSize Origin Snap% Move Log Copy% Convert
19885 base volumeGroup owi-a- 4.00g
19886 snap volumeGroup swi-a- 1.00g base 18.97
19887
19888# dmsetup status volumeGroup-snap
198890 8388608 snapshot 397896/2097152 1560
19890 ^^^^ metadata sectors
19891
19892# lvconvert --merge -b volumeGroup/snap
19893 Merging of volume snap started.
19894
19895# lvs volumeGroup/snap
19896 LV VG Attr LSize Origin Snap% Move Log Copy% Convert
19897 base volumeGroup Owi-a- 4.00g 17.23
19898
19899# dmsetup status volumeGroup-base
199000 8388608 snapshot-merge 281688/2097152 1104
19901
19902# dmsetup status volumeGroup-base
199030 8388608 snapshot-merge 180480/2097152 712
19904
19905# dmsetup status volumeGroup-base
199060 8388608 snapshot-merge 16/2097152 16
19907
19908Merging has finished.
19909
19910# lvs
19911 LV VG Attr LSize Origin Snap% Move Log Copy% Convert
19912 base volumeGroup owi-a- 4.00g
19913\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/striped.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003443\013062740170\0021313\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-stripe
19914=========
19915
19916Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0)
19917device across one or more underlying devices. Data is written in "chunks",
19918with consecutive chunks rotating among the underlying devices. This can
19919potentially provide improved I/O throughput by utilizing several physical
19920devices in parallel.
19921
19922Parameters: <num devs> <chunk size> [<dev path> <offset>]+
19923 <num devs>: Number of underlying devices.
19924 <chunk size>: Size of each chunk of data. Must be at least as
19925 large as the system's PAGE_SIZE.
19926 <dev path>: Full pathname to the underlying block-device, or a
19927 "major:minor" device-number.
19928 <offset>: Starting sector within the device.
19929
19930One or more underlying devices can be specified. The striped device size must
19931be a multiple of the chunk size multiplied by the number of underlying devices.
19932
19933
19934Example scripts
19935===============
19936
19937[[
19938#!/usr/bin/perl -w
19939# Create a striped device across any number of underlying devices. The device
19940# will be called "stripe_dev" and have a chunk-size of 128k.
19941
19942my $chunk_size = 128 * 2;
19943my $dev_name = "stripe_dev";
19944my $num_devs = @ARGV;
19945my @devs = @ARGV;
19946my ($min_dev_size, $stripe_dev_size, $i);
19947
19948if (!$num_devs) {
19949 die("Specify at least one device\n");
19950}
19951
19952$min_dev_size = `blockdev --getsize $devs[0]`;
19953for ($i = 1; $i < $num_devs; $i++) {
19954 my $this_size = `blockdev --getsize $devs[$i]`;
19955 $min_dev_size = ($min_dev_size < $this_size) ?
19956 $min_dev_size : $this_size;
19957}
19958
19959$stripe_dev_size = $min_dev_size * $num_devs;
19960$stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs);
19961
19962$table = "0 $stripe_dev_size striped $num_devs $chunk_size";
19963for ($i = 0; $i < $num_devs; $i++) {
19964 $table .= " $devs[$i] 0";
19965}
19966
19967`echo $table | dmsetup create $dev_name`;
19968]]
19969
19970\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/delay.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001330\013062740170\0020730\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-delay
19971========
19972
19973Device-Mapper's "delay" target delays reads and/or writes
19974and maps them to different devices.
19975
19976Parameters:
19977 <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
19978
19979With separate write parameters, the first set is only used for reads.
19980Offsets are specified in sectors.
19981Delays are specified in milliseconds.
19982
19983Example scripts
19984===============
19985[[
19986#!/bin/sh
19987# Create device delaying rw operation for 500ms
19988echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
19989]]
19990
19991[[
19992#!/bin/sh
19993# Create device delaying only write operation for 500ms and
19994# splitting reads and writes to different devices $1 $2
19995echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
19996]]
19997\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/uevent.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005132\013062740170\0021144\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0The device-mapper uevent code adds the capability to device-mapper to create
19998and send kobject uevents (uevents). Previously device-mapper events were only
19999available through the ioctl interface. The advantage of the uevents interface
20000is the event contains environment attributes providing increased context for
20001the event avoiding the need to query the state of the device-mapper device after
20002the event is received.
20003
20004There are two functions currently for device-mapper events. The first function
20005listed creates the event and the second function sends the event(s).
20006
20007void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
20008 const char *path, unsigned nr_valid_paths)
20009
20010void dm_send_uevents(struct list_head *events, struct kobject *kobj)
20011
20012
20013The variables added to the uevent environment are:
20014
20015Variable Name: DM_TARGET
20016Uevent Action(s): KOBJ_CHANGE
20017Type: string
20018Description:
20019Value: Name of device-mapper target that generated the event.
20020
20021Variable Name: DM_ACTION
20022Uevent Action(s): KOBJ_CHANGE
20023Type: string
20024Description:
20025Value: Device-mapper specific action that caused the uevent action.
20026 PATH_FAILED - A path has failed.
20027 PATH_REINSTATED - A path has been reinstated.
20028
20029Variable Name: DM_SEQNUM
20030Uevent Action(s): KOBJ_CHANGE
20031Type: unsigned integer
20032Description: A sequence number for this specific device-mapper device.
20033Value: Valid unsigned integer range.
20034
20035Variable Name: DM_PATH
20036Uevent Action(s): KOBJ_CHANGE
20037Type: string
20038Description: Major and minor number of the path device pertaining to this
20039event.
20040Value: Path name in the form of "Major:Minor"
20041
20042Variable Name: DM_NR_VALID_PATHS
20043Uevent Action(s): KOBJ_CHANGE
20044Type: unsigned integer
20045Description:
20046Value: Valid unsigned integer range.
20047
20048Variable Name: DM_NAME
20049Uevent Action(s): KOBJ_CHANGE
20050Type: string
20051Description: Name of the device-mapper device.
20052Value: Name
20053
20054Variable Name: DM_UUID
20055Uevent Action(s): KOBJ_CHANGE
20056Type: string
20057Description: UUID of the device-mapper device.
20058Value: UUID. (Empty string if there isn't one.)
20059
20060An example of the uevents generated as captured by udevmonitor is shown
20061below.
20062
200631.) Path failure.
20064UEVENT[1192521009.711215] change@/block/dm-3
20065ACTION=change
20066DEVPATH=/block/dm-3
20067SUBSYSTEM=block
20068DM_TARGET=multipath
20069DM_ACTION=PATH_FAILED
20070DM_SEQNUM=1
20071DM_PATH=8:32
20072DM_NR_VALID_PATHS=0
20073DM_NAME=mpath2
20074DM_UUID=mpath-35333333000002328
20075MINOR=3
20076MAJOR=253
20077SEQNUM=1130
20078
200792.) Path reinstate.
20080UEVENT[1192521132.989927] change@/block/dm-3
20081ACTION=change
20082DEVPATH=/block/dm-3
20083SUBSYSTEM=block
20084DM_TARGET=multipath
20085DM_ACTION=PATH_REINSTATED
20086DM_SEQNUM=2
20087DM_PATH=8:32
20088DM_NR_VALID_PATHS=1
20089DM_NAME=mpath2
20090DM_UUID=mpath-35333333000002328
20091MINOR=3
20092MAJOR=253
20093SEQNUM=1131
20094\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/era.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006107\013062740170\0020410\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Introduction
20095============
20096
20097dm-era is a target that behaves similar to the linear target. In
20098addition it keeps track of which blocks were written within a user
20099defined period of time called an 'era'. Each era target instance
20100maintains the current era as a monotonically increasing 32-bit
20101counter.
20102
20103Use cases include tracking changed blocks for backup software, and
20104partially invalidating the contents of a cache to restore cache
20105coherency after rolling back a vendor snapshot.
20106
20107Constructor
20108===========
20109
20110 era <metadata dev> <origin dev> <block size>
20111
20112 metadata dev : fast device holding the persistent metadata
20113 origin dev : device holding data blocks that may change
20114 block size : block size of origin data device, granularity that is
20115 tracked by the target
20116
20117Messages
20118========
20119
20120None of the dm messages take any arguments.
20121
20122checkpoint
20123----------
20124
20125Possibly move to a new era. You shouldn't assume the era has
20126incremented. After sending this message, you should check the
20127current era via the status line.
20128
20129take_metadata_snap
20130------------------
20131
20132Create a clone of the metadata, to allow a userland process to read it.
20133
20134drop_metadata_snap
20135------------------
20136
20137Drop the metadata snapshot.
20138
20139Status
20140======
20141
20142<metadata block size> <#used metadata blocks>/<#total metadata blocks>
20143<current era> <held metadata root | '-'>
20144
20145metadata block size : Fixed block size for each metadata block in
20146 sectors
20147#used metadata blocks : Number of metadata blocks used
20148#total metadata blocks : Total number of metadata blocks
20149current era : The current era
20150held metadata root : The location, in blocks, of the metadata root
20151 that has been 'held' for userspace read
20152 access. '-' indicates there is no held root
20153
20154Detailed use case
20155=================
20156
20157The scenario of invalidating a cache when rolling back a vendor
20158snapshot was the primary use case when developing this target:
20159
20160Taking a vendor snapshot
20161------------------------
20162
20163- Send a checkpoint message to the era target
20164- Make a note of the current era in its status line
20165- Take vendor snapshot (the era and snapshot should be forever
20166 associated now).
20167
20168Rolling back to an vendor snapshot
20169----------------------------------
20170
20171- Cache enters passthrough mode (see: dm-cache's docs in cache.txt)
20172- Rollback vendor storage
20173- Take metadata snapshot
20174- Ascertain which blocks have been written since the snapshot was taken
20175 by checking each block's era
20176- Invalidate those blocks in the caching software
20177- Cache returns to writeback/writethrough mode
20178
20179Memory usage
20180============
20181
20182The target uses a bitset to record writes in the current era. It also
20183has a spare bitset ready for switching over to a new era. Other than
20184that it uses a few 4k blocks for updating metadata.
20185
20186 (4 * nr_blocks) bytes + buffers
20187
20188Resilience
20189==========
20190
20191Metadata is updated on disk before a write to a previously unwritten
20192block is performed. As such dm-era should not be effected by a hard
20193crash such as power failure.
20194
20195Userland tools
20196==============
20197
20198Userland tools are found in the increasingly poorly named
20199thin-provisioning-tools project:
20200
20201 https://github.com/jthornber/thin-provisioning-tools
20202\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/zero.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003226\013062740170\0020617\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-zero
20203=======
20204
20205Device-Mapper's "zero" target provides a block-device that always returns
20206zero'd data on reads and silently drops writes. This is similar behavior to
20207/dev/zero, but as a block-device instead of a character-device.
20208
20209Dm-zero has no target-specific parameters.
20210
20211One very interesting use of dm-zero is for creating "sparse" devices in
20212conjunction with dm-snapshot. A sparse device reports a device-size larger
20213than the amount of actual storage space available for that device. A user can
20214write data anywhere within the sparse device and read it back like a normal
20215device. Reads to previously unwritten areas will return a zero'd buffer. When
20216enough data has been written to fill up the actual storage space, the sparse
20217device is deactivated. This can be very useful for testing device and
20218filesystem limitations.
20219
20220To create a sparse device, start by creating a dm-zero device that's the
20221desired size of the sparse device. For this example, we'll assume a 10TB
20222sparse device.
20223
20224TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2` # 10 TB in sectors
20225echo "0 $TEN_TERABYTES zero" | dmsetup create zero1
20226
20227Then create a snapshot of the zero device, using any available block-device as
20228the COW device. The size of the COW device will determine the amount of real
20229space available to the sparse device. For this example, we'll assume /dev/sdb1
20230is an available 10GB partition.
20231
20232echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \
20233 dmsetup create sparse1
20234
20235This will create a 10TB sparse device called /dev/mapper/sparse1 that has
2023610GB of actual storage space available. If more than 10GB of data is written
20237to this device, it will start returning I/O errors.
20238
20239\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/raid.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000026174\013062740170\0020566\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-raid
20240=======
20241
20242The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
20243It allows the MD RAID drivers to be accessed using a device-mapper
20244interface.
20245
20246
20247Mapping Table Interface
20248-----------------------
20249The target is named "raid" and it accepts the following parameters:
20250
20251 <raid_type> <#raid_params> <raid_params> \
20252 <#raid_devs> <metadata_dev0> <dev0> [.. <metadata_devN> <devN>]
20253
20254<raid_type>:
20255 raid1 RAID1 mirroring
20256 raid4 RAID4 dedicated parity disk
20257 raid5_la RAID5 left asymmetric
20258 - rotating parity 0 with data continuation
20259 raid5_ra RAID5 right asymmetric
20260 - rotating parity N with data continuation
20261 raid5_ls RAID5 left symmetric
20262 - rotating parity 0 with data restart
20263 raid5_rs RAID5 right symmetric
20264 - rotating parity N with data restart
20265 raid6_zr RAID6 zero restart
20266 - rotating parity zero (left-to-right) with data restart
20267 raid6_nr RAID6 N restart
20268 - rotating parity N (right-to-left) with data restart
20269 raid6_nc RAID6 N continue
20270 - rotating parity N (right-to-left) with data continuation
20271 raid10 Various RAID10 inspired algorithms chosen by additional params
20272 - RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
20273 - RAID1E: Integrated Adjacent Stripe Mirroring
20274 - RAID1E: Integrated Offset Stripe Mirroring
20275 - and other similar RAID10 variants
20276
20277 Reference: Chapter 4 of
20278 http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
20279
20280<#raid_params>: The number of parameters that follow.
20281
20282<raid_params> consists of
20283 Mandatory parameters:
20284 <chunk_size>: Chunk size in sectors. This parameter is often known as
20285 "stripe size". It is the only mandatory parameter and
20286 is placed first.
20287
20288 followed by optional parameters (in any order):
20289 [sync|nosync] Force or prevent RAID initialization.
20290
20291 [rebuild <idx>] Rebuild drive number 'idx' (first drive is 0).
20292
20293 [daemon_sleep <ms>]
20294 Interval between runs of the bitmap daemon that
20295 clear bits. A longer interval means less bitmap I/O but
20296 resyncing after a failure is likely to take longer.
20297
20298 [min_recovery_rate <kB/sec/disk>] Throttle RAID initialization
20299 [max_recovery_rate <kB/sec/disk>] Throttle RAID initialization
20300 [write_mostly <idx>] Mark drive index 'idx' write-mostly.
20301 [max_write_behind <sectors>] See '--write-behind=' (man mdadm)
20302 [stripe_cache <sectors>] Stripe cache size (RAID 4/5/6 only)
20303 [region_size <sectors>]
20304 The region_size multiplied by the number of regions is the
20305 logical size of the array. The bitmap records the device
20306 synchronisation state for each region.
20307
20308 [raid10_copies <# copies>]
20309 [raid10_format <near|far|offset>]
20310 These two options are used to alter the default layout of
20311 a RAID10 configuration. The number of copies is can be
20312 specified, but the default is 2. There are also three
20313 variations to how the copies are laid down - the default
20314 is "near". Near copies are what most people think of with
20315 respect to mirroring. If these options are left unspecified,
20316 or 'raid10_copies 2' and/or 'raid10_format near' are given,
20317 then the layouts for 2, 3 and 4 devices are:
20318 2 drives 3 drives 4 drives
20319 -------- ---------- --------------
20320 A1 A1 A1 A1 A2 A1 A1 A2 A2
20321 A2 A2 A2 A3 A3 A3 A3 A4 A4
20322 A3 A3 A4 A4 A5 A5 A5 A6 A6
20323 A4 A4 A5 A6 A6 A7 A7 A8 A8
20324 .. .. .. .. .. .. .. .. ..
20325 The 2-device layout is equivalent 2-way RAID1. The 4-device
20326 layout is what a traditional RAID10 would look like. The
20327 3-device layout is what might be called a 'RAID1E - Integrated
20328 Adjacent Stripe Mirroring'.
20329
20330 If 'raid10_copies 2' and 'raid10_format far', then the layouts
20331 for 2, 3 and 4 devices are:
20332 2 drives 3 drives 4 drives
20333 -------- -------------- --------------------
20334 A1 A2 A1 A2 A3 A1 A2 A3 A4
20335 A3 A4 A4 A5 A6 A5 A6 A7 A8
20336 A5 A6 A7 A8 A9 A9 A10 A11 A12
20337 .. .. .. .. .. .. .. .. ..
20338 A2 A1 A3 A1 A2 A2 A1 A4 A3
20339 A4 A3 A6 A4 A5 A6 A5 A8 A7
20340 A6 A5 A9 A7 A8 A10 A9 A12 A11
20341 .. .. .. .. .. .. .. .. ..
20342
20343 If 'raid10_copies 2' and 'raid10_format offset', then the
20344 layouts for 2, 3 and 4 devices are:
20345 2 drives 3 drives 4 drives
20346 -------- ------------ -----------------
20347 A1 A2 A1 A2 A3 A1 A2 A3 A4
20348 A2 A1 A3 A1 A2 A2 A1 A4 A3
20349 A3 A4 A4 A5 A6 A5 A6 A7 A8
20350 A4 A3 A6 A4 A5 A6 A5 A8 A7
20351 A5 A6 A7 A8 A9 A9 A10 A11 A12
20352 A6 A5 A9 A7 A8 A10 A9 A12 A11
20353 .. .. .. .. .. .. .. .. ..
20354 Here we see layouts closely akin to 'RAID1E - Integrated
20355 Offset Stripe Mirroring'.
20356
20357<#raid_devs>: The number of devices composing the array.
20358 Each device consists of two entries. The first is the device
20359 containing the metadata (if any); the second is the one containing the
20360 data.
20361
20362 If a drive has failed or is missing at creation time, a '-' can be
20363 given for both the metadata and data drives for a given position.
20364
20365
20366Example Tables
20367--------------
20368# RAID4 - 4 data drives, 1 parity (no metadata devices)
20369# No metadata devices specified to hold superblock/bitmap info
20370# Chunk size of 1MiB
20371# (Lines separated for easy reading)
20372
203730 1960893648 raid \
20374 raid4 1 2048 \
20375 5 - 8:17 - 8:33 - 8:49 - 8:65 - 8:81
20376
20377# RAID4 - 4 data drives, 1 parity (with metadata devices)
20378# Chunk size of 1MiB, force RAID initialization,
20379# min recovery rate at 20 kiB/sec/disk
20380
203810 1960893648 raid \
20382 raid4 4 2048 sync min_recovery_rate 20 \
20383 5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
20384
20385
20386Status Output
20387-------------
20388'dmsetup table' displays the table used to construct the mapping.
20389The optional parameters are always printed in the order listed
20390above with "sync" or "nosync" always output ahead of the other
20391arguments, regardless of the order used when originally loading the table.
20392Arguments that can be repeated are ordered by value.
20393
20394
20395'dmsetup status' yields information on the state and health of the array.
20396The output is as follows (normally a single line, but expanded here for
20397clarity):
203981: <s> <l> raid \
203992: <raid_type> <#devices> <health_chars> \
204003: <sync_ratio> <sync_action> <mismatch_cnt>
20401
20402Line 1 is the standard output produced by device-mapper.
20403Line 2 & 3 are produced by the raid target and are best explained by example:
20404 0 1960893648 raid raid4 5 AAAAA 2/490221568 init 0
20405Here we can see the RAID type is raid4, there are 5 devices - all of
20406which are 'A'live, and the array is 2/490221568 complete with its initial
20407recovery. Here is a fuller description of the individual fields:
20408 <raid_type> Same as the <raid_type> used to create the array.
20409 <health_chars> One char for each device, indicating: 'A' = alive and
20410 in-sync, 'a' = alive but not in-sync, 'D' = dead/failed.
20411 <sync_ratio> The ratio indicating how much of the array has undergone
20412 the process described by 'sync_action'. If the
20413 'sync_action' is "check" or "repair", then the process
20414 of "resync" or "recover" can be considered complete.
20415 <sync_action> One of the following possible states:
20416 idle - No synchronization action is being performed.
20417 frozen - The current action has been halted.
20418 resync - Array is undergoing its initial synchronization
20419 or is resynchronizing after an unclean shutdown
20420 (possibly aided by a bitmap).
20421 recover - A device in the array is being rebuilt or
20422 replaced.
20423 check - A user-initiated full check of the array is
20424 being performed. All blocks are read and
20425 checked for consistency. The number of
20426 discrepancies found are recorded in
20427 <mismatch_cnt>. No changes are made to the
20428 array by this action.
20429 repair - The same as "check", but discrepancies are
20430 corrected.
20431 reshape - The array is undergoing a reshape.
20432 <mismatch_cnt> The number of discrepancies found between mirror copies
20433 in RAID1/10 or wrong parity values found in RAID4/5/6.
20434 This value is valid only after a "check" of the array
20435 is performed. A healthy array has a 'mismatch_cnt' of 0.
20436
20437Message Interface
20438-----------------
20439The dm-raid target will accept certain actions through the 'message' interface.
20440('man dmsetup' for more information on the message interface.) These actions
20441include:
20442 "idle" - Halt the current sync action.
20443 "frozen" - Freeze the current sync action.
20444 "resync" - Initiate/continue a resync.
20445 "recover"- Initiate/continue a recover process.
20446 "check" - Initiate a check (i.e. a "scrub") of the array.
20447 "repair" - Initiate a repair of the array.
20448 "reshape"- Currently unsupported (-EINVAL).
20449
20450
20451Discard Support
20452---------------
20453The implementation of discard support among hardware vendors varies.
20454When a block is discarded, some storage devices will return zeroes when
20455the block is read. These devices set the 'discard_zeroes_data'
20456attribute. Other devices will return random data. Confusingly, some
20457devices that advertise 'discard_zeroes_data' will not reliably return
20458zeroes when discarded blocks are read! Since RAID 4/5/6 uses blocks
20459from a number of devices to calculate parity blocks and (for performance
20460reasons) relies on 'discard_zeroes_data' being reliable, it is important
20461that the devices be consistent. Blocks may be discarded in the middle
20462of a RAID 4/5/6 stripe and if subsequent read results are not
20463consistent, the parity blocks may be calculated differently at any time;
20464making the parity blocks useless for redundancy. It is important to
20465understand how your hardware behaves with discards if you are going to
20466enable discards with RAID 4/5/6.
20467
20468Since the behavior of storage devices is unreliable in this respect,
20469even when reporting 'discard_zeroes_data', by default RAID 4/5/6
20470discard support is disabled -- this ensures data integrity at the
20471expense of losing some performance.
20472
20473Storage devices that properly support 'discard_zeroes_data' are
20474increasingly whitelisted in the kernel and can thus be trusted.
20475
20476For trusted devices, the following dm-raid module parameter can be set
20477to safely enable discard support for RAID 4/5/6:
20478 'devices_handle_discards_safely'
20479
20480
20481Version History
20482---------------
204831.0.0 Initial version. Support for RAID 4/5/6
204841.1.0 Added support for RAID 1
204851.2.0 Handle creation of arrays that contain failed devices.
204861.3.0 Added support for RAID 10
204871.3.1 Allow device replacement/rebuild for RAID 10
204881.3.2 Fix/improve redundancy checking for RAID10
204891.4.0 Non-functional change. Removes arg from mapping function.
204901.4.1 RAID10 fix redundancy validation checks (commit 55ebbb5).
204911.4.2 Add RAID10 "far" and "offset" algorithm support.
204921.5.0 Add message interface to allow manipulation of the sync_action.
20493 New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
204941.5.1 Add ability to restore transiently failed devices on resume.
204951.5.2 'mismatch_cnt' is zero unless [last_]sync_action is "check".
204961.6.0 Add discard support (and devices_handle_discard_safely module param).
204971.7.0 Add support for MD RAID0 mappings.
20498\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/cache-policies.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011036\013062740170\0022506\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Guidance for writing policies
20499=============================
20500
20501Try to keep transactionality out of it. The core is careful to
20502avoid asking about anything that is migrating. This is a pain, but
20503makes it easier to write the policies.
20504
20505Mappings are loaded into the policy at construction time.
20506
20507Every bio that is mapped by the target is referred to the policy.
20508The policy can return a simple HIT or MISS or issue a migration.
20509
20510Currently there's no way for the policy to issue background work,
20511e.g. to start writing back dirty blocks that are going to be evicted
20512soon.
20513
20514Because we map bios, rather than requests it's easy for the policy
20515to get fooled by many small bios. For this reason the core target
20516issues periodic ticks to the policy. It's suggested that the policy
20517doesn't update states (eg, hit counts) for a block more than once
20518for each tick. The core ticks by watching bios complete, and so
20519trying to see when the io scheduler has let the ios run.
20520
20521
20522Overview of supplied cache replacement policies
20523===============================================
20524
20525multiqueue (mq)
20526---------------
20527
20528This policy is now an alias for smq (see below).
20529
20530The following tunables are accepted, but have no effect:
20531
20532 'sequential_threshold <#nr_sequential_ios>'
20533 'random_threshold <#nr_random_ios>'
20534 'read_promote_adjustment <value>'
20535 'write_promote_adjustment <value>'
20536 'discard_promote_adjustment <value>'
20537
20538Stochastic multiqueue (smq)
20539---------------------------
20540
20541This policy is the default.
20542
20543The stochastic multi-queue (smq) policy addresses some of the problems
20544with the multiqueue (mq) policy.
20545
20546The smq policy (vs mq) offers the promise of less memory utilization,
20547improved performance and increased adaptability in the face of changing
20548workloads. smq also does not have any cumbersome tuning knobs.
20549
20550Users may switch from "mq" to "smq" simply by appropriately reloading a
20551DM table that is using the cache target. Doing so will cause all of the
20552mq policy's hints to be dropped. Also, performance of the cache may
20553degrade slightly until smq recalculates the origin device's hotspots
20554that should be cached.
20555
20556Memory usage:
20557The mq policy used a lot of memory; 88 bytes per cache block on a 64
20558bit machine.
20559
20560smq uses 28bit indexes to implement it's data structures rather than
20561pointers. It avoids storing an explicit hit count for each block. It
20562has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
20563the entries (each hotspot block covers a larger area than a single
20564cache block).
20565
20566All this means smq uses ~25bytes per cache block. Still a lot of
20567memory, but a substantial improvement nontheless.
20568
20569Level balancing:
20570mq placed entries in different levels of the multiqueue structures
20571based on their hit count (~ln(hit count)). This meant the bottom
20572levels generally had the most entries, and the top ones had very
20573few. Having unbalanced levels like this reduced the efficacy of the
20574multiqueue.
20575
20576smq does not maintain a hit count, instead it swaps hit entries with
20577the least recently used entry from the level above. The overall
20578ordering being a side effect of this stochastic process. With this
20579scheme we can decide how many entries occupy each multiqueue level,
20580resulting in better promotion/demotion decisions.
20581
20582Adaptability:
20583The mq policy maintained a hit count for each cache block. For a
20584different block to get promoted to the cache it's hit count has to
20585exceed the lowest currently in the cache. This meant it could take a
20586long time for the cache to adapt between varying IO patterns.
20587
20588smq doesn't maintain hit counts, so a lot of this problem just goes
20589away. In addition it tracks performance of the hotspot queue, which
20590is used to decide which blocks to promote. If the hotspot queue is
20591performing badly then it starts moving entries more quickly between
20592levels. This lets it adapt to new IO patterns very quickly.
20593
20594Performance:
20595Testing smq shows substantially better performance than mq.
20596
20597cleaner
20598-------
20599
20600The cleaner writes back all dirty blocks in a cache to decommission it.
20601
20602Examples
20603========
20604
20605The syntax for a table is:
20606 cache <metadata dev> <cache dev> <origin dev> <block size>
20607 <#feature_args> [<feature arg>]*
20608 <policy> <#policy_args> [<policy arg>]*
20609
20610The syntax to send a message using the dmsetup command is:
20611 dmsetup message <mapped device> 0 sequential_threshold 1024
20612 dmsetup message <mapped device> 0 random_threshold 8
20613
20614Using dmsetup:
20615 dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
20616 /dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
20617 creates a 128GB large mapped device named 'blah' with the
20618 sequential threshold set to 1024 and the random_threshold set to 8.
20619\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/service-time.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006252\013062740170\0022236\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-service-time
20620===============
20621
20622dm-service-time is a path selector module for device-mapper targets,
20623which selects a path with the shortest estimated service time for
20624the incoming I/O.
20625
20626The service time for each path is estimated by dividing the total size
20627of in-flight I/Os on a path with the performance value of the path.
20628The performance value is a relative throughput value among all paths
20629in a path-group, and it can be specified as a table argument.
20630
20631The path selector name is 'service-time'.
20632
20633Table parameters for each path: [<repeat_count> [<relative_throughput>]]
20634 <repeat_count>: The number of I/Os to dispatch using the selected
20635 path before switching to the next path.
20636 If not given, internal default is used. To check
20637 the default value, see the activated table.
20638 <relative_throughput>: The relative throughput value of the path
20639 among all paths in the path-group.
20640 The valid range is 0-100.
20641 If not given, minimum value '1' is used.
20642 If '0' is given, the path isn't selected while
20643 other paths having a positive value are available.
20644
20645Status for each path: <status> <fail-count> <in-flight-size> \
20646 <relative_throughput>
20647 <status>: 'A' if the path is active, 'F' if the path is failed.
20648 <fail-count>: The number of path failures.
20649 <in-flight-size>: The size of in-flight I/Os on the path.
20650 <relative_throughput>: The relative throughput value of the path
20651 among all paths in the path-group.
20652
20653
20654Algorithm
20655=========
20656
20657dm-service-time adds the I/O size to 'in-flight-size' when the I/O is
20658dispatched and subtracts when completed.
20659Basically, dm-service-time selects a path having minimum service time
20660which is calculated by:
20661
20662 ('in-flight-size' + 'size-of-incoming-io') / 'relative_throughput'
20663
20664However, some optimizations below are used to reduce the calculation
20665as much as possible.
20666
20667 1. If the paths have the same 'relative_throughput', skip
20668 the division and just compare the 'in-flight-size'.
20669
20670 2. If the paths have the same 'in-flight-size', skip the division
20671 and just compare the 'relative_throughput'.
20672
20673 3. If some paths have non-zero 'relative_throughput' and others
20674 have zero 'relative_throughput', ignore those paths with zero
20675 'relative_throughput'.
20676
20677If such optimizations can't be applied, calculate service time, and
20678compare service time.
20679If calculated service time is equal, the path having maximum
20680'relative_throughput' may be better. So compare 'relative_throughput'
20681then.
20682
20683
20684Examples
20685========
20686In case that 2 paths (sda and sdb) are used with repeat_count == 128
20687and sda has an average throughput 1GB/s and sdb has 4GB/s,
20688'relative_throughput' value may be '1' for sda and '4' for sdb.
20689
20690# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4" \
20691 dmsetup create test
20692#
20693# dmsetup table
20694test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 1 8:16 128 4
20695#
20696# dmsetup status
20697test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 1 8:16 A 0 0 4
20698
20699
20700Or '2' for sda and '8' for sdb would be also true.
20701
20702# echo "0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8" \
20703 dmsetup create test
20704#
20705# dmsetup table
20706test: 0 10 multipath 0 0 1 1 service-time 0 2 2 8:0 128 2 8:16 128 8
20707#
20708# dmsetup status
20709test: 0 10 multipath 2 0 0 0 1 1 E 0 2 2 8:0 A 0 0 2 8:16 A 0 0 8
20710\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/kcopyd.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003555\013062740170\0021136\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0kcopyd
20711======
20712
20713Kcopyd provides the ability to copy a range of sectors from one block-device
20714to one or more other block-devices, with an asynchronous completion
20715notification. It is used by dm-snapshot and dm-mirror.
20716
20717Users of kcopyd must first create a client and indicate how many memory pages
20718to set aside for their copy jobs. This is done with a call to
20719kcopyd_client_create().
20720
20721 int kcopyd_client_create(unsigned int num_pages,
20722 struct kcopyd_client **result);
20723
20724To start a copy job, the user must set up io_region structures to describe
20725the source and destinations of the copy. Each io_region indicates a
20726block-device along with the starting sector and size of the region. The source
20727of the copy is given as one io_region structure, and the destinations of the
20728copy are given as an array of io_region structures.
20729
20730 struct io_region {
20731 struct block_device *bdev;
20732 sector_t sector;
20733 sector_t count;
20734 };
20735
20736To start the copy, the user calls kcopyd_copy(), passing in the client
20737pointer, pointers to the source and destination io_regions, the name of a
20738completion callback routine, and a pointer to some context data for the copy.
20739
20740 int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
20741 unsigned int num_dests, struct io_region *dests,
20742 unsigned int flags, kcopyd_notify_fn fn, void *context);
20743
20744 typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err,
20745 void *context);
20746
20747When the copy completes, kcopyd will call the user's completion routine,
20748passing back the user's context pointer. It will also indicate if a read or
20749write error occurred during the copy.
20750
20751When a user is done with all their copy jobs, they should call
20752kcopyd_client_destroy() to delete the kcopyd client, which will release the
20753associated memory pages.
20754
20755 void kcopyd_client_destroy(struct kcopyd_client *kc);
20756
20757\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/doc/kernel/crypt.txt\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006654\013062740170\0021011\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm-crypt
20758=========
20759
20760Device-Mapper's "crypt" target provides transparent encryption of block devices
20761using the kernel crypto API.
20762
20763For a more detailed description of supported parameters see:
20764https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
20765
20766Parameters: <cipher> <key> <iv_offset> <device path> \
20767 <offset> [<#opt_params> <opt_params>]
20768
20769<cipher>
20770 Encryption cipher and an optional IV generation mode.
20771 (In format cipher[:keycount]-chainmode-ivmode[:ivopts]).
20772 Examples:
20773 des
20774 aes-cbc-essiv:sha256
20775 twofish-ecb
20776
20777 /proc/crypto contains supported crypto modes
20778
20779<key>
20780 Key used for encryption. It is encoded as a hexadecimal number.
20781 You can only use key sizes that are valid for the selected cipher
20782 in combination with the selected iv mode.
20783 Note that for some iv modes the key string can contain additional
20784 keys (for example IV seed) so the key contains more parts concatenated
20785 into a single string.
20786
20787<keycount>
20788 Multi-key compatibility mode. You can define <keycount> keys and
20789 then sectors are encrypted according to their offsets (sector 0 uses key0;
20790 sector 1 uses key1 etc.). <keycount> must be a power of two.
20791
20792<iv_offset>
20793 The IV offset is a sector count that is added to the sector number
20794 before creating the IV.
20795
20796<device path>
20797 This is the device that is going to be used as backend and contains the
20798 encrypted data. You can specify it as a path like /dev/xxx or a device
20799 number <major>:<minor>.
20800
20801<offset>
20802 Starting sector within the device where the encrypted data begins.
20803
20804<#opt_params>
20805 Number of optional parameters. If there are no optional parameters,
20806 the optional paramaters section can be skipped or #opt_params can be zero.
20807 Otherwise #opt_params is the number of following arguments.
20808
20809 Example of optional parameters section:
20810 3 allow_discards same_cpu_crypt submit_from_crypt_cpus
20811
20812allow_discards
20813 Block discard requests (a.k.a. TRIM) are passed through the crypt device.
20814 The default is to ignore discard requests.
20815
20816 WARNING: Assess the specific security risks carefully before enabling this
20817 option. For example, allowing discards on encrypted devices may lead to
20818 the leak of information about the ciphertext device (filesystem type,
20819 used space etc.) if the discarded blocks can be located easily on the
20820 device later.
20821
20822same_cpu_crypt
20823 Perform encryption using the same cpu that IO was submitted on.
20824 The default is to use an unbound workqueue so that encryption work
20825 is automatically balanced between available CPUs.
20826
20827submit_from_crypt_cpus
20828 Disable offloading writes to a separate thread after encryption.
20829 There are some situations where offloading write bios from the
20830 encryption threads to a single thread degrades performance
20831 significantly. The default is to offload write bios to the same
20832 thread because it benefits CFQ to have writes submitted using the
20833 same context.
20834
20835Example scripts
20836===============
20837LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
20838encryption with dm-crypt using the 'cryptsetup' utility, see
20839https://gitlab.com/cryptsetup/cryptsetup
20840
20841[[
20842#!/bin/sh
20843# Create a crypt device using dmsetup
20844dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
20845]]
20846
20847[[
20848#!/bin/sh
20849# Create a crypt device using cryptsetup and LUKS header with default cipher
20850cryptsetup luksFormat $1
20851cryptsetup luksOpen $1 crypt1
20852]]
20853\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/coverity/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0016713\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/coverity/coverity_model.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005566\013062740170\0022117\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
20854 * Copyright (C) 2015 Red Hat, Inc. All rights reserved.
20855 *
20856 * This file is part of LVM2.
20857 *
20858 * This copyrighted material is made available to anyone wishing to use,
20859 * modify, copy, or redistribute it subject to the terms and conditions
20860 * of the GNU General Public License v.2.
20861 *
20862 * You should have received a copy of the GNU General Public License
20863 * along with this program; if not, write to the Free Software Foundation,
20864 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20865 */
20866
20867/*
20868 * Coverity usage:
20869 *
20870 * translate model into xml
20871 * cov-make-library -of coverity_model.xml coverity_model.c
20872 *
20873 * compile (using outdir 'cov'):
20874 * cov-build --dir=cov make CC=gcc
20875 *
20876 * analyze (agressively, using 'cov')
20877 * cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml
20878 *
20879 * generate html output (to 'html' from 'cov'):
20880 * cov-format-errors --dir cov --html-output html
20881 */
20882
20883struct lv_segment;
20884struct logical_volume;
20885
20886struct lv_segment *first_seg(const struct logical_volume *lv)
20887{
20888 return ((struct lv_segment **)lv)[0];
20889}
20890
20891struct lv_segment *last_seg(const struct logical_volume *lv)
20892{
20893 return ((struct lv_segment **)lv)[0];
20894}
20895
20896/* simple_memccpy() from glibc */
20897void *memccpy(void *dest, const void *src, int c, size_t n)
20898{
20899 const char *s = src;
20900 char *d = dest;
20901
20902 while (n-- > 0)
20903 if ((*d++ = *s++) == (char) c)
20904 return d;
20905
20906 return 0;
20907}
20908
20909/*
20910 * 2 lines bellow needs to be placed in coverity/config/user_nodefs.h
20911 * Not sure about any other way.
20912 * Without them, coverity shows warning since x86 system header files
20913 * are using inline assembly to reset fdset
20914 */
20915//#nodef FD_ZERO model_FD_ZERO
20916//void model_FD_ZERO(void *fdset);
20917
20918void model_FD_ZERO(void *fdset)
20919{
20920 unsigned i;
20921
20922 for (i = 0; i < 1024 / 8 / sizeof(long); ++i)
20923 ((long*)fdset)[i] = 0;
20924}
20925
20926/*
20927 * Added extra pointer check to not need these models,
20928 * for now just keep then in file
20929 */
20930
20931/*
20932struct cmd_context;
20933struct profile;
20934
20935const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
20936{
20937 return "text";
20938}
20939
20940const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, struct profile *profile)
20941{
20942 return "text";
20943}
20944*/
20945
20946/*
20947 * Until fixed coverity case# 00531860:
20948 * A FORWARD_NULL false positive on a recursive function call
20949 *
20950 * model also these functions:
20951 */
20952/*
20953const struct dm_config_node;
20954const struct dm_config_node *find_config_tree_array(struct cmd_context *cmd, int id, struct profile *profile)
20955{
20956 const struct dm_config_node *cn;
20957
20958 return cn;
20959}
20960
20961const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile)
20962{
20963 const struct dm_config_node *cn;
20964
20965 return cn;
20966}
20967
20968int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile)
20969{
20970 int b;
20971
20972 return b;
20973}
20974*/
20975\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0015622\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvck.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002306\013062740170\0017264\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVCK 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
20976.SH NAME
20977pvck \(em check physical volume metadata
20978.SH SYNOPSIS
20979.B pvck
20980.RB [ \-\-commandprofile
20981.IR ProfileName ]
20982.RB [ \-d | \-\-debug ]
20983.RB [ \-h | \-\-help ]
20984.RB [ \-v | \-\-verbose ]
20985.RB [ \-\-labelsector
20986.IR sector ]
20987.I PhysicalVolume
20988.RI [ PhysicalVolume ...]
20989.SH DESCRIPTION
20990pvck checks physical volume LVM metadata for consistency.
20991.SH OPTIONS
20992See \fBlvm\fP(8) for common options.
20993.TP
20994.B \-\-labelsector \fIsector
20995By default, 4 sectors of \fBPhysicalVolume\fP are scanned for an LVM label,
20996starting at sector 0. This parameter allows you to specify a different
20997starting sector for the scan and is useful for recovery situations. For
20998example, suppose the partition table is corrupted or lost on /dev/sda,
20999but you suspect there was an LVM partition at approximately 100 MiB. This
21000area of the disk may be scanned by using the \fB\-\-labelsector\fP parameter
21001with a value of 204800 (100 * 1024 * 1024 / 512 = 204800):
21002.sp
21003.B pvck \-\-labelsector 204800 /dev/sda
21004.sp
21005Note that a script can be used with \fB\-\-labelsector\fP to automate the
21006process of finding LVM labels.
21007.SH SEE ALSO
21008.BR lvm (8),
21009.BR pvcreate (8),
21010.BR pvscan (8)
21011.BR vgck (8)
21012\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgimport.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002153\013062740170\0020170\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGIMPORT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
21013.SH NAME
21014vgimport \(em make exported volume groups known to the system
21015.SH SYNOPSIS
21016.B vgimport
21017.RB [ \-a | \-\-all ]
21018.RB [ \-d | \-\-debug ]
21019.RB [ \-h | \-? | \-\-help ]
21020.RB [ \-\-reportformat
21021.RB { basic | json }]
21022.RB [ \-S | \-\-select
21023.IR Selection ]
21024.RB [ \-v | \-\-verbose ]
21025.RI [ VolumeGroupName ...]
21026.SH DESCRIPTION
21027vgimport allows you to make a Volume Group that was previously
21028exported using
21029.BR vgexport (8)
21030known to the system again, perhaps after moving its Physical Volumes
21031from a different machine.
21032vgexport clears the VG system ID, and vgimport sets the VG system ID
21033to match the host running vgimport (if the host has a system ID).
21034.SH OPTIONS
21035See \fBlvm\fP(8) for common options.
21036.TP
21037.BR \-a ", " \-\-all
21038Import all exported Volume Groups.
21039.TP
21040.BR \-\-force
21041Import exported Volume Groups even if there are missing Physical Volumes.
21042This option should only be used if the missing devices are known to have
21043failed and they cannot be restored.
21044.SH SEE ALSO
21045.BR lvm (8),
21046.BR pvscan (8),
21047.BR vgexport (8),
21048.BR vgscan (8),
21049.BR lvmsystemid (7)
21050\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmdiskscan.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001443\013062740170\0020640\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMDISKSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
21051.SH NAME
21052lvmdiskscan \(em scan for all devices visible to LVM2
21053.SH SYNOPSIS
21054.B lvmdiskscan
21055.RB [ \-\-commandprofile
21056.IR ProfileName ]
21057.RB [ \-d | \-\-debug ]
21058.RB [ \-h | \-? | \-\-help ]
21059.RB [ \-l | \-\-lvmpartition ]
21060.RB [ \-v | \-\-verbose ]
21061.SH DESCRIPTION
21062lvmdiskscan scans all SCSI, (E)IDE disks, multiple devices and a bunch
21063of other block devices in the system looking for LVM physical volumes.
21064The size reported is the real device size.
21065Define a filter in \fBlvm.conf\fP(5) to restrict
21066the scan to avoid a CD ROM, for example.
21067.SH OPTIONS
21068See \fBlvm\fP(8) for common options.
21069.TP
21070.BR \-l ", " \-\-lvmpartition
21071Only reports Physical Volumes.
21072.SH SEE ALSO
21073.BR lvm (8),
21074.BR lvm.conf (5),
21075.BR pvscan (8),
21076.BR vgscan (8)
21077\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvs.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000023306\013062740170\0017130\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
21078.SH NAME
21079lvs \(em report information about logical volumes
21080.SH SYNOPSIS
21081.B lvs
21082.RB [ \-\-aligned ]
21083.RB [ \-\-binary ]
21084.RB [ \-a | \-\-all ]
21085.RB [ \-\-commandprofile
21086.IR ProfileName ]
21087.RB [[ \-\-configreport
21088.IR ReportName ]
21089.RB [ \-o | \-\-options
21090.RI [ + | \- | # ] Field1 [, Field2 ...]
21091.RB [ \-O | \-\-sort
21092.RI [ + | \- ] Key1 [, Key2 ...]]
21093.RB [ \-S | \-\-select
21094.IR Selection ]
21095.RB ...]
21096.RB [ \-d | \-\-debug ]
21097.RB [ \-h | \-? | \-\-help ]
21098.RB [ \-H | \-\-history ]
21099.RB [ \-\-ignorelockingfailure ]
21100.RB [ \-\-ignoreskippedcluster ]
21101.RB [ \-\-logonly ]
21102.RB [ \-\-nameprefixes ]
21103.RB [ \-\-noheadings ]
21104.RB [ \-\-nosuffix ]
21105.RI [ + | \- ] Key1 [,[ + | \- ] Key2 [,...]]]
21106.RB [ \-P | \-\-partial ]
21107.RB [ \-\-reportformat
21108.RB { basic | json }]
21109.RB [ \-\-rows ]
21110.RB [ \-\-separator
21111.IR Separator ]
21112.RB [ \-\-segments ]
21113.RB [ \-\-unbuffered ]
21114.RB [ \-\-units
21115.IR hHbBsSkKmMgGtTpPeE ]
21116.RB [ \-\-unquoted ]
21117.RB [ \-v | \-\-verbose ]
21118.RB [ \-\-version ]
21119.RI [ VolumeGroupName | LogicalVolume { Name | Path }
21120.RI [ VolumeGroupName | LogicalVolume { Name | Path }\ ...]]
21121
21122.SH DESCRIPTION
21123lvs produces formatted output about logical volumes.
21124.SH OPTIONS
21125See
21126.BR lvm (8)
21127for common options.
21128.TP
21129.B \-\-aligned
21130Use with \fB\-\-separator\fP to align the output columns.
21131.TP
21132.B \-\-all
21133Include information in the output about internal Logical Volumes that
21134are components of normally-accessible Logical Volumes, such as mirrors,
21135but which are not independently accessible (e.g. not mountable).
21136The names of such Logical Volumes are enclosed within square brackets
21137in the output. For example, after creating a mirror using
21138.B lvcreate -m1 \-\-mirrorlog disk
21139, this option will reveal three internal Logical
21140Volumes, with suffixes mimage_0, mimage_1, and mlog.
21141.TP
21142.B \-\-binary
21143Use binary values "0" or "1" instead of descriptive literal values
21144for columns that have exactly two valid values to report (not counting
21145the "unknown" value which denotes that the value could not be determined).
21146.TP
21147.B \-\-configreport \fI ReportName
21148Make any subsequent \fB\-o, \-\-options\fP, \fB\-O, \-\-sort\fP or
21149\fB\-S, \-\-select\fP to apply for \fIReportName\fP where \fIReportName\fP
21150is either 'lv' for command's main report or 'log' for log report.
21151If \fB\-\-configreport\fP option is not used to identify a report, then
21152command's main report is assumed. The log report is available only if
21153enabled by \fBlog/report_command_log\fP \fBlvm.conf\fP(5) setting or
21154if \fB\-\-logonly\fP option is used.
21155.TP
21156.B \-H ", " \-\-history
21157Include historical logical volumes in the output.
21158(This has no effect unless logical volumes were removed while the configuration
21159setting \fBmetadata/record_lvs_history\fP was enabled.)
21160.TP
21161.B \-\-logonly
21162Suppress the lvs report itself and display only log report on output.
21163.TP
21164.B \-\-nameprefixes
21165Add an "LVM2_" prefix plus the field name to the output. Useful
21166with \fB\-\-noheadings\fP to produce a list of field=value pairs that can
21167be used to set environment variables (for example, in
21168.BR udev (7)
21169rules).
21170.TP
21171.B \-\-noheadings
21172Suppress the headings line that is normally the first line of output.
21173Useful if grepping the output.
21174.TP
21175.B \-\-nosuffix
21176Suppress the suffix on output sizes. Use with \fB\-\-units\fP
21177(except h and H) if processing the output.
21178.TP
21179.BR \-o ", " \-\-options
21180Comma-separated ordered list of columns.
21181.IP
21182Precede the list with '\fI+\fP' to append to the current list
21183of columns, '\fI-\fP' to remove from the current list of columns
21184or '\fI#\fP' to compact given columns. The \fI\-o\fP option can
21185be repeated, providing several lists. These lists are evaluated
21186from left to right.
21187.IP
21188Use \fB\-o lv_all\fP to select all logical volume columns,
21189and \fB\-o seg_all\fP
21190to select all logical volume segment columns.
21191.IP
21192Use \fB\-o help\fP to view the full list of columns available.
21193.IP
21194Column names include:
21195chunk_size,
21196convert_lv,
21197copy_percent,
21198data_lv,
21199devices,
21200discards,
21201lv_attr,
21202lv_host,
21203lv_kernel_major,
21204lv_kernel_minor,
21205lv_kernel_read_ahead,
21206lv_major,
21207lv_minor,
21208lv_name,
21209lv_path,
21210lv_profile,
21211lv_read_ahead,
21212lv_size,
21213lv_tags,
21214lv_time,
21215lv_uuid,
21216metadata_lv,
21217mirror_log,
21218modules,
21219move_pv,
21220origin,
21221origin_size,
21222pool_lv,
21223raid_max_recovery_rate,
21224raid_min_recovery_rate,
21225raid_mismatch_count,
21226raid_sync_action,
21227raid_write_behind,
21228region_size,
21229segtype,
21230seg_count,
21231seg_pe_ranges,
21232seg_size,
21233seg_size_pe,
21234seg_start,
21235seg_start_pe,
21236seg_tags,
21237snap_percent,
21238stripes,
21239stripe_size,
21240sync_percent,
21241thin_count,
21242transaction_id,
21243zero.
21244.IP
21245With \fB\-\-segments\fP, any "seg_" prefixes are optional;
21246otherwise any "lv_" prefixes are optional. Columns mentioned in
21247.BR vgs (8)
21248can also be chosen.
21249.IP
21250The lv_attr bits are:
21251.RS
21252.IP 1 3
21253Volume type: (C)ache, (m)irrored, (M)irrored without initial sync, (o)rigin,
21254(O)rigin with merging snapshot, (r)aid, (R)aid without initial sync,
21255(s)napshot, merging (S)napshot, (p)vmove, (v)irtual,
21256mirror or raid (i)mage, mirror or raid (I)mage out-of-sync, mirror (l)og device,
21257under (c)onversion, thin (V)olume, (t)hin pool, (T)hin pool data, raid or
21258pool m(e)tadata or pool metadata spare.
21259.IP 2 3
21260Permissions: (w)riteable, (r)ead-only, (R)ead-only activation of non-read-only
21261volume
21262.IP 3 3
21263Allocation policy: (a)nywhere, (c)ontiguous, (i)nherited, c(l)ing, (n)ormal
21264This is capitalised if the volume is currently locked against allocation
21265changes, for example during
21266.BR pvmove (8).
21267.IP 4 3
21268fixed (m)inor
21269.IP 5 3
21270State: (a)ctive, (h)istorical, (s)uspended, (I)nvalid snapshot,
21271invalid (S)uspended snapshot, snapshot (m)erge failed,
21272suspended snapshot (M)erge failed, mapped (d)evice present without tables,
21273mapped device present with (i)nactive table, thin-pool (c)heck needed,
21274suspended thin-pool (C)heck needed, (X) unknown
21275.IP 6 3
21276device (o)pen, (X) unknown
21277.IP 7 3
21278Target type: (C)ache, (m)irror, (r)aid, (s)napshot, (t)hin, (u)nknown, (v)irtual.
21279This groups logical volumes related to the same kernel target together. So,
21280for example, mirror images, mirror logs as well as mirrors themselves appear as
21281(m) if they use the original device-mapper mirror kernel driver; whereas the raid
21282equivalents using the md raid kernel driver all appear as (r).
21283Snapshots using the original device-mapper driver appear as (s); whereas
21284snapshots of thin volumes using the new thin provisioning driver appear as (t).
21285.IP 8 3
21286Newly-allocated data blocks are overwritten with blocks of (z)eroes before use.
21287.IP 9 3
21288Volume Health, where there are currently three groups of attributes identified:
21289.IP
21290Common ones for all Logical Volumes: (p)artial, (X) unknown.
21291.br
21292(p)artial signifies that one or more of the Physical Volumes this Logical
21293Volume uses is missing from the system. (X) unknown signifies the status
21294is unknown.
21295.IP
21296Related to RAID Logical Volumes: (r)efresh needed, (m)ismatches exist, (w)ritemostly.
21297.br
21298(r)efresh signifies that one or more of the Physical Volumes this RAID Logical
21299Volume uses had suffered a write error. The write error could be due to a
21300temporary failure of that Physical Volume or an indication that it is failing.
21301The device should be refreshed or replaced. (m)ismatches signifies that the
21302RAID logical volume has portions of the array that are not coherent.
21303Inconsistencies are detected by initiating a "check" on a RAID logical volume.
21304(The scrubbing operations, "check" and "repair", can be performed on a RAID
21305logical volume via the 'lvchange' command.) (w)ritemostly signifies the
21306devices in a RAID 1 logical volume that have been marked write-mostly.
21307.IP
21308Related to Thin pool Logical Volumes: (F)ailed, out of (D)ata space,
21309(M)etadata read only.
21310.br
21311(F)ailed is set if thin pool encounters serious failures and hence no further I/O
21312is permitted at all. The out of (D)ata space is set if thin pool has run out of
21313data space. (M)etadata read only signifies that thin pool encounters certain
21314types of failures but it's still possible to do reads at least,
21315but no metadata changes are allowed.
21316.IP
21317Related to Thin Logical Volumes: (F)ailed.
21318.br
21319(F)ailed is set when related thin pool enters Failed state and no further I/O
21320is permitted at all.
21321.IP 10 3
21322s(k)ip activation: this volume is flagged to be skipped during activation.
21323.RE
21324.TP
21325.BR \-O ", " \-\-sort
21326Comma-separated ordered list of columns to sort by. Replaces the default
21327selection. Precede any column with '\fI\-\fP' for a reverse sort on that column.
21328.TP
21329.B \-\-rows
21330Output columns as rows.
21331.TP
21332.BR \-S ", " \-\-select " " \fISelection
21333Display only rows that match Selection criteria. All rows are displayed with
21334the additional "selected" column (\fB-o selected\fP) showing 1 if the row
21335matches the Selection and 0 otherwise. The Selection criteria are defined
21336by specifying column names and their valid values (that can include reserved
21337values) while making use of supported comparison operators. See \fBlvm\fP(8)
21338and \fB\-S\fP, \fB\-\-select\fP description for more detailed information
21339about constructing the Selection criteria. As a quick help and to see full
21340list of column names that can be used in Selection including the list of
21341reserved values and the set of supported selection operators, check the
21342output of \fBlvs -S help\fP command.
21343.TP
21344.B \-\-segments
21345Use default columns that emphasize segment information.
21346.TP
21347.B \-\-separator \fISeparator
21348String to use to separate each column. Useful if grepping the output.
21349.TP
21350.B \-\-unbuffered
21351Produce output immediately without sorting or aligning the columns properly.
21352.TP
21353.B \-\-units \fIhHbBsSkKmMgGtTpPeE
21354All sizes are output in these units: (h)uman-readable, (b)ytes, (s)ectors,
21355(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
21356Capitalise to use multiples of 1000 (S.I.) instead of 1024. Can also specify
21357custom units e.g. \fB\-\-units 3M\fP
21358.TP
21359.B \-\-unquoted
21360When used with \fB\-\-nameprefixes\fP, output values in the field=value
21361pairs are not quoted.
21362.SH SEE ALSO
21363.BR lvm (8),
21364.BR lvdisplay (8),
21365.BR pvs (8),
21366.BR vgs (8)
21367\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmconf.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004162\013062740170\0017767\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMCONF" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
21368
21369.SH "NAME"
21370lvmconf \(em LVM configuration modifier
21371.SH "SYNOPSIS"
21372.B lvmconf
21373.RB [ \-\-disable-cluster ]
21374.RB [ \-\-enable-cluster ]
21375.RB [ \-\-enable-halvm ]
21376.RB [ \-\-disable-halvm ]
21377.RB [ \-\-file
21378.RI < configfile >]
21379.RB [ \-\-lockinglib
21380.RI < lib >]
21381.RB [ \-\-lockinglibdir
21382.RI < dir >]
21383.RB [ \-\-services ]
21384.RB [ \-\-mirrorservice ]
21385.RB [ \-\-startstopservices ]
21386
21387.SH "DESCRIPTION"
21388lvmconf is a script that modifies the locking configuration in
21389an lvm configuration file. See \fBlvm.conf\fP(5). In addition
21390to that, it can also set Systemd or SysV services according to
21391changes in the lvm configuration if needed.
21392
21393.SH "OPTIONS"
21394.TP
21395.BR \-\-disable-cluster
21396Set \fBlocking_type\fR to the default non-clustered type. Also reset
21397lvmetad use to its default.
21398.TP
21399.BR \-\-enable-cluster
21400Set \fBlocking_type\fR to the default clustered type on this system.
21401Also disable lvmetad use as it is not yet supported in clustered environment.
21402.TP
21403.BR \-\-disable-halvm
21404Set \fBlocking_type\fR to the default non-clustered type. Also reset
21405lvmetad use to its default.
21406.TP
21407.BR \-\-enable-halvm
21408Set \fBlocking_type\fR suitable for HA LVM use.
21409Also disable lvmetad use as it is not yet supported in HA LVM environment.
21410.TP
21411.BR \-\-file " <" \fIconfigfile >
21412Apply the changes to \fIconfigfile\fP instead of the default
21413\fI#DEFAULT_SYS_DIR#/lvm.conf\fP.
21414.TP
21415.BR \-\-lockinglib " <" \fIlib >
21416Set external \fBlocking_library\fR locking library to load if an external locking type is used.
21417.TP
21418.BR \-\-lockinglibdir " <" \fIdir >
21419.TP
21420.BR \-\-services
21421In addition to setting the lvm configuration, also enable or disable related Systemd or SysV
21422clvmd and lvmetad services. This script does not configure services provided by cluster resource
21423agents.
21424.TP
21425.BR \-\-mirrorservice
21426Also enable or disable optional cmirrord service when handling services (applicable only with \-\-services).
21427.TP
21428.BR \-\-startstopservices
21429In addition to enabling or disabling related services, start or stop them immediately
21430(applicable only with \-\-services).
21431.SH FILES
21432.I #DEFAULT_SYS_DIR#/lvm.conf
21433
21434.SH "SEE ALSO"
21435.BR lvm (8),
21436.BR lvm.conf (5)
21437\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmraid.7.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000111455\013062740170\0017764\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMRAID" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
21438
21439.SH NAME
21440lvmraid \(em LVM RAID
21441
21442.SH DESCRIPTION
21443
21444LVM RAID is a way to create logical volumes (LVs) that use multiple physical
21445devices to improve performance or tolerate device failure. How blocks of
21446data in an LV are placed onto physical devices is determined by the RAID
21447level. RAID levels are commonly referred to by number, e.g. raid1, raid5.
21448Selecting a RAID level involves tradeoffs among physical device
21449requirements, fault tolerance, and performance. A description of the RAID
21450levels can be found at
21451.br
21452www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
21453
21454LVM RAID uses both Device Mapper (DM) and Multiple Device (MD) drivers
21455from the Linux kernel. DM is used to create and manage visible LVM
21456devices, and MD is used to place data on physical devices.
21457
21458.SH Create a RAID LV
21459
21460To create a RAID LV, use lvcreate and specify an LV type.
21461The LV type corresponds to a RAID level.
21462The basic RAID levels that can be used are:
21463.B raid0, raid1, raid4, raid5, raid6, raid10.
21464
21465.B lvcreate \-\-type
21466.I RaidLevel
21467[\fIOPTIONS\fP]
21468.B \-\-name
21469.I Name
21470.B \-\-size
21471.I Size
21472.I VG
21473[\fIPVs\fP]
21474
21475To display the LV type of an existing LV, run:
21476
21477.B lvs -o name,segtype
21478\fIVG\fP/\fILV\fP
21479
21480(The LV type is also referred to as "segment type" or "segtype".)
21481
21482LVs can be created with the following types:
21483
21484.SS raid0
21485
21486\&
21487
21488Also called striping, raid0 spreads LV data across multiple devices in
21489units of stripe size. This is used to increase performance. LV data will
21490be lost if any of the devices fail.
21491
21492.B lvcreate \-\-type raid0
21493[\fB\-\-stripes\fP \fINumber\fP \fB\-\-stripesize\fP \fISize\fP]
21494\fIVG\fP
21495[\fIPVs\fP]
21496
21497.HP
21498.B \-\-stripes
21499specifies the number of devices to spread the LV across.
21500
21501.HP
21502.B \-\-stripesize
21503specifies the size of each stripe in kilobytes. This is the amount of
21504data that is written to one device before moving to the next.
21505.P
21506
21507\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21508\fINumber\fP devices, one for each stripe.
21509
21510.SS raid1
21511
21512\&
21513
21514Also called mirroring, raid1 uses multiple devices to duplicate LV data.
21515The LV data remains available if all but one of the devices fail.
21516The minimum number of devices required is 2.
21517
21518.B lvcreate \-\-type raid1
21519[\fB\-\-mirrors\fP \fINumber\fP]
21520\fIVG\fP
21521[\fIPVs\fP]
21522
21523.HP
21524.B \-\-mirrors
21525specifies the number of mirror images in addition to the original LV
21526image, e.g. \-\-mirrors 1 means there are two images of the data, the
21527original and one mirror image.
21528.P
21529
21530\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21531\fINumber\fP devices, one for each image.
21532
21533.SS raid4
21534
21535\&
21536
21537raid4 is a form of striping that uses an extra device dedicated to storing
21538parity blocks. The LV data remains available if one device fails. The
21539parity is used to recalculate data that is lost from a single device. The
21540minimum number of devices required is 3.
21541
21542.B lvcreate \-\-type raid4
21543[\fB\-\-stripes\fP \fINumber\fP \fB\-\-stripesize\fP \fISize\fP]
21544\fIVG\fP
21545[\fIPVs\fP]
21546
21547.HP
21548.B \-\-stripes
21549specifies the number of devices to use for LV data. This does not include
21550the extra device lvm adds for storing parity blocks. \fINumber\fP stripes
21551requires \fINumber\fP+1 devices. \fINumber\fP must be 2 or more.
21552
21553.HP
21554.B \-\-stripesize
21555specifies the size of each stripe in kilobytes. This is the amount of
21556data that is written to one device before moving to the next.
21557.P
21558
21559\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21560\fINumber\fP+1 separate devices.
21561
21562raid4 is called non-rotating parity because the parity blocks are always
21563stored on the same device.
21564
21565.SS raid5
21566
21567\&
21568
21569raid5 is a form of striping that uses an extra device for storing parity
21570blocks. LV data and parity blocks are stored on each device. The LV data
21571remains available if one device fails. The parity is used to recalculate
21572data that is lost from a single device. The minimum number of devices
21573required is 3.
21574
21575.B lvcreate \-\-type raid5
21576[\fB\-\-stripes\fP \fINumber\fP \fB\-\-stripesize\fP \fISize\fP]
21577\fIVG\fP
21578[\fIPVs\fP]
21579
21580.HP
21581.B \-\-stripes
21582specifies the number of devices to use for LV data. This does not include
21583the extra device lvm adds for storing parity blocks. \fINumber\fP stripes
21584requires \fINumber\fP+1 devices. \fINumber\fP must be 2 or more.
21585
21586.HP
21587.B \-\-stripesize
21588specifies the size of each stripe in kilobytes. This is the amount of
21589data that is written to one device before moving to the next.
21590.P
21591
21592\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21593\fINumber\fP+1 separate devices.
21594
21595raid5 is called rotating parity because the parity blocks are placed on
21596different devices in a round-robin sequence. There are variations of
21597raid5 with different algorithms for placing the parity blocks. The
21598default variant is raid5_ls (raid5 left symmetric, which is a rotating
21599parity 0 with data restart.) See \fBRAID5 variants\fP below.
21600
21601.SS raid6
21602
21603\&
21604
21605raid6 is a form of striping like raid5, but uses two extra devices for
21606parity blocks. LV data and parity blocks are stored on each device. The
21607LV data remains available if up to two devices fail. The parity is used
21608to recalculate data that is lost from one or two devices. The minimum
21609number of devices required is 5.
21610
21611.B lvcreate \-\-type raid6
21612[\fB\-\-stripes\fP \fINumber\fP \fB\-\-stripesize\fP \fISize\fP]
21613\fIVG\fP
21614[\fIPVs\fP]
21615
21616.HP
21617.B \-\-stripes
21618specifies the number of devices to use for LV data. This does not include
21619the extra two devices lvm adds for storing parity blocks. \fINumber\fP
21620stripes requires \fINumber\fP+2 devices. \fINumber\fP must be 3 or more.
21621
21622.HP
21623.B \-\-stripesize
21624specifies the size of each stripe in kilobytes. This is the amount of
21625data that is written to one device before moving to the next.
21626.P
21627
21628\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21629\fINumber\fP+2 separate devices.
21630
21631Like raid5, there are variations of raid6 with different algorithms for
21632placing the parity blocks. The default variant is raid6_zr (raid6 zero
21633restart, aka left symmetric, which is a rotating parity 0 with data
21634restart.) See \fBRAID6 variants\fP below.
21635
21636.SS raid10
21637
21638\&
21639
21640raid10 is a combination of raid1 and raid0, striping data across mirrored
21641devices. LV data remains available if one or more devices remains in each
21642mirror set. The minimum number of devices required is 4.
21643
21644.B lvcreate \-\-type raid10
21645.RS
21646[\fB\-\-mirrors\fP \fINumberMirrors\fP]
21647.br
21648[\fB\-\-stripes\fP \fINumberStripes\fP \fB\-\-stripesize\fP \fISize\fP]
21649.br
21650\fIVG\fP
21651[\fIPVs\fP]
21652.RE
21653
21654.HP
21655.B \-\-mirrors
21656specifies the number of mirror images within each stripe. e.g.
21657\-\-mirrors 1 means there are two images of the data, the original and one
21658mirror image.
21659
21660.HP
21661.B \-\-stripes
21662specifies the total number of devices to use in all raid1 images (not the
21663number of raid1 devices to spread the LV across, even though that is the
21664effective result). The number of devices in each raid1 mirror will be
21665NumberStripes/(NumberMirrors+1), e.g. mirrors 1 and stripes 4 will stripe
21666data across two raid1 mirrors, where each mirror is devices.
21667
21668.HP
21669.B \-\-stripesize
21670specifies the size of each stripe in kilobytes. This is the amount of
21671data that is written to one device before moving to the next.
21672.P
21673
21674\fIPVs\fP specifies the devices to use. If not specified, lvm will choose
21675the necessary devices. Devices are used to create mirrors in the
21676order listed, e.g. for mirrors 1, stripes 2, listing PV1 PV2 PV3 PV4
21677results in mirrors PV1/PV2 and PV3/PV4.
21678
21679RAID10 is not mirroring on top of stripes, which would be RAID01, which is
21680less tolerant of device failures.
21681
21682
21683.SH Synchronization
21684
21685Synchronization makes all the devices in a RAID LV consistent with each
21686other.
21687
21688In a RAID1 LV, all mirror images should have the same data. When a new
21689mirror image is added, or a mirror image is missing data, then images need
21690to be synchronized. Data blocks are copied from an existing image to a
21691new or outdated image to make them match.
21692
21693In a RAID 4/5/6 LV, parity blocks and data blocks should match based on
21694the parity calculation. When the devices in a RAID LV change, the data
21695and parity blocks can become inconsistent and need to be synchronized.
21696Correct blocks are read, parity is calculated, and recalculated blocks are
21697written.
21698
21699The RAID implementation keeps track of which parts of a RAID LV are
21700synchronized. This uses a bitmap saved in the RAID metadata. The bitmap
21701can exclude large parts of the LV from synchronization to reduce the
21702amount of work. Without this, the entire LV would need to be synchronized
21703every time it was activated. When a RAID LV is first created and
21704activated the first synchronization is called initialization.
21705
21706Automatic synchronization happens when a RAID LV is activated, but it is
21707usually partial because the bitmaps reduce the areas that are checked.
21708A full sync may become necessary when devices in the RAID LV are changed.
21709
21710The synchronization status of a RAID LV is reported by the
21711following command, where "image synced" means sync is complete:
21712
21713.B lvs -a -o name,sync_percent
21714
21715
21716.SS Scrubbing
21717
21718Scrubbing is a full scan/synchronization of the RAID LV requested by a user.
21719Scrubbing can find problems that are missed by partial synchronization.
21720
21721Scrubbing assumes that RAID metadata and bitmaps may be inaccurate, so it
21722verifies all RAID metadata, LV data, and parity blocks. Scrubbing can
21723find inconsistencies caused by hardware errors or degradation. These
21724kinds of problems may be undetected by automatic synchronization which
21725excludes areas outside of the RAID write-intent bitmap.
21726
21727The command to scrub a RAID LV can operate in two different modes:
21728
21729.B lvchange \-\-syncaction
21730.BR check | repair
21731.IR VG / LV
21732
21733.HP
21734.B check
21735Check mode is read\-only and only detects inconsistent areas in the RAID
21736LV, it does not correct them.
21737
21738.HP
21739.B repair
21740Repair mode checks and writes corrected blocks to synchronize any
21741inconsistent areas.
21742
21743.P
21744
21745Scrubbing can consume a lot of bandwidth and slow down application I/O on
21746the RAID LV. To control the I/O rate used for scrubbing, use:
21747
21748.HP
21749.B \-\-maxrecoveryrate
21750.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
21751.br
21752Sets the maximum recovery rate for a RAID LV. \fIRate\fP is specified as
21753an amount per second for each device in the array. If no suffix is given,
21754then KiB/sec/device is assumed. Setting the recovery rate to \fB0\fP
21755means it will be unbounded.
21756
21757.HP
21758.BR \-\-minrecoveryrate
21759.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
21760.br
21761Sets the minimum recovery rate for a RAID LV. \fIRate\fP is specified as
21762an amount per second for each device in the array. If no suffix is given,
21763then KiB/sec/device is assumed. Setting the recovery rate to \fB0\fP
21764means it will be unbounded.
21765
21766.P
21767
21768To display the current scrubbing in progress on an LV, including
21769the syncaction mode and percent complete, run:
21770
21771.B lvs -a -o name,raid_sync_action,sync_percent
21772
21773After scrubbing is complete, to display the number of inconsistent blocks
21774found, run:
21775
21776.B lvs -o name,raid_mismatch_count
21777
21778Also, if mismatches were found, the lvs attr field will display the letter
21779"m" (mismatch) in the 9th position, e.g.
21780
21781.nf
21782# lvs -o name,vgname,segtype,attr vg/lvol0
21783 LV VG Type Attr
21784 lvol0 vg raid1 Rwi-a-r-m-
21785.fi
21786
21787
21788.SS Scrubbing Limitations
21789
21790The \fBcheck\fP mode can only report the number of inconsistent blocks, it
21791cannot report which blocks are inconsistent. This makes it impossible to
21792know which device has errors, or if the errors affect file system data,
21793metadata or nothing at all.
21794
21795The \fBrepair\fP mode can make the RAID LV data consistent, but it does
21796not know which data is correct. The result may be consistent but
21797incorrect data. When two different blocks of data must be made
21798consistent, it chooses the block from the device that would be used during
21799RAID intialization. However, if the PV holding corrupt data is known,
21800lvchange \-\-rebuild can be used to reconstruct the data on the bad
21801device.
21802
21803Future developments might include:
21804
21805Allowing a user to choose the correct version of data during repair.
21806
21807Using a majority of devices to determine the correct version of data to
21808use in a three-way RAID1 or RAID6 LV.
21809
21810Using a checksumming device to pin-point when and where an error occurs,
21811allowing it to be rewritten.
21812
21813
21814.SH SubLVs
21815
21816An LV is often a combination of other hidden LVs called SubLVs. The
21817SubLVs either use physical devices, or are built from other SubLVs
21818themselves. SubLVs hold LV data blocks, RAID parity blocks, and RAID
21819metadata. SubLVs are generally hidden, so the lvs \-a option is required
21820display them:
21821
21822.B lvs -a -o name,segtype,devices
21823
21824SubLV names begin with the visible LV name, and have an automatic suffix
21825indicating its role:
21826
21827.IP \(bu 3
21828SubLVs holding LV data or parity blocks have the suffix _rimage_#.
21829These SubLVs are sometimes referred to as DataLVs.
21830
21831.IP \(bu 3
21832SubLVs holding RAID metadata have the suffix _rmeta_#. RAID metadata
21833includes superblock information, RAID type, bitmap, and device health
21834information. These SubLVs are sometimes referred to as MetaLVs.
21835
21836.P
21837
21838SubLVs are an internal implementation detail of LVM. The way they are
21839used, constructed and named may change.
21840
21841The following examples show the SubLV arrangement for each of the basic
21842RAID LV types, using the fewest number of devices allowed for each.
21843
21844.SS Examples
21845
21846.B raid0
21847.br
21848Each rimage SubLV holds a portion of LV data. No parity is used.
21849No RAID metadata is used.
21850
21851.nf
21852lvcreate --type raid0 --stripes 2 --name lvr0 ...
21853
21854lvs -a -o name,segtype,devices
21855 lvr0 raid0 lvr0_rimage_0(0),lvr0_rimage_1(0)
21856 [lvr0_rimage_0] linear /dev/sda(...)
21857 [lvr0_rimage_1] linear /dev/sdb(...)
21858.fi
21859
21860.B raid1
21861.br
21862Each rimage SubLV holds a complete copy of LV data. No parity is used.
21863Each rmeta SubLV holds RAID metadata.
21864
21865.nf
21866lvcreate --type raid1 --mirrors 1 --name lvr1 ...
21867
21868lvs -a -o name,segtype,devices
21869 lvr1 raid1 lvr1_rimage_0(0),lvr1_rimage_1(0)
21870 [lvr1_rimage_0] linear /dev/sda(...)
21871 [lvr1_rimage_1] linear /dev/sdb(...)
21872 [lvr1_rmeta_0] linear /dev/sda(...)
21873 [lvr1_rmeta_1] linear /dev/sdb(...)
21874.fi
21875
21876.B raid4
21877.br
21878Two rimage SubLVs each hold a portion of LV data and one rimage SubLV
21879holds parity. Each rmeta SubLV holds RAID metadata.
21880
21881.nf
21882lvcreate --type raid4 --stripes 2 --name lvr4 ...
21883
21884lvs -a -o name,segtype,devices
21885 lvr4 raid4 lvr4_rimage_0(0),\\
21886 lvr4_rimage_1(0),\\
21887 lvr4_rimage_2(0)
21888 [lvr4_rimage_0] linear /dev/sda(...)
21889 [lvr4_rimage_1] linear /dev/sdb(...)
21890 [lvr4_rimage_2] linear /dev/sdc(...)
21891 [lvr4_rmeta_0] linear /dev/sda(...)
21892 [lvr4_rmeta_1] linear /dev/sdb(...)
21893 [lvr4_rmeta_2] linear /dev/sdc(...)
21894.fi
21895
21896.B raid5
21897.br
21898Three rimage SubLVs each hold a portion of LV data and parity.
21899Each rmeta SubLV holds RAID metadata.
21900
21901.nf
21902lvcreate --type raid5 --stripes 2 --name lvr5 ...
21903
21904lvs -a -o name,segtype,devices
21905 lvr5 raid5 lvr5_rimage_0(0),\\
21906 lvr5_rimage_1(0),\\
21907 lvr5_rimage_2(0)
21908 [lvr5_rimage_0] linear /dev/sda(...)
21909 [lvr5_rimage_1] linear /dev/sdb(...)
21910 [lvr5_rimage_2] linear /dev/sdc(...)
21911 [lvr5_rmeta_0] linear /dev/sda(...)
21912 [lvr5_rmeta_1] linear /dev/sdb(...)
21913 [lvr5_rmeta_2] linear /dev/sdc(...)
21914.fi
21915
21916.B raid6
21917.br
21918Six rimage SubLVs each hold a portion of LV data and parity.
21919Each rmeta SubLV holds RAID metadata.
21920
21921.nf
21922lvcreate --type raid6 --stripes 3 --name lvr6
21923
21924lvs -a -o name,segtype,devices
21925 lvr6 raid6 lvr6_rimage_0(0),\\
21926 lvr6_rimage_1(0),\\
21927 lvr6_rimage_2(0),\\
21928 lvr6_rimage_3(0),\\
21929 lvr6_rimage_4(0),\\
21930 lvr6_rimage_5(0)
21931 [lvr6_rimage_0] linear /dev/sda(...)
21932 [lvr6_rimage_1] linear /dev/sdb(...)
21933 [lvr6_rimage_2] linear /dev/sdc(...)
21934 [lvr6_rimage_3] linear /dev/sdd(...)
21935 [lvr6_rimage_4] linear /dev/sde(...)
21936 [lvr6_rimage_5] linear /dev/sdf(...)
21937 [lvr6_rmeta_0] linear /dev/sda(...)
21938 [lvr6_rmeta_1] linear /dev/sdb(...)
21939 [lvr6_rmeta_2] linear /dev/sdc(...)
21940 [lvr6_rmeta_3] linear /dev/sdd(...)
21941 [lvr6_rmeta_4] linear /dev/sde(...)
21942 [lvr6_rmeta_5] linear /dev/sdf(...)
21943
21944.B raid10
21945.br
21946Four rimage SubLVs each hold a portion of LV data. No parity is used.
21947Each rmeta SubLV holds RAID metadata.
21948
21949.nf
21950lvcreate --type raid10 --stripes 2 --mirrors 1 --name lvr10
21951
21952lvs -a -o name,segtype,devices
21953 lvr10 raid10 lvr10_rimage_0(0),\\
21954 lvr10_rimage_1(0),\\
21955 lvr10_rimage_2(0),\\
21956 lvr10_rimage_3(0)
21957 [lvr10_rimage_0] linear /dev/sda(...)
21958 [lvr10_rimage_1] linear /dev/sdb(...)
21959 [lvr10_rimage_2] linear /dev/sdc(...)
21960 [lvr10_rimage_3] linear /dev/sdd(...)
21961 [lvr10_rmeta_0] linear /dev/sda(...)
21962 [lvr10_rmeta_1] linear /dev/sdb(...)
21963 [lvr10_rmeta_2] linear /dev/sdc(...)
21964 [lvr10_rmeta_3] linear /dev/sdd(...)
21965.fi
21966
21967
21968.SH Device Failure
21969
21970Physical devices in a RAID LV can fail or be lost for multiple reasons.
21971A device could be disconnected, permanently failed, or temporarily
21972disconnected. The purpose of RAID LVs (levels 1 and higher) is to
21973continue operating in a degraded mode, without losing LV data, even after
21974a device fails. The number of devices that can fail without the loss of
21975LV data depends on the RAID level:
21976
21977.IP \[bu] 3
21978RAID0 (striped) LVs cannot tolerate losing any devices. LV data will be
21979lost if any devices fail.
21980
21981.IP \[bu] 3
21982RAID1 LVs can tolerate losing all but one device without LV data loss.
21983
21984.IP \[bu] 3
21985RAID4 and RAID5 LVs can tolerate losing one device without LV data loss.
21986
21987.IP \[bu] 3
21988RAID6 LVs can tolerate losing two devices without LV data loss.
21989
21990.IP \[bu] 3
21991RAID10 is variable, and depends on which devices are lost. It can
21992tolerate losing all but one device in a single raid1 mirror without
21993LV data loss.
21994
21995.P
21996
21997If a RAID LV is missing devices, or has other device-related problems, lvs
21998reports this in the health_status (and attr) fields:
21999
22000.B lvs -o name,lv_health_status
22001
22002.B partial
22003.br
22004Devices are missing from the LV. This is also indicated by the letter "p"
22005(partial) in the 9th position of the lvs attr field.
22006
22007.B refresh needed
22008.br
22009A device was temporarily missing but has returned. The LV needs to be
22010refreshed to use the device again (which will usually require
22011partial synchronization). This is also indicated by the letter "r" (refresh
22012needed) in the 9th position of the lvs attr field. See
22013\fBRefreshing an LV\fP. This could also indicate a problem with the
22014device, in which case it should be be replaced, see
22015\fBReplacing Devices\fP.
22016
22017.B mismatches exist
22018.br
22019See
22020.BR Scrubbing .
22021
22022Most commands will also print a warning if a device is missing, e.g.
22023.br
22024.nf
22025WARNING: Device for PV uItL3Z-wBME-DQy0-... not found or rejected ...
22026.fi
22027
22028This warning will go away if the device returns or is removed from the
22029VG (see \fBvgreduce \-\-removemissing\fP).
22030
22031
22032.SS Activating an LV with missing devices
22033
22034A RAID LV that is missing devices may be activated or not, depending on
22035the "activation mode" used in lvchange:
22036
22037.B lvchange \-ay \-\-activationmode
22038.RB { complete | degraded | partial }
22039.IR VG / LV
22040
22041.B complete
22042.br
22043The LV is only activated if all devices are present.
22044
22045.B degraded
22046.br
22047The LV is activated with missing devices if the RAID level can
22048tolerate the number of missing devices without LV data loss.
22049
22050.B partial
22051.br
22052The LV is always activated, even if portions of the LV data are missing
22053because of the missing device(s). This should only be used to perform
22054recovery or repair operations.
22055
22056.BR lvm.conf (5)
22057.B activation/activation_mode
22058.br
22059controls the activation mode when not specified by the command.
22060
22061The default value is printed by:
22062.nf
22063lvmconfig --type default activation/activation_mode
22064.fi
22065
22066.SS Replacing Devices
22067
22068Devices in a RAID LV can be replaced with other devices in the VG. When
22069replacing devices that are no longer visible on the system, use lvconvert
22070\-\-repair. When replacing devices that are still visible, use lvconvert
22071\-\-replace. The repair command will attempt to restore the same number
22072of data LVs that were previously in the LV. The replace option can be
22073repeated to replace multiple PVs. Replacement devices can be optionally
22074listed with either option.
22075
22076.B lvconvert \-\-repair
22077.IR VG / LV
22078[\fINewPVs\fP]
22079
22080.B lvconvert \-\-replace
22081\fIOldPV\fP
22082.IR VG / LV
22083[\fINewPV\fP]
22084
22085.B lvconvert
22086.B \-\-replace
22087\fIOldPV1\fP
22088.B \-\-replace
22089\fIOldPV2\fP
22090...
22091.IR VG / LV
22092[\fINewPVs\fP]
22093
22094New devices require synchronization with existing devices, see
22095.BR Synchronization .
22096
22097.SS Refreshing an LV
22098
22099Refreshing a RAID LV clears any transient device failures (device was
22100temporarily disconnected) and returns the LV to its fully redundant mode.
22101Restoring a device will usually require at least partial synchronization
22102(see \fBSynchronization\fP). Failure to clear a transient failure results
22103in the RAID LV operating in degraded mode until it is reactivated. Use
22104the lvchange command to refresh an LV:
22105
22106.B lvchange \-\-refresh
22107.IR VG / LV
22108
22109.nf
22110# lvs -o name,vgname,segtype,attr,size vg
22111 LV VG Type Attr LSize
22112 raid1 vg raid1 Rwi-a-r-r- 100.00g
22113
22114# lvchange --refresh vg/raid1
22115
22116# lvs -o name,vgname,segtype,attr,size vg
22117 LV VG Type Attr LSize
22118 raid1 vg raid1 Rwi-a-r--- 100.00g
22119.fi
22120
22121.SS Automatic repair
22122
22123If a device in a RAID LV fails, device-mapper in the kernel notifies the
22124.BR dmeventd (8)
22125monitoring process (see \fBMonitoring\fP).
22126dmeventd can be configured to automatically respond using:
22127
22128.BR lvm.conf (5)
22129.B activation/raid_fault_policy
22130
22131Possible settings are:
22132
22133.B warn
22134.br
22135A warning is added to the system log indicating that a device has
22136failed in the RAID LV. It is left to the user to repair the LV, e.g.
22137replace failed devices.
22138
22139.B allocate
22140.br
22141dmeventd automatically attempts to repair the LV using spare devices
22142in the VG. Note that even a transient failure is handled as a permanent
22143failure; a new device is allocated and full synchronization is started.
22144
22145The specific command run by dmeventd to warn or repair is:
22146.br
22147.B lvconvert \-\-repair \-\-use\-policies
22148.IR VG / LV
22149
22150
22151.SS Corrupted Data
22152
22153Data on a device can be corrupted due to hardware errors, without the
22154device ever being disconnected, and without any fault in the software.
22155This should be rare, and can be detected (see \fBScrubbing\fP).
22156
22157
22158.SS Rebuild specific PVs
22159
22160If specific PVs in a RAID LV are known to have corrupt data, the data on
22161those PVs can be reconstructed with:
22162
22163.B lvchange \-\-rebuild PV
22164.IR VG / LV
22165
22166The rebuild option can be repeated with different PVs to replace the data
22167on multiple PVs.
22168
22169
22170.SH Monitoring
22171
22172When a RAID LV is activated the \fBdmeventd\fP(8) process is started to
22173monitor the health of the LV. Various events detected in the kernel can
22174cause a notification to be sent from device-mapper to the monitoring
22175process, including device failures and synchronization completion (e.g.
22176for initialization or scrubbing).
22177
22178The LVM configuration file contains options that affect how the monitoring
22179process will respond to failure events (e.g. raid_fault_policy). It is
22180possible to turn on and off monitoring with lvchange, but it is not
22181recommended to turn this off unless you have a thorough knowledge of the
22182consequences.
22183
22184
22185.SH Configuration Options
22186
22187There are a number of options in the LVM configuration file that affect
22188the behavior of RAID LVs. The tunable options are listed
22189below. A detailed description of each can be found in the LVM
22190configuration file itself.
22191.br
22192 mirror_segtype_default
22193.br
22194 raid10_segtype_default
22195.br
22196 raid_region_size
22197.br
22198 raid_fault_policy
22199.br
22200 activation_mode
22201
22202
22203.SH RAID1 Tuning
22204
22205A RAID1 LV can be tuned so that certain devices are avoided for reading
22206while all devices are still written to.
22207
22208.B lvchange
22209.BR \-\- [ raid ] writemostly
22210.BR \fIPhysicalVolume [ : { y | n | t }]
22211.IR VG / LV
22212
22213The specified device will be marked as "write mostly", which means that
22214reading from this device will be avoided, and other devices will be
22215preferred for reading (unless no other devices are available.) This
22216minimizes the I/O to the specified device.
22217
22218If the PV name has no suffix, the write mostly attribute is set. If the
22219PV name has the suffix \fB:n\fP, the write mostly attribute is cleared,
22220and the suffix \fB:t\fP toggles the current setting.
22221
22222The write mostly option can be repeated on the command line to change
22223multiple devices at once.
22224
22225To report the current write mostly setting, the lvs attr field will show
22226the letter "w" in the 9th position when write mostly is set:
22227
22228.B lvs -a -o name,attr
22229
22230When a device is marked write mostly, the maximum number of outstanding
22231writes to that device can be configured. Once the maximum is reached,
22232further writes become synchronous. When synchronous, a write to the LV
22233will not complete until writes to all the mirror images are complete.
22234
22235.B lvchange
22236.BR \-\- [ raid ] writebehind
22237.IR IOCount
22238.IR VG / LV
22239
22240To report the current write behind setting, run:
22241
22242.B lvs -o name,raid_write_behind
22243
22244When write behind is not configured, or set to 0, all LV writes are
22245synchronous.
22246
22247
22248.SH RAID Takeover
22249
22250RAID takeover is converting a RAID LV from one RAID level to another, e.g.
22251raid5 to raid6. Changing the RAID level is usually done to increase or
22252decrease resilience to device failures. This is done using lvconvert and
22253specifying the new RAID level as the LV type:
22254
22255.B lvconvert --type
22256.I RaidLevel
22257\fIVG\fP/\fILV\fP
22258[\fIPVs\fP]
22259
22260The most common and recommended RAID takeover conversions are:
22261
22262.HP
22263\fBlinear\fP to \fBraid1\fP
22264.br
22265Linear is a single image of LV data, and
22266converting it to raid1 adds a mirror image which is a direct copy of the
22267original linear image.
22268
22269.HP
22270\fBstriped\fP/\fBraid0\fP to \fBraid4/5/6\fP
22271.br
22272Adding parity devices to a
22273striped volume results in raid4/5/6.
22274
22275.P
22276
22277Unnatural conversions that are not recommended include converting between
22278striped and non-striped types. This is because file systems often
22279optimize I/O patterns based on device striping values. If those values
22280change, it can decrease performance.
22281
22282Converting to a higher RAID level requires allocating new SubLVs to hold
22283RAID metadata, and new SubLVs to hold parity blocks for LV data.
22284Converting to a lower RAID level removes the SubLVs that are no longer
22285needed.
22286
22287Conversion often requires full synchronization of the RAID LV (see
22288\fBSynchronization\fP). Converting to RAID1 requires copying all LV data
22289blocks to a new image on a new device. Converting to a parity RAID level
22290requires reading all LV data blocks, calculating parity, and writing the
22291new parity blocks. Synchronization can take a long time and degrade
22292performance (rate controls also apply to conversion, see
22293\fB\-\-maxrecoveryrate\fP.)
22294
22295.P
22296
22297The following takeover conversions are currently possible:
22298.br
22299.IP \(bu 3
22300between linear and raid1.
22301.IP \(bu 3
22302between striped and raid4.
22303
22304.SS Examples
22305
223061. Converting an LV from \fBlinear\fP to \fBraid1\fP.
22307
22308.nf
22309# lvs -a -o name,segtype,size vg
22310 LV Type LSize
22311 lv linear 300.00g
22312
22313# lvconvert --type raid1 --mirrors 1 vg/lv
22314
22315# lvs -a -o name,segtype,size vg
22316 LV Type LSize
22317 lv raid1 300.00g
22318 [lv_rimage_0] linear 300.00g
22319 [lv_rimage_1] linear 300.00g
22320 [lv_rmeta_0] linear 3.00m
22321 [lv_rmeta_1] linear 3.00m
22322.fi
22323
223242. Converting an LV from \fBmirror\fP to \fBraid1\fP.
22325
22326.nf
22327# lvs -a -o name,segtype,size vg
22328 LV Type LSize
22329 lv mirror 100.00g
22330 [lv_mimage_0] linear 100.00g
22331 [lv_mimage_1] linear 100.00g
22332 [lv_mlog] linear 3.00m
22333
22334# lvconvert --type raid1 vg/lv
22335
22336# lvs -a -o name,segtype,size vg
22337 LV Type LSize
22338 lv raid1 100.00g
22339 [lv_rimage_0] linear 100.00g
22340 [lv_rimage_1] linear 100.00g
22341 [lv_rmeta_0] linear 3.00m
22342 [lv_rmeta_1] linear 3.00m
22343.fi
22344
223453. Converting an LV from \fBlinear\fP to \fBraid1\fP (with 3 images).
22346
22347.nf
22348Start with a linear LV:
22349
22350# lvcreate -L1G -n my_lv vg
22351
22352Convert the linear LV to raid1 with three images
22353(original linear image plus 2 mirror images):
22354
22355# lvconvert --type raid1 --mirrors 2 vg/my_lv
22356.fi
22357
22358.ig
223594. Converting an LV from \fBstriped\fP (with 4 stripes) to \fBraid6_nc\fP.
22360
22361.nf
22362Start with a striped LV:
22363
22364# lvcreate --stripes 4 -L64M -n my_lv vg
22365
22366Convert the striped LV to raid6_nc:
22367
22368# lvconvert --type raid6_nc vg/my_lv
22369
22370# lvs -a -o lv_name,segtype,sync_percent,data_copies
22371 LV Type Cpy%Sync #Cpy
22372 my_lv raid6_n_6 100.00 3
22373 [my_lv_rimage_0] linear
22374 [my_lv_rimage_1] linear
22375 [my_lv_rimage_2] linear
22376 [my_lv_rimage_3] linear
22377 [my_lv_rimage_4] linear
22378 [my_lv_rimage_5] linear
22379 [my_lv_rmeta_0] linear
22380 [my_lv_rmeta_1] linear
22381 [my_lv_rmeta_2] linear
22382 [my_lv_rmeta_3] linear
22383 [my_lv_rmeta_4] linear
22384 [my_lv_rmeta_5] linear
22385.fi
22386
22387This convert begins by allocating MetaLVs (rmeta_#) for each of the
22388existing stripe devices. It then creates 2 additional MetaLV/DataLV pairs
22389(rmeta_#/rimage_#) for dedicated raid6 parity.
22390
22391If rotating data/parity is required, such as with raid6_nr, it must be
22392done by reshaping (see below).
22393..
22394
22395
22396.SH RAID Reshaping
22397
22398RAID reshaping is changing attributes of a RAID LV while keeping the same
22399RAID level, i.e. changes that do not involve changing the number of
22400devices. This includes changing RAID layout, stripe size, or number of
22401stripes.
22402
22403When changing the RAID layout or stripe size, no new SubLVs (MetaLVs or
22404DataLVs) need to be allocated, but DataLVs are extended by a small amount
22405(typically 1 extent). The extra space allows blocks in a stripe to be
22406updated safely, and not corrupted in case of a crash. If a crash occurs,
22407reshaping can just be restarted.
22408
22409(If blocks in a stripe were updated in place, a crash could leave them
22410partially updated and corrupted. Instead, an existing stripe is quiesced,
22411read, changed in layout, and the new stripe written to free space. Once
22412that is done, the new stripe is unquiesced and used.)
22413
22414(The reshaping features are planned for a future release.)
22415
22416.ig
22417.SS Examples
22418
224191. Converting raid6_n_6 to raid6_nr with rotating data/parity.
22420
22421This conversion naturally follows a previous conversion from striped to
22422raid6_n_6 (shown above). It completes the transition to a more
22423traditional RAID6.
22424
22425.nf
22426# lvs -o lv_name,segtype,sync_percent,data_copies
22427 LV Type Cpy%Sync #Cpy
22428 my_lv raid6_n_6 100.00 3
22429 [my_lv_rimage_0] linear
22430 [my_lv_rimage_1] linear
22431 [my_lv_rimage_2] linear
22432 [my_lv_rimage_3] linear
22433 [my_lv_rimage_4] linear
22434 [my_lv_rimage_5] linear
22435 [my_lv_rmeta_0] linear
22436 [my_lv_rmeta_1] linear
22437 [my_lv_rmeta_2] linear
22438 [my_lv_rmeta_3] linear
22439 [my_lv_rmeta_4] linear
22440 [my_lv_rmeta_5] linear
22441
22442# lvconvert --type raid6_nr vg/my_lv
22443
22444# lvs -a -o lv_name,segtype,sync_percent,data_copies
22445 LV Type Cpy%Sync #Cpy
22446 my_lv raid6_nr 100.00 3
22447 [my_lv_rimage_0] linear
22448 [my_lv_rimage_0] linear
22449 [my_lv_rimage_1] linear
22450 [my_lv_rimage_1] linear
22451 [my_lv_rimage_2] linear
22452 [my_lv_rimage_2] linear
22453 [my_lv_rimage_3] linear
22454 [my_lv_rimage_3] linear
22455 [my_lv_rimage_4] linear
22456 [my_lv_rimage_5] linear
22457 [my_lv_rmeta_0] linear
22458 [my_lv_rmeta_1] linear
22459 [my_lv_rmeta_2] linear
22460 [my_lv_rmeta_3] linear
22461 [my_lv_rmeta_4] linear
22462 [my_lv_rmeta_5] linear
22463.fi
22464
22465The DataLVs are larger (additional segment in each) which provides space
22466for out-of-place reshaping. The result is:
22467
22468FIXME: did the lv name change from my_lv to r?
22469.br
22470FIXME: should we change device names in the example to sda,sdb,sdc?
22471.br
22472FIXME: include -o devices or seg_pe_ranges above also?
22473
22474.nf
22475# lvs -a -o lv_name,segtype,seg_pe_ranges,dataoffset
22476 LV Type PE Ranges data
22477 r raid6_nr r_rimage_0:0-32 \\
22478 r_rimage_1:0-32 \\
22479 r_rimage_2:0-32 \\
22480 r_rimage_3:0-32
22481 [r_rimage_0] linear /dev/sda:0-31 2048
22482 [r_rimage_0] linear /dev/sda:33-33
22483 [r_rimage_1] linear /dev/sdaa:0-31 2048
22484 [r_rimage_1] linear /dev/sdaa:33-33
22485 [r_rimage_2] linear /dev/sdab:1-33 2048
22486 [r_rimage_3] linear /dev/sdac:1-33 2048
22487 [r_rmeta_0] linear /dev/sda:32-32
22488 [r_rmeta_1] linear /dev/sdaa:32-32
22489 [r_rmeta_2] linear /dev/sdab:0-0
22490 [r_rmeta_3] linear /dev/sdac:0-0
22491.fi
22492
22493All segments with PE ranges '33-33' provide the out-of-place reshape space.
22494The dataoffset column shows that the data was moved from initial offset 0 to
224952048 sectors on each component DataLV.
22496..
22497
22498.SH RAID5 Variants
22499
22500raid5_ls
22501.br
22502\[bu]
22503RAID5 left symmetric
22504.br
22505\[bu]
22506Rotating parity N with data restart
22507
22508raid5_la
22509.br
22510\[bu]
22511RAID5 left symmetric
22512.br
22513\[bu]
22514Rotating parity N with data continuation
22515
22516raid5_rs
22517.br
22518\[bu]
22519RAID5 right symmetric
22520.br
22521\[bu]
22522Rotating parity 0 with data restart
22523
22524raid5_ra
22525.br
22526\[bu]
22527RAID5 right asymmetric
22528.br
22529\[bu]
22530Rotating parity 0 with data continuation
22531
22532.ig
22533raid5_n
22534.br
22535\[bu]
22536RAID5 striping
22537.br
22538\[bu]
22539Same layout as raid4 with a dedicated parity N with striped data.
22540.br
22541\[bu]
22542Used for
22543.B RAID Takeover
22544..
22545
22546.SH RAID6 Variants
22547
22548raid6
22549.br
22550\[bu]
22551RAID6 zero restart (aka left symmetric)
22552.br
22553\[bu]
22554Rotating parity 0 with data restart
22555.br
22556\[bu]
22557Same as raid6_zr
22558
22559raid6_zr
22560.br
22561\[bu]
22562RAID6 zero restart (aka left symmetric)
22563.br
22564\[bu]
22565Rotating parity 0 with data restart
22566
22567raid6_nr
22568.br
22569\[bu]
22570RAID6 N restart (aka right symmetric)
22571.br
22572\[bu]
22573Rotating parity N with data restart
22574
22575raid6_nc
22576.br
22577\[bu]
22578RAID6 N continue
22579.br
22580\[bu]
22581Rotating parity N with data continuation
22582
22583.ig
22584raid6_n_6
22585.br
22586\[bu]
22587RAID6 N continue
22588.br
22589\[bu]
22590Fixed P-Syndrome N-1 and Q-Syndrome N with striped data
22591.br
22592\[bu]
22593Used for
22594.B RAID Takeover
22595
22596raid6_ls_6
22597.br
22598\[bu]
22599RAID6 N continue
22600.br
22601\[bu]
22602Same as raid5_ls for N-1 disks with fixed Q-Syndrome N
22603.br
22604\[bu]
22605Used for
22606.B RAID Takeover
22607
22608raid6_la_6
22609.br
22610\[bu]
22611RAID6 N continue
22612.br
22613\[bu]
22614Same as raid5_la for N-1 disks with fixed Q-Syndrome N
22615.br
22616\[bu]
22617Used for
22618.B RAID Takeover
22619
22620raid6_rs_6
22621.br
22622\[bu]
22623RAID6 N continue
22624.br
22625\[bu]
22626Same as raid5_rs for N-1 disks with fixed Q-Syndrome N
22627.br
22628\[bu]
22629Used for
22630.B RAID Takeover
22631
22632raid6_ra_6
22633.br
22634\[bu]
22635RAID6 N continue
22636.br
22637\[bu]
22638Same as raid5_ra for N-1 disks with fixed Q-Syndrome N
22639.br
22640\[bu]
22641Used for
22642.B RAID Takeover
22643..
22644
22645
22646.ig
22647.SH RAID Duplication
22648
22649RAID LV conversion (takeover or reshaping) can be done out\-of\-place by
22650copying the LV data onto new devices while changing the RAID properties.
22651Copying avoids modifying the original LV but requires additional devices.
22652Once the LV data has been copied/converted onto the new devices, there are
22653multiple options:
22654
226551. The RAID LV can be switched over to run from just the new devices, and
22656the original copy of the data removed. The converted LV then has the new
22657RAID properties, and exists on new devices. The old devices holding the
22658original data can be removed or reused.
22659
226602. The new copy of the data can be dropped, leaving the original RAID LV
22661unchanged and using its original devices.
22662
226633. The new copy of the data can be separated and used as a new independent
22664LV, leaving the original RAID LV unchanged on its original devices.
22665
22666The command to start duplication is:
22667
22668.B lvconvert \-\-type
22669.I RaidLevel
22670[\fB\-\-stripes\fP \fINumber\fP \fB\-\-stripesize\fP \fISize\fP]
22671.RS
22672.B \-\-duplicate
22673.IR VG / LV
22674[\fIPVs\fP]
22675.RE
22676
22677.HP
22678.B \-\-duplicate
22679.br
22680Specifies that the LV conversion should be done out\-of\-place, copying
22681LV data to new devices while converting.
22682
22683.HP
22684.BR \-\-type , \-\-stripes , \-\-stripesize
22685.br
22686Specifies the RAID properties to use when creating the copy.
22687
22688.P
22689\fIPVs\fP specifies the new devices to use.
22690
22691The steps in the duplication process:
22692
22693.IP \(bu 3
22694LVM creates a new LV on new devices using the specified RAID properties
22695(type, stripes, etc) and optionally specified devices.
22696
22697.IP \(bu 3
22698LVM changes the visible RAID LV to type raid1, making the original LV the
22699first raid1 image (SubLV 0), and the new LV the second raid1 image
22700(SubLV 1).
22701
22702.IP \(bu 3
22703The RAID1 synchronization process copies data from the original LV
22704image (SubLV 0) to the new LV image (SubLV 1).
22705
22706.IP \(bu 3
22707When synchronization is complete, the original and new LVs are
22708mirror images of each other and can be separated.
22709
22710.P
22711
22712The duplication process retains both the original and new LVs (both
22713SubLVs) until an explicit unduplicate command is run to separate them. The
22714unduplicate command specifies if the original LV should use the old
22715devices (SubLV 0) or the new devices (SubLV 1).
22716
22717To make the RAID LV use the data on the old devices, and drop the copy on
22718the new devices, specify the name of SubLV 0 (suffix _dup_0):
22719
22720.B lvconvert \-\-unduplicate
22721.BI \-\-name
22722.IB LV _dup_0
22723.IR VG / LV
22724
22725To make the RAID LV use the data copy on the new devices, and drop the old
22726devices, specify the name of SubLV 1 (suffix _dup_1):
22727
22728.B lvconvert \-\-unduplicate
22729.BI \-\-name
22730.IB LV _dup_1
22731.IR VG / LV
22732
22733FIXME: To make the LV use the data on the original devices, but keep the
22734data copy as a new LV, ...
22735
22736FIXME: include how splitmirrors can be used.
22737
22738
22739.SH RAID1E
22740
22741TODO
22742..
22743
22744.SH History
22745
22746The 2.6.38-rc1 version of the Linux kernel introduced a device-mapper
22747target to interface with the software RAID (MD) personalities. This
22748provided device-mapper with RAID 4/5/6 capabilities and a larger
22749development community. Later, support for RAID1, RAID10, and RAID1E (RAID
2275010 variants) were added. Support for these new kernel RAID targets was
22751added to LVM version 2.02.87. The capabilities of the LVM \fBraid1\fP
22752type have surpassed the old \fBmirror\fP type. raid1 is now recommended
22753instead of mirror. raid1 became the default for mirroring in LVM version
227542.02.100.
22755
22756\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgrename.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003152\013062740170\0020125\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGRENAME 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
22757.SH NAME
22758vgrename \(em rename a volume group
22759.SH SYNOPSIS
22760.B vgrename
22761.RB [ \-A | \-\-autobackup
22762.RI { y | n }]
22763.RB [ \-\-commandprofile
22764.IR ProfileName ]
22765.RB [ \-d | \-\-debug ]
22766.RB [ \-h | \-? | \-\-help ]
22767.RB [ \-\-reportformat
22768.RB { basic | json }]
22769.RB [ \-t | \-\-test ]
22770.RB [ \-v | \-\-verbose ]
22771.IR OldVolumeGroup { Path | Name | UUID }
22772.IR NewVolumeGroup { Path | Name }
22773.SH DESCRIPTION
22774vgrename renames an existing (see
22775.BR vgcreate (8))
22776volume group from
22777.IR OldVolumeGroup { Name | Path | UUID }
22778to
22779.IR NewVolumeGroup { Name | Path }.
22780
22781All the Volume Groups visible to a system need to have different
22782names. Otherwise many LVM2 commands will refuse to run or give
22783warning messages.
22784
22785This situation could arise when disks are moved between machines. If
22786a disk is connected and it contains a Volume Group with the same name
22787as the Volume Group containing your root filesystem the machine might
22788not even boot correctly. However, the two Volume Groups should have
22789different UUIDs (unless the disk was cloned) so you can rename
22790one of the conflicting Volume Groups with
22791\fBvgrename\fP.
22792.SH OPTIONS
22793See \fBlvm\fP(8) for common options.
22794.SH Examples
22795Renames existing volume group vg02 to my_volume_group:
22796.sp
22797.B vgrename /dev/vg02 /dev/my_volume_group
22798
22799or
22800.sp
22801.B vgrename vg02 my_volume_group
22802
22803Changes the name of the Volume Group with UUID
22804.br
22805Zvlifi-Ep3t-e0Ng-U42h-o0ye-KHu1-nl7Ns4 to VolGroup00_tmp:
22806.sp
22807.B vgrename Zvlifi\-Ep3t\-e0Ng\-U42h\-o0ye\-KHu1\-nl7Ns4 VolGroup00_tmp
22808
22809.SH SEE ALSO
22810.BR lvm (8),
22811.BR vgchange (8),
22812.BR vgcreate (8),
22813.BR lvrename (8)
22814\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvdisplay.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005353\013062740170\0020341\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
22815.SH NAME
22816pvdisplay \- display attributes of a physical volume
22817.SH SYNOPSIS
22818.B pvdisplay
22819.RB [ \-c | \-\-colon ]
22820.RB [ \-\-commandprofile
22821.IR ProfileName ]
22822.RB [ \-d | \-\-debug ]
22823.RB [ \-h | \-? | \-\-help ]
22824.RB [ \-\-ignorelockingfailure ]
22825.RB [ \-\-ignoreskippedcluster ]
22826.RB [ \-\-maps ]
22827.RB [ \-\-nosuffix ]
22828.RB [ \-\-reportformat
22829.RB { basic | json }]
22830.RB [ \-s | \-\-short ]
22831.RB [ \-S | \-\-select
22832.IR Selection ]
22833.RB [ \-\-units
22834.IR hsbkmgtHKMGT ]
22835.RB [ \-v [ v ]| \-\-verbose
22836.RB [ \-\-verbose ]]
22837.RB [ \-\-version ]
22838.RI [ PhysicalVolumePath ...]
22839.br
22840
22841.br
22842.B pvdisplay
22843.BR \-C | \-\-columns
22844.RB [ \-\-aligned ]
22845.RB [ \-\-binary ]
22846.RB [ \-a | \-\-all ]
22847.RB [ \-\-commandprofile
22848.RB [[ \-\-configreport
22849.IR ReportName ]
22850.RB [ \-o | \-\-options
22851.RI [ + | \- | # ] Field1 [, Field2 ...]
22852.RB [ \-O | \-\-sort
22853.RI [ + | \- ] Key1 [, Key2 ...]]
22854.RB [ \-S | \-\-select
22855.IR Selection ]
22856.RB ...]
22857.IR ProfileName ]
22858.RB [ \-d | \-\-debug ]
22859.RB [ \-h | \-? | \-\-help ]
22860.RB [ \-\-ignorelockingfailure ]
22861.RB [ \-\-logonly ]
22862.RB [ \-\-noheadings ]
22863.RB [ \-\-nosuffix ]
22864.RB [ \-\-reportformat
22865.RB { basic | json }]
22866.RB [ \-\-separator
22867.IR Separator ]
22868.RB [ \-\-unbuffered ]
22869.RB [ \-\-units
22870.IR hHbBsSkKmMgGtTpPeE ]
22871.RB [ \-v [ v ]| \-\-verbose
22872.RB [ \-\-verbose ]]
22873.RB [ \-\-version ]
22874.RI [ PhysicalVolumePath ...]
22875.SH DESCRIPTION
22876pvdisplay allows you to see the attributes of one or more physical volumes
22877like size, physical extent size, space used for the volume group descriptor
22878area and so on.
22879.P
22880\fBpvs\fP(8) is an alternative that provides the same information
22881in the style of \fBps\fP(1).
22882.SH OPTIONS
22883See \fBlvm\fP(8) for common options.
22884.TP
22885.BR \-C ", " \-\-columns
22886Display output in columns, the equivalent of \fBpvs\fP(8). See
22887\fBpvs\fP(8) for a description of other options with this form of
22888\fBpvdisplay\fP.
22889.TP
22890.BR \-c ", " \-\-colon
22891Generate colon separated output for easier parsing in scripts or programs.
22892N.B. \fBpvs\fP(8) provides considerably more control over the output.
22893.nf
22894
22895The values are:
22896
22897\(bu physical volume device name
22898\(bu volume group name
22899\(bu physical volume size in sectors
22900\(bu internal physical volume number (obsolete)
22901\(bu physical volume status
22902\(bu physical volume (not) allocatable
22903\(bu current number of logical volumes on this physical volume
22904\(bu physical extent size in kilobytes
22905\(bu total number of physical extents
22906\(bu free number of physical extents
22907\(bu allocated number of physical extents
22908
22909.fi
22910.TP
22911.BR \-s ", " \-\-short
22912Only display the size of the given physical volumes.
22913.TP
22914.BR \-m ", " \-\-maps
22915Display the mapping of physical extents to logical volumes and
22916logical extents.
22917.SH SEE ALSO
22918.BR lvm (8),
22919.BR pvs (8),
22920.BR pvcreate (8),
22921.BR lvcreate (8),
22922.BR vgcreate (8)
22923\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvchange.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003161\013062740170\0020114\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
22924.SH NAME
22925pvchange \(em change attributes of a physical volume
22926.SH SYNOPSIS
22927.B pvchange
22928.RB [ \-\-addtag
22929.IR Tag ]
22930.RB [ \-A | \-\-autobackup
22931.RI { y | n }]
22932.RB [ \-\-commandprofile
22933.IR ProfileName ]
22934.RB [ \-d | \-\-debug ]
22935.RB [ \-f | \-\-force ]
22936.RB [ \-\-deltag
22937.IR Tag ]
22938.RB [ \-\-metadataignore
22939.RI { y | n }]
22940.RB [ \-h | \-? | \-\-help ]
22941.RB [ \-\-reportformat
22942.RB { basic | json }]
22943.RB [ \-S | \-\-select
22944.IR Selection ]
22945.RB [ \-t | \-\-test ]
22946.RB [ \-v | \-\-verbose ]
22947.RB [ \-a | \-\-all ]
22948.RB [ \-x | \-\-allocatable
22949.RI { y | n }]
22950.RB [ \-u | \-\-uuid ]
22951.RI [ PhysicalVolumePath ...]
22952.SH DESCRIPTION
22953pvchange allows you to change the allocation permissions of one or
22954more physical volumes.
22955.SH OPTIONS
22956See \fBlvm\fP(8) for common options.
22957.TP
22958.BR \-a ", " \-\-all
22959If PhysicalVolumePath is not specified on the command line all
22960physical volumes are searched for and used.
22961.TP
22962.BR \-\-metadataignore " {" \fIy | \fIn }
22963Ignore or un-ignore metadata areas on this physical volume.
22964If metadata areas on a physical volume are ignored, LVM will
22965not not store metadata in the metadata areas present on this Physical
22966Volume.
22967.TP
22968.BR \-u ", " \-\-uuid
22969Generate new random UUID for specified physical volumes.
22970.TP
22971.BR \-x ", " \-\-allocatable " {" \fIy | \fIn }
22972Enable or disable allocation of physical extents on this physical volume.
22973.SH Example
22974Disallows the allocation of physical extents on this physical volume
22975(possibly because of disk errors, or because it will be removed after
22976freeing it:
22977.sp
22978.B pvchange \-x n /dev/sdk1
22979.SH SEE ALSO
22980.BR lvm (8),
22981.BR pvcreate (8)
22982\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvcreate.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000017715\013062740170\0020144\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
22983.SH NAME
22984pvcreate \(em initialize a disk or partition for use by LVM
22985.SH SYNOPSIS
22986.B pvcreate
22987.RB [ \-\-commandprofile
22988.IR ProfileName ]
22989.RB [ \-d | \-\-debug ]
22990.RB [ \-h | \-\-help ]
22991.RB [ \-t | \-\-test ]
22992.RB [ \-v | \-\-verbose ]
22993.RB [ \-\-version ]
22994.RB [ \-f [ f ]| \-\-force
22995.RB [ \-\-force ]]
22996.RB [ \-y | \-\-yes ]
22997.RB [ \-\-labelsector ]
22998.RB [ \-\-bootloaderareasize
22999.IR size ]
23000.RB [ \-M | \-\-metadatatype
23001.IR type ]
23002.RB [ \-\- [ pv ] metadatacopies
23003.IR NumberOfCopies ]
23004.RB [ \-\-metadatasize
23005.IR size ]
23006.RB [ \-\-metadataignore
23007.RI { y | n }]
23008.RB [ \-\-dataalignment
23009.IR alignment ]
23010.RB [ \-\-dataalignmentoffset
23011.IR alignment_offset ]
23012.RB [ \-\-restorefile
23013.IR file ]
23014.RB [ \-\-norestorefile ]
23015.RB [ \-\-reportformat
23016.RB { basic | json }]
23017.RB [ \-\-setphysicalvolumesize
23018.IR size ]
23019.RB [ \-u | \-\-uuid
23020.IR uuid ]
23021.RB [ \-Z | \-\-zero
23022.RI { y | n }]
23023.I PhysicalVolume
23024.RI [ PhysicalVolume ...]
23025.SH DESCRIPTION
23026pvcreate initializes
23027.I PhysicalVolume
23028for later use by the Logical Volume Manager (LVM). Each
23029.I PhysicalVolume
23030can be a disk partition, whole disk, meta device, or loopback file.
23031For DOS disk partitions, the partition id should be set to 0x8e using
23032.BR fdisk (8),
23033.BR cfdisk (8),
23034or a equivalent. For GUID Partition Table (GPT), the id is
23035E6D6D379-F507-44C2-A23C-238F2A3DF928. For
23036.B whole disk devices only
23037the partition table must be erased, which will effectively destroy all
23038data on that disk. This can be done by zeroing the first sector with:
23039.sp
23040.BI "dd if=/dev/zero of=" PhysicalVolume " bs=512 count=1"
23041.sp
23042Continue with
23043.BR vgcreate (8)
23044to create a new volume group on
23045.IR PhysicalVolume ,
23046or
23047.BR vgextend (8)
23048to add
23049.I PhysicalVolume
23050to an existing volume group.
23051.SH OPTIONS
23052See \fBlvm\fP(8) for common options.
23053.TP
23054.BR \-f ", " \-\-force
23055Force the creation without any confirmation. You can not recreate
23056(reinitialize) a physical volume belonging to an existing volume group.
23057In an emergency you can override this behaviour with \fB-ff\fP.
23058.TP
23059.BR \-u ", " \-\-uuid " " \fIuuid
23060Specify the uuid for the device.
23061Without this option, \fBpvcreate\fP(8) generates a random uuid.
23062All of your physical volumes must have unique uuids.
23063You need to use this option before restoring a backup of LVM metadata
23064onto a replacement device - see \fBvgcfgrestore\fP(8). As such, use of
23065\fB\-\-restorefile\fP is compulsory unless the \fB\-\-norestorefile\fP is
23066used.
23067.TP
23068.BR \-y ", " \-\-yes
23069Answer yes to all questions.
23070.TP
23071.BR \-Z ", " \-\-zero " {" \fIy | \fIn }
23072Whether or not the first 4 sectors (2048 bytes) of the device should be
23073wiped.
23074If this option is not given, the
23075default is to wipe these sectors unless either or both of the
23076\fB\-\-restorefile\fP or \fB\-\-uuid\fP options were specified.
23077.SH NEW METADATA OPTIONS
23078LVM2 introduces a new format for storing metadata on disk.
23079This new format is more efficient and resilient than the format the
23080original version of LVM used and offers the advanced user greater
23081flexibility and control.
23082.P
23083The new format may be selected on the command line with \fB\-M2\fP or by
23084setting \fBformat = "lvm2"\fP in the \fBglobal\fP section of \fBlvm.conf\fP(5).
23085Each physical volume in the same volume group must use the same format, but
23086different volume groups on a machine may use different formats
23087simultaneously: the tools can handle both formats.
23088Additional formats can be added as shared libraries.
23089.P
23090Additional tools for manipulating the locations and sizes of metadata areas
23091will be written in due course. Use the verbose/debug options on the tools
23092to see where the metadata areas are placed.
23093.TP
23094.B \-\-metadatasize \fIsize
23095The approximate amount of space to be set aside for each metadata area.
23096(The size you specify may get rounded.)
23097.TP
23098.B \-\-dataalignment \fIalignment
23099Align the start of the data to a multiple of this number.
23100You should also specify an appropriate \fIPhysicalExtentSize\fP when creating
23101the Volume Group with \fBvgcreate\fP.
23102.sp
23103To see the location of the first Physical Extent of an existing Physical Volume
23104use \fBpvs \-o +pe_start\fP . It will be a multiple of the requested
23105alignment. In addition it may be shifted by \fIalignment_offset\fP from
23106\fIdata_alignment_offset_detection\fP (if enabled in \fBlvm.conf\fP(5)) or
23107\fB\-\-dataalignmentoffset\fP.
23108.TP
23109.B \-\-dataalignmentoffset \fIalignment_offset
23110Shift the start of the data area by this additional \fIalignment_offset\fP.
23111.TP
23112.BR \-\- [ pv ] metadatacopies " " \fINumberOfCopies
23113The number of metadata areas to set aside on each PV. Currently
23114this can be 0, 1 or 2.
23115If set to 2, two copies of the volume group metadata
23116are held on the PV, one at the front of the PV and one at the end.
23117If set to 1 (the default), one copy is kept at the front of the PV
23118(starting in the 5th sector).
23119If set to 0, no copies are kept on this PV - you might wish to use this
23120with VGs containing large numbers of PVs. But if you do this and
23121then later use \fBvgsplit\fP(8) you must ensure that each VG is still going
23122to have a suitable number of copies of the metadata after the split!
23123.TP
23124.BR \-\-metadataignore " {" \fIy | \fIn }
23125Ignore or un-ignore metadata areas on this physical volume.
23126The default is "n". This setting can be changed with \fBpvchange\fP.
23127If metadata areas on a physical volume are ignored, LVM will
23128not store metadata in the metadata areas present on this Physical
23129Volume. Metadata areas cannot be created or extended after Logical
23130Volumes have been allocated on the device. If you do not want to store
23131metadata on this device, it is still wise always to allocate a metadata
23132area in case you need it in the future and to use this option to instruct
23133LVM2 to ignore it.
23134.TP
23135.B \-\-restorefile \fIfile
23136In conjunction with \fB\-\-uuid\fP, this extracts the location and size
23137of the data on the PV from the file (produced by \fBvgcfgbackup\fP)
23138and ensures that the metadata that the program produces is consistent
23139with the contents of the file i.e. the physical extents will be in
23140the same place and not get overwritten by new metadata. This provides
23141a mechanism to upgrade the metadata format or to add/remove metadata
23142areas. Use with care. See also \fBvgconvert\fP(8).
23143.TP
23144.B \-\-norestorefile
23145In conjunction with \fB\-\-uuid\fP, this allows a \fIuuid\fP to be specified
23146without also requiring that a backup of the metadata be provided.
23147.TP
23148.B \-\-labelsector \fIsector
23149By default the PV is labelled with an LVM2 identifier in its second
23150sector (sector 1). This lets you use a different sector near the
23151start of the disk (between 0 and 3 inclusive - see LABEL_SCAN_SECTORS
23152in the source). Use with care.
23153.TP
23154.B \-\-bootloaderareasize \fIsize
23155Create a separate bootloader area of specified size besides PV's data
23156area. The bootloader area is an area of reserved space on the PV from
23157which LVM2 will not allocate any extents and it's kept untouched. This is
23158primarily aimed for use with bootloaders to embed their own data or metadata.
23159The start of the bootloader area is always aligned, see also \fB\-\-dataalignment\fP
23160and \fB\-\-dataalignmentoffset\fP. The bootloader area size may eventually
23161end up increased due to the alignment, but it's never less than the
23162size that is requested. To see the bootloader area start and size of
23163an existing Physical Volume use \fBpvs \-o +pv_ba_start,pv_ba_size\fP.
23164.TP
23165.B \-\-setphysicalvolumesize \fIsize
23166Overrides the automatically-detected size of the PV. Use with care.
23167.SH Examples
23168Initialize partition #4 on the third SCSI disk and the entire fifth
23169SCSI disk for later use by LVM:
23170.sp
23171.B pvcreate /dev/sdc4 /dev/sde
23172
23173If the 2nd SCSI disk is a 4KiB sector drive that compensates for windows
23174partitioning (sector 7 is the lowest aligned logical block, the 4KiB
23175sectors start at LBA -1, and consequently sector 63 is aligned on a 4KiB
23176boundary) manually account for this when initializing for use by LVM:
23177.sp
23178.B pvcreate \-\-dataalignmentoffset 7s /dev/sdb
23179
23180.SH SEE ALSO
23181.BR lvm.conf (5),
23182.BR lvm (8),
23183.BR vgcreate (8),
23184.BR vgextend (8),
23185.BR lvcreate (8),
23186.BR cfdisk (8),
23187.BR fdisk (8),
23188.BR losetup (8),
23189.BR mdadm (8),
23190.BR vgcfgrestore (8),
23191.BR vgconvert (8)
23192\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/clvmd.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010336\013062740170\0017430\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH CLVMD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
23193.
23194.SH NAME
23195.
23196clvmd \(em cluster LVM daemon
23197.
23198.SH SYNOPSIS
23199.
23200.ad l
23201.B clvmd
23202.RB [ \-C ]
23203.RB [ \-d
23204.RI [ value ]]
23205.RB [ \-E
23206.IR lock_uuid ]
23207.RB [ \-f ]
23208.RB [ \-h ]
23209.RB [ \-I
23210.IR cluster_manager ]
23211.RB [ \-R ]
23212.RB [ \-S ]
23213.RB [ \-t
23214.IR timeout ]
23215.RB [ \-T
23216.IR start_timeout ]
23217.RB [ \-V ]
23218.ad b
23219.
23220.SH DESCRIPTION
23221.
23222clvmd is the daemon that distributes LVM metadata updates around a cluster.
23223It must be running on all nodes in the cluster and will give an error
23224if a node in the cluster does not have this daemon running.
23225.
23226.SH OPTIONS
23227.
23228.HP
23229.BR \-C
23230.br
23231Only valid if \fB\-d\fP is also specified.
23232Tells all clvmds in a cluster to enable/disable debug logging.
23233Without this switch, only the local clvmd will change its debug level to that
23234given with \fB\-d\fP.
23235.br
23236This does not work correctly if specified on the command-line that starts clvmd.
23237If you want to start clvmd \fBand\fP
23238enable cluster-wide logging then the command needs to be issued twice, eg:
23239.br
23240.BR clvmd
23241.br
23242.BR clvmd\ \-d2
23243.
23244.HP
23245.BR \-d
23246.RI [ value ]
23247.br
23248Set debug logging level.
23249If \fB\-d\fP is specified without a \fIvalue\fP
23250then 1 is assumed. \fIValue\fP can be:
23251.PD 0
23252.IP
23253.BR 0
23254\(em Disabled
23255.IP
23256.BR 1
23257\(em Sends debug logs to stderr (implies \fB\-f\fP)
23258.IP
23259.BR 2
23260\(em Sends debug logs to \fBsyslog\fP(3)
23261.PD
23262.
23263.HP
23264.BR \-E
23265.IR lock_uuid
23266.br
23267Pass lock uuid to be reacquired exclusively when clvmd is restarted.
23268.
23269.HP
23270.BR \-f
23271.br
23272Don't fork, run in the foreground.
23273.
23274.HP
23275.BR \-h
23276.br
23277Show help information.
23278.
23279.HP
23280.BR \-I
23281.IR cluster_manager
23282.br
23283Selects the cluster manager to use for locking and internal
23284communications. As it is quite possible to have multiple managers available on
23285the same system you might have to manually specify this option to override the
23286search.
23287
23288By default, omit \fB-I\fP is equivalent to \fB\-Iauto\fP.
23289Clvmd will use the first cluster manager that succeeds,
23290and it checks them in a predefined order
23291.BR cman ,
23292.BR corosync ,
23293.BR openais .
23294The available managers will be listed by order as part of the
23295\fBclvmd \-h\fP output.
23296.
23297.HP
23298.BR \-R
23299.br
23300Tells all the running instance of \fBclvmd\fP in the cluster to reload their device cache and
23301re-read the lvm configuration file \fBlvm.conf\fP(5). This command should be run whenever the
23302devices on a cluster system are changed.
23303.
23304.HP
23305.BR \-S
23306.br
23307Tells the running \fBclvmd\fP to exit and reexecute itself, for example at the
23308end of a package upgrade. The new instance is instructed to reacquire
23309any locks in the same state as they were previously held. (Alternative
23310methods of restarting the daemon have the side effect of changing
23311exclusive LV locks into shared locks.)
23312.
23313.HP
23314.BR \-t
23315.IR timeout
23316.br
23317Specifies the \fItimeout\fP for commands to run around the cluster. This should not
23318be so small that commands with many disk updates to do will fail, so you
23319may need to increase this on systems with very large disk farms.
23320The default is 60 seconds.
23321.
23322.HP
23323.BR \-T
23324.IR start_timeout
23325.br
23326Specifies the start timeout for \fBclvmd\fP daemon startup. If the
23327daemon does not report that it has started up within this time then the parent
23328command will exit with status of 5. This does NOT mean that \fBclvmd\fP has
23329not started! What it means is that the startup has been delayed for some
23330reason; the most likely cause of this is an inquorate cluster though it
23331could be due to locking latencies on a cluster with large numbers of logical
23332volumes. If you get the return code of 5 it is usually not necessary to
23333restart \fBclvmd\fP it will start as soon as that blockage has cleared.
23334This flag is to allow startup scripts to exit in a timely fashion even if the
23335cluster is stalled for some reason.
23336
23337The default is \fB0\fP (no timeout) and the value is in seconds. Don't set this too
23338small or you will experience spurious errors. 10 or 20 seconds might be
23339sensible.
23340
23341This timeout will be ignored if you start \fBclvmd\fP with the \fB\-d\fP.
23342.
23343.HP
23344.BR \-V
23345.br
23346Display the version of the cluster LVM daemon.
23347.
23348.SH ENVIRONMENT VARIABLES
23349.TP
23350.B LVM_CLVMD_BINARY
23351The CLVMD binary to use when \fBclvmd\fP restart is requested.
23352Defaults to \fI#CLVMD_PATH#\fP.
23353.TP
23354.B LVM_BINARY
23355The LVM2 binary to use.
23356Defaults to \fI#LVM_PATH#\fP.
23357.SH FILES
23358.I #CLVMD_PATH#
23359.br
23360.I #LVM_PATH#
23361.SH SEE ALSO
23362.BR syslog (3),
23363.BR lvm.conf (5),
23364.BR lvm (8)
23365\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm-dumpconfig.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000025\013062740170\0021244\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.so man8/lvmconfig.8
23366\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmsystemid.7.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000026146\013062740170\0020710\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMSYSTEMID" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
23367
23368.SH NAME
23369lvmsystemid \(em LVM system ID
23370
23371.SH DESCRIPTION
23372
23373Local VGs may exist on shared storage where they are visible to multiple
23374hosts. These VGs are intended to be used by only a single machine, even
23375though they are visible to many. A system_id identifying a single host
23376can be assigned to a VG to indicate the VGs owner. The VG owner can use
23377the VG as usual, and all other hosts will ignore it. This protects the VG
23378from accidental use by other hosts.
23379
23380The system_id is not a dynamic property, and can only be changed in very
23381limited circumstances (see vgexport and vgimport). Even limited changes
23382to the VG system_id are not perfectly reflected across hosts. A more
23383coherent view of shared storage requires using an inter-host locking
23384system to coordinate access and update caches.
23385
23386The system_id is a string uniquely identifying a host. It can be manually
23387set to a custom value or it can be assigned automatically by lvm using a
23388unique identifier already available on the host, e.g. machine-id or uname.
23389
23390In vgcreate, the local system_id is saved in the new VG metadata. The
23391local host owns the new VG, and other hosts cannot use it.
23392
23393A VG without a system_id can be used by any host, and a VG with a
23394system_id can only be used by a host with a matching system_id. A
23395.B foreign VG
23396is a VG with a system_id as viewed by a host with a system_id
23397that does not match the VGs system_id. (Or from a host without a
23398system_id.)
23399
23400Valid system_id characters are the same as valid VG name characters. If a
23401system_id contains invalid characters, those characters are omitted and
23402remaining characters are used. If a system_id is longer than the maximum
23403name length, the characters up to the maximum length are used. The
23404maximum length of a system_id is 128 characters.
23405
23406.SS Limitations and warnings
23407
23408To benefit fully from system_id, all hosts must have system_id set, and
23409VGs must have system_id set. A VG on shared storage can be damaged or
23410destroyed in some cases which the user must be careful to avoid.
23411
23412.IP \[bu] 2
23413A VG without a system_id can be used without restriction from any host,
23414even from hosts that have a system_id. Many VGs will not have a system_id
23415and are unprotected. Verify that a VG has a system_id by running the
23416command 'vgs -o+systemid'
23417
23418A VG will not have a system_id if it was created before this feature was
23419added to lvm, or if it was created by a host that did not have a system_id
23420defined. A system_id can be assigned to these VGs by using vgchange
23421--systemid (see below).
23422
23423.IP \[bu] 2
23424Two hosts should not be assigned the same system_id. Doing so defeats
23425the purpose of the system_id which is to distinguish different hosts.
23426
23427.IP \[bu] 2
23428Orphan PVs (or unused devices) on shared storage are completely
23429unprotected by the system_id feature. Commands that use these PVs, such
23430as vgcreate or vgextend, are not prevented from performing conflicting
23431operations and corrupting the PVs. See the
23432.B orphans
23433section for more information.
23434
23435.IP \[bu] 2
23436A host using an old version of lvm without the system_id feature will not
23437recognize a new system_id in VGs from other hosts. Even though the old
23438version of lvm is not blocked from reading a VG with a system_id, it is
23439blocked from writing to the VG (or its LVs). The new system_id changes
23440the write mode of a VG, making it appear read-only to previous lvm
23441versions.
23442
23443This also means that if a host downgrades its version of lvm, it would
23444lose access to any VGs it had created with a system_id. To avoid this,
23445the system_id should be removed from VGs before downgrading to an lvm
23446version without the system_id feature.
23447
23448.P
23449
23450.SS Types of VG access
23451
23452A local VG is meant to be used by a single host.
23453.br
23454A shared or clustered VG is meant to be used by multiple hosts.
23455.br
23456These can be further distinguished as:
23457
23458.B Unrestricted:
23459A local VG that has no system_id. This VG type is unprotected and
23460accessible to any host.
23461
23462.B Owned:
23463A local VG that has a system_id set, as viewed from the one host with a
23464matching system_id (the owner). This VG type is by definition acessible.
23465
23466.B Foreign:
23467A local VG that has a system_id set, as viewed from any host with an
23468unmatching system_id (or no system_id). It is owned by another host.
23469This VG type is by definition not accessible.
23470
23471.B Exported:
23472A local VG that has been exported with vgexport and has no system_id.
23473This VG type can only be accessed by vgimport which will change it to
23474owned.
23475
23476.B Shared:
23477A shared or "lockd" VG has lock_type set and no system_id.
23478A shared VG is meant to be used on shared storage from multiple hosts,
23479and is only accessible to hosts using lvmlockd. Applicable only if LVM
23480is compiled with lockd support.
23481
23482.B Clustered:
23483A clustered or "clvm" VG has the clustered flag set and no system_id.
23484A clustered VG is meant to be used on shared storage from multiple hosts,
23485and is only accessible to hosts using clvmd.
23486
23487.SS system_id_source
23488
23489A host's own system_id can be defined in a number of ways. lvm.conf
23490global/system_id_source defines the method lvm will use to find the local
23491system_id:
23492
23493.TP
23494.B none
23495.br
23496
23497lvm will not use a system_id. lvm is allowed to access VGs without a
23498system_id, and will create new VGs without a system_id. An undefined
23499system_id_source is equivalent to none.
23500
23501.I lvm.conf
23502.nf
23503global {
23504 system_id_source = "none"
23505}
23506.fi
23507
23508.TP
23509.B machineid
23510.br
23511
23512The content of /etc/machine-id is used as the system_id if available.
23513See
23514.BR machine-id (5)
23515and
23516.BR systemd-machine-id-setup (1)
23517to check if machine-id is available on the host.
23518
23519.I lvm.conf
23520.nf
23521global {
23522 system_id_source = "machineid"
23523}
23524.fi
23525
23526.TP
23527.B uname
23528.br
23529
23530The string utsname.nodename from
23531.BR uname (2)
23532is used as the system_id. A uname beginning with "localhost"
23533is ignored and equivalent to none.
23534
23535.I lvm.conf
23536.nf
23537global {
23538 system_id_source = "uname"
23539}
23540.fi
23541
23542.TP
23543.B lvmlocal
23544.br
23545
23546The system_id is defined in lvmlocal.conf local/system_id.
23547
23548.I lvm.conf
23549.nf
23550global {
23551 system_id_source = "lvmlocal"
23552}
23553.fi
23554
23555.I lvmlocal.conf
23556.nf
23557local {
23558 system_id = "example_name"
23559}
23560.fi
23561
23562.TP
23563.B file
23564.br
23565
23566The system_id is defined in a file specified by lvm.conf
23567global/system_id_file.
23568
23569.I lvm.conf
23570.nf
23571global {
23572 system_id_source = "file"
23573 system_id_file = "/path/to/file"
23574}
23575.fi
23576
23577.LP
23578
23579Changing system_id_source will often cause the system_id to change, which
23580may prevent the host from using VGs that it previously used (see
23581extra_system_ids below to handle this.)
23582
23583If a system_id_source other than none fails to resolve a system_id, the
23584host will be allowed to access VGs with no system_id, but will not be
23585allowed to access VGs with a defined system_id.
23586
23587.SS extra_system_ids
23588
23589In some cases, it may be useful for a host to access VGs with different
23590system_id's, e.g. if a host's system_id changes, and it wants to use VGs
23591that it created with its old system_id. To allow a host to access VGs
23592with other system_id's, those other system_id's can be listed in
23593lvmlocal.conf local/extra_system_ids.
23594
23595.I lvmlocal.conf
23596.nf
23597local {
23598 extra_system_ids = [ "my_other_name" ]
23599}
23600.fi
23601
23602.SS vgcreate
23603
23604In vgcreate, the host running the command assigns its own system_id to the
23605new VG. To override this and set another system_id:
23606
23607.B vgcreate --systemid
23608.I SystemID VG Devices
23609
23610Overriding the system_id makes it possible for a host to create a VG that
23611it may not be able to use. Another host with a system_id matching the one
23612specified may not recognize the new VG without manually rescanning
23613devices.
23614
23615If the --systemid argument is an empty string (""), the VG is created with
23616no system_id, making it accessible to other hosts (see warnings above.)
23617
23618.SS report/display
23619
23620The system_id of a VG is displayed with the "systemid" reporting option.
23621
23622Report/display commands ignore foreign VGs by default. To report foreign
23623VGs, the --foreign option can be used. This causes the VGs to be read
23624from disk. Because lvmetad caching is not used, this option can cause
23625poor performance.
23626
23627.B vgs --foreign -o+systemid
23628
23629When a host with no system_id sees foreign VGs, it warns about them as
23630they are skipped. The host should be assigned a system_id, after which
23631standard reporting commands will silently ignore foreign VGs.
23632
23633.SS vgexport/vgimport
23634
23635vgexport clears the system_id.
23636
23637Other hosts will continue to see a newly exported VG as foreign because of
23638local caching (when lvmetad is used). Manually updating the local lvmetad
23639cache with pvscan --cache will allow a host to recognize the newly
23640exported VG.
23641
23642vgimport sets the VG system_id to the local system_id as determined by
23643lvm.conf system_id_source. vgimport automatically scans storage for
23644newly exported VGs.
23645
23646After vgimport, the exporting host will continue to see the VG as
23647exported, and not owned by the new host. Manually updating the local
23648cache with pvscan --cache will allow a host to recognize the newly
23649imported VG as foreign.
23650
23651.SS vgchange
23652
23653A host can change the system_id of its own VGs, but the command requires
23654confirmation because the host may lose access to the VG being changed:
23655
23656.B vgchange --systemid
23657.I SystemID VG
23658
23659The system_id can be removed from a VG by specifying an empty string ("")
23660as the new system_id. This makes the VG accessible to other hosts (see
23661warnings above.)
23662
23663A host cannot directly change the system_id of a foreign VG.
23664
23665To move a VG from one host to another, vgexport and vgimport should be
23666used.
23667
23668To forcibly gain ownership of a foreign VG, a host can add the foreign
23669system_id to its extra_system_ids list, change the system_id of the
23670foreign VG to its own, and remove the foreign system_id from its
23671extra_system_ids list.
23672
23673.SS shared VGs
23674
23675A shared/lockd VG has no system_id set, allowing multiple hosts to
23676use it via lvmlockd. Changing a VG to a lockd type will clear the
23677existing system_id. Applicable only if LVM is compiled with lockd
23678support.
23679
23680.SS clustered VGs
23681
23682A clustered/clvm VG has no system_id set, allowing multiple hosts to
23683use it via clvmd. Changing a VG to clustered will clear the existing
23684system_id. Changing a VG to not clustered will set the system_id to the
23685host running the vgchange command.
23686
23687.SS creation_host
23688
23689In vgcreate, the VG metadata field creation_host is set by default to the
23690host's uname. The creation_host cannot be changed, and is not used to
23691control access. When system_id_source is "uname", the system_id and
23692creation_host will be the same.
23693
23694.SS orphans
23695
23696Orphan PVs are unused devices; they are not currently used in any VG.
23697Because of this, they are not protected by a system_id, and any host can
23698use them. Coordination of changes to orphan PVs is beyond the scope of
23699system_id. The same is true of any block device that is not a PV.
23700
23701The effects of this are especially evident when lvm uses lvmetad caching.
23702For example, if multiple hosts see an orphan PV, and one host creates a VG
23703using the orphan, the other hosts will continue to report the PV as an
23704orphan. Nothing would automatically prevent the other hosts from using
23705the newly allocated PV and corrupting it. If the other hosts run a
23706command to rescan devices, and update lvmetad, they would then recognize
23707that the PV has been used by another host. A command that rescans devices
23708could be pvscan --cache, or vgs --foreign.
23709
23710.SH SEE ALSO
23711.BR vgcreate (8),
23712.BR vgchange (8),
23713.BR vgimport (8),
23714.BR vgexport (8),
23715.BR lvm.conf (5),
23716.BR machine-id (5),
23717.BR uname (2),
23718.BR vgs (8)
23719
23720\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvreduce.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010032\013062740170\0020125\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVREDUCE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
23721.SH NAME
23722lvreduce \(em reduce the size of a logical volume
23723.SH SYNOPSIS
23724.B lvreduce
23725.RB [ \-A | \-\-autobackup
23726.RI { y | n }]
23727.RB [ \-\-commandprofile
23728.IR ProfileName ]
23729.RB [ \-d | \-\-debug ]
23730.RB [ \-h | \-\-help ]
23731.RB [ \-t | \-\-test ]
23732.RB [ \-v | \-\-verbose ]
23733.RB [ \-\-version ]
23734.RB [ \-f | \-\-force ]
23735.RB [ \-\-noudevsync ]
23736.RB { \-l | \-\-extents
23737.RI [ \- ] LogicalExtentsNumber [ % { VG | LV | FREE | ORIGIN }]
23738.RB |
23739.BR \-L | \-\-size
23740.RI [ \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]}
23741.RB [ \-n | \-\-nofsck ]
23742.RB [ \-\-reportformat
23743.RB { basic | json }]
23744.RB [ \-r | \-\-resizefs ]
23745.IR LogicalVolume { Name | Path }
23746.SH DESCRIPTION
23747lvreduce allows you to reduce the size of a logical volume.
23748Be careful when reducing a logical volume's size, because data in the
23749reduced part is lost!!!
23750.br
23751You should therefore ensure that any filesystem on the volume is
23752resized
23753.I before
23754running lvreduce so that the extents that are to be removed are not in use.
23755.br
23756Shrinking snapshot logical volumes (see
23757.BR lvcreate (8)
23758for information to create snapshots) is supported as well.
23759But to change the number of copies in a mirrored logical
23760volume use
23761.BR lvconvert (8).
23762.br
23763Sizes will be rounded if necessary - for example, the volume size must
23764be an exact number of extents and the size of a striped segment must
23765be a multiple of the number of stripes.
23766.br
23767.SH OPTIONS
23768See \fBlvm\fP(8) for common options.
23769.TP
23770.BR \-f ", " \-\-force
23771Force size reduction without prompting even when it may cause data loss.
23772.TP
23773.IR \fB\-l ", " \fB\-\-extents " [" \- ] LogicalExtentsNumber [ % { VG | LV | FREE | ORIGIN }]
23774Reduce or set the logical volume size in units of logical extents.
23775With the \fI-\fP sign the value will be subtracted from
23776the logical volume's actual size and without it the value will be taken
23777as an absolute size.
23778The total number of physical extents freed will be greater than this logical
23779value if, for example, the volume is mirrored.
23780The number can also be expressed as a percentage of the total space
23781in the Volume Group with the suffix \fI%VG\fP, relative to the existing
23782size of the Logical Volume with the suffix \fI%LV\fP, as a percentage of the
23783remaining free space in the Volume Group with the suffix \fI%FREE\fP, or (for
23784a snapshot) as a percentage of the total space in the Origin Logical
23785Volume with the suffix \fI%ORIGIN\fP.
23786The resulting value for the subtraction is rounded downward, for the absolute
23787size it is rounded upward.
23788N.B. In a future release, when expressed as a percentage with VG or FREE, the
23789number will be treated as an approximate total number of physical extents to be
23790freed (including extents used by any mirrors, for example). The code may
23791currently release more space than you might otherwise expect.
23792.TP
23793.IR \fB\-L ", " \fB\-\-size " [" \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
23794Reduce or set the logical volume size in units of megabytes.
23795A size suffix of \fIk\fP for kilobyte, \fIm\fP for megabyte,
23796\fIg\fP for gigabytes, \fIt\fP for terabytes, \fIp\fP for petabytes
23797or \fIe\fP for exabytes is optional.
23798With the \fI\-\fP sign the value will be subtracted from
23799the logical volume's actual size and without it it will be taken as
23800an absolute size.
23801.TP
23802.BR \-n ", " \-\-nofsck
23803Do not perform fsck before resizing filesystem when filesystem
23804requires it. You may need to use \fB\-\-force\fR to proceed with
23805this option.
23806.TP
23807.BR \-\-noudevsync
23808Disable udev synchronisation. The
23809process will not wait for notification from udev.
23810It will continue irrespective of any possible udev processing
23811in the background. You should only use this if udev is not running
23812or has rules that ignore the devices LVM2 creates.
23813.TP
23814.BR \-r ", " \-\-resizefs
23815Resize underlying filesystem together with the logical volume using
23816.BR fsadm (8).
23817.SH Examples
23818Reduce the size of logical volume lvol1 in volume group vg00 by 3 logical extents:
23819.sp
23820.B lvreduce \-l \-3 vg00/lvol1
23821.SH SEE ALSO
23822.BR fsadm (8),
23823.BR lvchange (8),
23824.BR lvconvert (8),
23825.BR lvcreate (8),
23826.BR lvextend (8),
23827.BR lvm (8),
23828.BR lvresize (8),
23829.BR vgreduce (8)
23830\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgremove.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002573\013062740170\0020161\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
23831.SH NAME
23832vgremove \(em remove a volume group
23833.SH SYNOPSIS
23834.B vgremove
23835.RB [ \-\-commandprofile
23836.IR ProfileName ]
23837.RB [ \-d | \-\-debug ]
23838.RB [ \-f | \-\-force ]
23839.RB [ \-h | \-? | \-\-help ]
23840.RB [ \-\-noudevsync ]
23841.RB [ \-\-reportformat
23842.RB { basic | json }]
23843.RB [ \-S | \-\-select
23844.IR Selection ]
23845.RB [ \-t | \-\-test ]
23846.RB [ \-v | \-\-verbose ]
23847.RI [ VolumeGroupName ...]
23848.SH DESCRIPTION
23849vgremove allows you to remove one or more volume groups.
23850If one or more physical volumes in the volume group are lost,
23851consider \fBvgreduce \-\-removemissing\fP to make the volume group
23852metadata consistent again.
23853.sp
23854If there are logical volumes that exist in the volume group,
23855a prompt will be given to confirm removal. You can override
23856the prompt with \fB\-f\fP.
23857.SH OPTIONS
23858See \fBlvm\fP(8) for common options.
23859.TP
23860.BR \-f ", " \-\-force
23861Force the removal of any logical volumes on the volume group
23862without confirmation.
23863To remove also damaged pool volumes use \-ff.
23864.TP
23865.BR \-\-noudevsync
23866Disable udev synchronisation. The
23867process will not wait for notification from udev.
23868It will continue irrespective of any possible udev processing
23869in the background. You should only use this if udev is not running
23870or has rules that ignore the devices LVM2 creates.
23871.SH SEE ALSO
23872.BR lvm (8),
23873.BR lvremove (8),
23874.BR vgcreate (8),
23875.BR vgreduce (8)
23876\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvcreate.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000074140\013062740170\0020133\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
23877.
23878.\" Use 1st. parameter with \% to fix 'man2html' rendeing on same line!
23879.de SIZE_G
23880. IR \\$1 \c
23881. RB [ b | B | s | S | k | K | m | M | g | G ]
23882..
23883.de SIZE_E
23884. IR \\$1 \c
23885. RB [ b | B | s | S | k | K | m | M | \c
23886. BR g | G | t | T | p | P | e | E ]
23887..
23888.
23889.SH NAME
23890.
23891lvcreate \- create a logical volume in an existing volume group
23892.
23893.SH SYNOPSIS
23894.
23895.ad l
23896.B lvcreate
23897.RB [ \-a | \-\-activate
23898.RB [ a ][ e | l | s ]{ y | n }]
23899.RB [ \-\-addtag
23900.IR Tag ]
23901.RB [ \-\-alloc
23902.IR Allocation\%Policy ]
23903.RB [ \-A | \-\-autobackup
23904.RB { y | n }]
23905.RB [ \-H | \-\-cache ]
23906.RB [ \-\-cachemode
23907.RB { passthrough | writeback | writethrough }]
23908.RB [ \-\-cachepolicy
23909.IR Policy ]
23910.RB \%[ \-\-cachepool
23911.IR CachePoolLogicalVolume ]
23912.RB [ \-\-cachesettings
23913.IR Key \fB= Value ]
23914.RB [ \-c | \-\-chunksize
23915.IR ChunkSize ]
23916.RB [ \-\-commandprofile
23917.IR ProfileName ]
23918.RB \%[ \-C | \-\-contiguous
23919.RB { y | n }]
23920.RB [ \-d | \-\-debug ]
23921.RB [ \-\-discards
23922.RB \%{ ignore | nopassdown | passdown }]
23923.RB [ \-\-errorwhenfull
23924.RB { y | n }]
23925.RB [{ \-l | \-\-extents
23926.BR \fILogicalExtents\%Number [ % { FREE | PVS | VG }]
23927.RB |
23928.BR \-L | \-\-size
23929.BR \fILogicalVolumeSize }
23930.RB [ \-i | \-\-stripes
23931.IR Stripes
23932.RB [ \-I | \-\-stripesize
23933.IR StripeSize ]]]
23934.RB [ \-h | \-? | \-\-help ]
23935.RB [ \-K | \-\-ignoreactivationskip ]
23936.RB [ \-\-ignoremonitoring ]
23937.RB [ \-\-minor
23938.IR Minor
23939.RB [ \-j | \-\-major
23940.IR Major ]]
23941.RB [ \-\-metadataprofile
23942.IR Profile\%Name ]
23943.RB [ \-m | \-\-mirrors
23944.IR Mirrors
23945.RB [ \-\-corelog | \-\-mirrorlog
23946.RB { disk | core | mirrored }]
23947.RB [ \-\-nosync ]
23948.RB [ \-R | \-\-regionsize
23949.BR \fIMirrorLogRegionSize ]]
23950.RB [ \-\-monitor
23951.RB { y | n }]
23952.RB [ \-n | \-\-name
23953.IR Logical\%Volume ]
23954.RB [ \-\-noudevsync ]
23955.RB [ \-p | \-\-permission
23956.RB { r | rw }]
23957.RB [ \-M | \-\-persistent
23958.RB { y | n }]
23959.\" .RB [ \-\-pooldatasize
23960.\" .I DataVolumeSize
23961.RB \%[ \-\-poolmetadatasize
23962.IR MetadataVolumeSize ]
23963.RB [ \-\-poolmetadataspare
23964.RB { y | n }]
23965.RB [ \-\- [ raid ] maxrecoveryrate
23966.IR Rate ]
23967.RB [ \-\- [ raid ] minrecoveryrate
23968.IR Rate ]
23969.RB [ \-r | \-\-readahead
23970.RB { \fIReadAheadSectors | auto | none }]
23971.RB [ \-\-reportformat
23972.RB {basic | json}]
23973.RB \%[ \-k | \-\-setactivationskip
23974.RB { y | n }]
23975.RB [ \-s | \-\-snapshot ]
23976.RB [ \-V | \-\-virtualsize
23977.IR VirtualSize ]
23978.RB [ \-t | \-\-test ]
23979.RB [ \-T | \-\-thin ]
23980.RB [ \-\-thinpool
23981.IR ThinPoolLogicalVolume ]
23982.RB [ \-\-type
23983.IR SegmentType ]
23984.RB [ \-v | \-\-verbose ]
23985.RB [ \-W | \-\-wipesignatures
23986.RB { y | n }]
23987.RB [ \-Z | \-\-zero
23988.RB { y | n }]
23989.RI [ VolumeGroup
23990.RI |
23991.RI \%{ ExternalOrigin | Origin | Pool } LogicalVolume
23992.RI \%[ PhysicalVolumePath [ \fB: \fIPE \fR[ \fB\- PE ]]...]]
23993.LP
23994.B lvcreate
23995.RB [ \-l | \-\-extents
23996.BR \fILogicalExtentsNumber [ % { FREE | ORIGIN | PVS | VG }]
23997|
23998.BR \-L | \-\-size
23999.\" | \-\-pooldatasize
24000.IR LogicalVolumeSize ]
24001.RB [ \-c | \-\-chunksize
24002.IR ChunkSize ]
24003.RB \%[ \-\-commandprofile
24004.IR Profile\%Name ]
24005.RB [ \-\-noudevsync ]
24006.RB [ \-\-ignoremonitoring ]
24007.RB [ \-\-metadataprofile
24008.IR Profile\%Name ]
24009.RB \%[ \-\-monitor
24010.RB { y | n }]
24011.RB [ \-n | \-\-name
24012.IR SnapshotLogicalVolumeName ]
24013.RB [ \-\-reportformat
24014.RB {basic | json}]
24015.BR \-s | \-\-snapshot | \-H | \-\-cache
24016.RI \%{[ VolumeGroup \fB/\fP] OriginalLogicalVolume
24017.RB \%[ \-V | \-\-virtualsize
24018.IR VirtualSize ]}
24019.ad b
24020.
24021.SH DESCRIPTION
24022.
24023lvcreate creates a new logical volume in a volume group (see
24024.BR vgcreate "(8), " vgchange (8))
24025by allocating logical extents from the free physical extent pool
24026of that volume group. If there are not enough free physical extents then
24027the volume group can be extended (see
24028.BR vgextend (8))
24029with other physical volumes or by reducing existing logical volumes
24030of this volume group in size (see
24031.BR lvreduce (8)).
24032If you specify one or more PhysicalVolumes, allocation of physical
24033extents will be restricted to these volumes.
24034.br
24035.br
24036The second form supports the creation of snapshot logical volumes which
24037keep the contents of the original logical volume for backup purposes.
24038.
24039.SH OPTIONS
24040.
24041See
24042.BR lvm (8)
24043for common options.
24044.
24045.HP
24046.BR \-a | \-\-activate
24047.RB [ a ][ l | e | s ]{ y | n }
24048.br
24049Controls the availability of the Logical Volumes for immediate use after
24050the command finishes running.
24051By default, new Logical Volumes are activated (\fB\-ay\fP).
24052If it is possible technically, \fB\-an\fP will leave the new Logical
24053Volume inactive. But for example, snapshots of active origin can only be
24054created in the active state so \fB\-an\fP cannot be used with
24055\fB-\-type snapshot\fP. This does not apply to thin volume snapshots,
24056which are by default created with flag to skip their activation
24057(\fB-ky\fP).
24058Normally the \fB\-\-zero n\fP argument has to be supplied too because
24059zeroing (the default behaviour) also requires activation.
24060If autoactivation option is used (\fB\-aay\fP), the logical volume is
24061activated only if it matches an item in the
24062\fBactivation/auto_activation_volume_list\fP
24063set in \fBlvm.conf\fP(5).
24064For autoactivated logical volumes, \fB\-\-zero n\fP and
24065\fB\-\-wipesignatures n\fP is always assumed and it can't
24066be overridden. If the clustered locking is enabled,
24067\fB\-aey\fP will activate exclusively on one node and
24068.BR \-a { a | l } y
24069will activate only on the local node.
24070.
24071.HP
24072.BR \-H | \-\-cache
24073.br
24074Creates cache or cache pool logical volume.
24075.\" or both.
24076Specifying the optional argument \fB\-\-extents\fP or \fB\-\-size\fP
24077will cause the creation of the cache logical volume.
24078.\" Specifying the optional argument \fB\-\-pooldatasize\fP will cause
24079.\" the creation of the cache pool logical volume.
24080.\" Specifying both arguments will cause the creation of cache with its
24081.\" cache pool volume.
24082When the Volume group name is specified together with existing logical volume
24083name which is NOT a cache pool name, such volume is treated
24084as cache origin volume and cache pool is created. In this case the
24085\fB\-\-extents\fP or \fB\-\-size\fP is used to specify size of cache pool volume.
24086See \fBlvmcache\fP(7) for more info about caching support.
24087Note that the cache segment type requires a dm-cache kernel module version
240881.3.0 or greater.
24089.
24090.HP
24091.BR \-\-cachemode
24092.RB { passthrough | writeback | writethrough }
24093.br
24094Specifying a cache mode determines when the writes to a cache LV
24095are considered complete. When \fBwriteback\fP is specified, a write is
24096considered complete as soon as it is stored in the cache pool LV.
24097If \fBwritethough\fP is specified, a write is considered complete only
24098when it has been stored in the cache pool LV and on the origin LV.
24099While \fBwritethrough\fP may be slower for writes, it is more
24100resilient if something should happen to a device associated with the
24101cache pool LV. With \fBpassthrough\fP mode, all reads are served
24102from origin LV (all reads miss the cache) and all writes are
24103forwarded to the origin LV; additionally, write hits cause cache
24104block invalidates. See \fBlvmcache(7)\fP for more details.
24105.
24106.HP
24107.BR \-\-cachepolicy
24108.IR Policy
24109.br
24110Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
24111the cache policy. \fBmq\fP is the basic policy name. \fBsmq\fP is more advanced
24112version available in newer kernels.
24113.
24114.HP
24115.BR \-\-cachepool
24116.IR CachePoolLogicalVolume { Name | Path }
24117.br
24118Specifies the name of cache pool volume name. The other way to specify pool name
24119is to append name to Volume group name argument.
24120.
24121.HP
24122.BR \-\-cachesettings
24123.IB Key = Value
24124.br
24125Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
24126the cache tunable settings. In most use-cases, default values should be adequate.
24127Special string value \fBdefault\fP switches setting back to its default kernel value
24128and removes it from the list of settings stored in lvm2 metadata.
24129.
24130.HP
24131.BR \-c | \-\-chunksize
24132.SIZE_G \%ChunkSize
24133.br
24134Gives the size of chunk for snapshot, cache pool and thin pool logical volumes.
24135Default unit is in kilobytes.
24136.br
24137For snapshots the value must be power of 2 between 4KiB and 512KiB
24138and the default value is 4KiB.
24139.br
24140For cache pools the value must a multiple of 32KiB
24141between 32KiB and 1GiB. The default is 64KiB.
24142When the size is specified with volume caching, it may not be smaller
24143than cache pool creation chunk size was.
24144.br
24145For thin pools the value must be a multiple of 64KiB
24146between 64KiB and 1GiB.
24147Default value starts with 64KiB and grows up to
24148fit the pool metadata size within 128MiB,
24149if the pool metadata size is not specified.
24150See
24151.BR lvm.conf (5)
24152setting \fBallocation/thin_pool_chunk_size_policy\fP
24153to select different calculation policy.
24154Thin pool target version <1.4 requires this value to be a power of 2.
24155For target version <1.5 discard is not supported for non power of 2 values.
24156.
24157.HP
24158.BR \-C | \-\-contiguous
24159.RB { y | n }
24160.br
24161Sets or resets the contiguous allocation policy for
24162logical volumes. Default is no contiguous allocation based
24163on a next free principle.
24164.
24165.HP
24166.BR \-\-corelog
24167.br
24168This is shortcut for option \fB\-\-mirrorlog core\fP.
24169.
24170.HP
24171.BR \-\-discards
24172.RB { ignore | nopassdown | passdown }
24173.br
24174Sets discards behavior for thin pool.
24175Default is \fBpassdown\fP.
24176.
24177.HP
24178.BR \-\-errorwhenfull
24179.RB { y | n }
24180.br
24181Configures thin pool behaviour when data space is exhausted.
24182Default is \fBn\fPo.
24183Device will queue I/O operations until target timeout
24184(see dm-thin-pool kernel module option \fPno_space_timeout\fP)
24185expires. Thus configured system has a time to i.e. extend
24186the size of thin pool data device.
24187When set to \fBy\fPes, the I/O operation is immeditelly errored.
24188.
24189.HP
24190.BR \-K | \-\-ignoreactivationskip
24191.br
24192Ignore the flag to skip Logical Volumes during activation.
24193Use \fB\-\-setactivationskip\fP option to set or reset
24194activation skipping flag persistently for logical volume.
24195.
24196.HP
24197.BR \-\-ignoremonitoring
24198.br
24199Make no attempt to interact with dmeventd unless \fB\-\-monitor\fP
24200is specified.
24201.
24202.HP
24203.BR -l | \-\-extents
24204.IR LogicalExtentsNumber \c
24205.RB [ % { VG | PVS | FREE | ORIGIN }]
24206.br
24207Specifies the size of the new LV in logical extents. The number of
24208physical extents allocated may be different, and depends on the LV type.
24209Certain LV types require more physical extents for data redundancy or
24210metadata. An alternate syntax allows the size to be determined indirectly
24211as a percentage of the size of a related VG, LV, or set of PVs. The
24212suffix \fB%VG\fP denotes the total size of the VG, the suffix \fB%FREE\fP
24213the remaining free space in the VG, and the suffix \fB%PVS\fP the free
24214space in the specified Physical Volumes. For a snapshot, the size
24215can be expressed as a percentage of the total size of the Origin Logical
24216Volume with the suffix \fB%ORIGIN\fP (\fB100%ORIGIN\fP provides space for
24217the whole origin).
24218When expressed as a percentage, the size defines an upper limit for the
24219number of logical extents in the new LV. The precise number of logical
24220extents in the new LV is not determined until the command has completed.
24221.
24222.HP
24223.BR \-j | \-\-major
24224.IR Major
24225.br
24226Sets the major number.
24227Major numbers are not supported with pool volumes.
24228This option is supported only on older systems
24229(kernel version 2.4) and is ignored on modern Linux systems where major
24230numbers are dynamically assigned.
24231.
24232.HP
24233.BR \-\-metadataprofile
24234.IR ProfileName
24235.br
24236Uses and attaches the \fIProfileName\fP configuration profile to the logical
24237volume metadata. Whenever the logical volume is processed next time,
24238the profile is automatically applied. If the volume group has another
24239profile attached, the logical volume profile is preferred.
24240See \fBlvm.conf\fP(5) for more information about \fBmetadata profiles\fP.
24241.
24242.HP
24243.BR \-\-minor
24244.IR Minor
24245.br
24246Sets the minor number.
24247Minor numbers are not supported with pool volumes.
24248.
24249.HP
24250.BR \-m | \-\-mirrors
24251.IR mirrors
24252.br
24253Creates a mirrored logical volume with \fImirrors\fP copies.
24254For example, specifying \fB\-m 1\fP
24255would result in a mirror with two-sides; that is,
24256a linear volume plus one copy.
24257
24258Specifying the optional argument \fB\-\-nosync\fP will cause the creation
24259of the mirror LV to skip the initial resynchronization. Any data written
24260afterwards will be mirrored, but the original contents will not be copied.
24261
24262This is useful for skipping a potentially long and resource intensive initial
24263sync of an empty mirrored RaidLV.
24264
24265There are two implementations of mirroring which can be used and correspond
24266to the "\fIraid1\fP" and "\fImirror\fP" segment types.
24267The default is "\fIraid1\fP". See the
24268\fB\-\-type\fP option for more information if you would like to use the
24269legacy "\fImirror\fP" segment type. See
24270.BR lvm.conf (5)
24271settings \fB global/mirror_segtype_default\fP
24272and \fBglobal/raid10_segtype_default\fP
24273to configure default mirror segment type.
24274The options
24275\fB\-\-mirrorlog\fP and \fB\-\-corelog\fP apply
24276to the legacy "\fImirror\fP" segment type only.
24277
24278Note the current maxima for mirrors are 7 for "mirror" providing
242798 mirror legs and 9 for "raid1" providing 10 legs.
24280.
24281.HP
24282.BR \-\-mirrorlog
24283.RB { disk | core | mirrored }
24284.br
24285Specifies the type of log to be used for logical volumes utilizing
24286the legacy "\fImirror\fP" segment type.
24287.br
24288The default is \fBdisk\fP, which is persistent and requires
24289a small amount of storage space, usually on a separate device from the
24290data being mirrored.
24291.br
24292Using \fBcore\fP means the mirror is regenerated by copying the data
24293from the first device each time the logical volume is activated,
24294like after every reboot.
24295.br
24296Using \fBmirrored\fP will create a persistent log that is itself mirrored.
24297.
24298.HP
24299.BR \-\-monitor
24300.RB { y | n }
24301.br
24302Starts or avoids monitoring a mirrored, snapshot or thin pool logical volume with
24303dmeventd, if it is installed.
24304If a device used by a monitored mirror reports an I/O error,
24305the failure is handled according to
24306\fBactivation/mirror_image_fault_policy\fP
24307and \fBactivation/mirror_log_fault_policy\fP
24308set in \fBlvm.conf\fP(5).
24309.
24310.HP
24311.BR \-n | \-\-name
24312.IR LogicalVolume { Name | Path }
24313.br
24314Sets the name for the new logical volume.
24315.br
24316Without this option a default name of "lvol#" will be generated where
24317# is the LVM internal number of the logical volume.
24318.
24319.HP
24320.BR \-\-nosync
24321.br
24322Causes the creation of mirror, raid1, raid4, raid5 and raid10 to skip the
24323initial resynchronization. In case of mirror, raid1 and raid10, any data
24324written afterwards will be mirrored, but the original contents will not be
24325copied. In case of raid4 and raid5, no parity blocks will be written,
24326though any data written afterwards will cause parity blocks to be stored.
24327.br
24328This is useful for skipping a potentially long and resource intensive initial
24329sync of an empty mirror/raid1/raid4/raid5 and raid10 LV.
24330.br
24331This option is not valid for raid6, because raid6 relies on proper parity
24332(P and Q Syndromes) being created during initial synchronization in order
24333to reconstruct proper user date in case of device failures.
24334
24335raid0 and raid0_meta don't provide any data copies or parity support
24336and thus don't support initial resynchronization.
24337.
24338.HP
24339.BR \-\-noudevsync
24340.br
24341Disables udev synchronisation. The
24342process will not wait for notification from udev.
24343It will continue irrespective of any possible udev processing
24344in the background. You should only use this if udev is not running
24345or has rules that ignore the devices LVM2 creates.
24346.
24347.HP
24348.BR \-p | \-\-permission
24349.RB { r | rw }
24350.br
24351Sets access permissions to read only (\fBr\fP) or read and write (\fBrw\fP).
24352.br
24353Default is read and write.
24354.
24355.HP
24356.BR \-M | \-\-persistent
24357.RB { y | n }
24358.br
24359Set to \fBy\fP to make the minor number specified persistent.
24360Pool volumes cannot have persistent major and minor numbers.
24361Defaults to \fBy\fPes only when major or minor number is specified.
24362Otherwise it is \fBn\fPo.
24363.\" .HP
24364.\" .IR \fB\-\-pooldatasize " " PoolDataVolumeSize [ bBsSkKmMgGtTpPeE ]
24365.\" Sets the size of pool's data logical volume.
24366.\" For thin pools you may also specify the size
24367.\" with the option \fB\-\-size\fP.
24368.\"
24369.
24370.HP
24371.BR \-\-poolmetadatasize
24372.SIZE_G \%MetadataVolumeSize
24373.br
24374Sets the size of pool's metadata logical volume.
24375Supported values are in range between 2MiB and 16GiB for thin pool,
24376and upto 16GiB for cache pool. The minimum value is computed from pool's
24377data size.
24378Default value for thin pool is (Pool_LV_size / Pool_LV_chunk_size * 64b).
24379To work with a thin pool, there should be at least 25% of free space
24380when the size of metadata is smaller then 16MiB,
24381or at least 4MiB of free space otherwise.
24382Default unit is megabytes.
24383.
24384.HP
24385.BR \-\-poolmetadataspare
24386.RB { y | n }
24387.br
24388Controls creation and maintanence of pool metadata spare logical volume
24389that will be used for automated pool recovery.
24390Only one such volume is maintained within a volume group
24391with the size of the biggest pool metadata volume.
24392Default is \fBy\fPes.
24393.
24394.HP
24395.BR \-\- [ raid ] maxrecoveryrate
24396.SIZE_G \%Rate
24397.br
24398Sets the maximum recovery rate for a RAID logical volume. \fIRate\fP
24399is specified as an amount per second for each device in the array.
24400If no suffix is given, then KiB/sec/device is assumed. Setting the
24401recovery rate to 0 means it will be unbounded.
24402.
24403.HP
24404.BR \-\- [ raid ] minrecoveryrate
24405.SIZE_G \%Rate
24406.br
24407Sets the minimum recovery rate for a RAID logical volume. \fIRate\fP
24408is specified as an amount per second for each device in the array.
24409If no suffix is given, then KiB/sec/device is assumed. Setting the
24410recovery rate to 0 means it will be unbounded.
24411.
24412.HP
24413.BR \-r | \-\-readahead
24414.RB { \fIReadAheadSectors | auto | none }
24415.br
24416Sets read ahead sector count of this logical volume.
24417For volume groups with metadata in lvm1 format, this must
24418be a value between 2 and 120.
24419The default value is \fBauto\fP which allows the kernel to choose
24420a suitable value automatically.
24421\fBnone\fP is equivalent to specifying zero.
24422.
24423.HP
24424.BR \-R | \-\-regionsize
24425.SIZE_G \%MirrorLogRegionSize
24426.br
24427A mirror is divided into regions of this size (in MiB), and the mirror log
24428uses this granularity to track which regions are in sync.
24429.
24430.HP
24431.BR \-k | \-\-setactivationskip
24432.RB { y | n }
24433.br
24434Controls whether Logical Volumes are persistently flagged to be skipped during
24435activation. By default, thin snapshot volumes are flagged for activation skip.
24436See
24437.BR lvm.conf (5)
24438\fBactivation/auto_set_activation_skip\fP
24439how to change its default behaviour.
24440To activate such volumes, an extra \fB\-\-ignoreactivationskip\fP
24441option must be used. The flag is not applied during deactivation. Use
24442\fBlvchange \-\-setactivationskip\fP
24443command to change the skip flag for existing volumes.
24444To see whether the flag is attached, use \fBlvs\fP command
24445where the state of the flag is reported within \fBlv_attr\fP bits.
24446.
24447.HP
24448.BR \-L | \-\-size
24449.SIZE_E \%LogicalVolumeSize
24450.br
24451Gives the size to allocate for the new logical volume.
24452A size suffix of \fBB\fP for bytes, \fBS\fP for sectors as 512 bytes,
24453\fBK\fP for kilobytes, \fBM\fP for megabytes,
24454\fBG\fP for gigabytes, \fBT\fP for terabytes, \fBP\fP for petabytes
24455or \fBE\fP for exabytes is optional.
24456.br
24457Default unit is megabytes.
24458.
24459.HP
24460.BR \-s | \fB\-\-snapshot
24461.IR OriginalLogicalVolume { Name | Path }
24462.br
24463Creates a snapshot logical volume (or snapshot) for an existing, so called
24464original logical volume (or origin).
24465Snapshots provide a 'frozen image' of the contents of the origin
24466while the origin can still be updated. They enable consistent
24467backups and online recovery of removed/overwritten data/files.
24468.br
24469Thin snapshot is created when the origin is a thin volume and
24470the size IS NOT specified. Thin snapshot shares same blocks within
24471the thin pool volume.
24472The non thin volume snapshot with the specified size does not need
24473the same amount of storage the origin has. In a typical scenario,
2447415-20% might be enough. In case the snapshot runs out of storage, use
24475.BR lvextend (8)
24476to grow it. Shrinking a snapshot is supported by
24477.BR lvreduce (8)
24478as well. Run
24479.BR lvs (8)
24480on the snapshot in order to check how much data is allocated to it.
24481Note: a small amount of the space you allocate to the snapshot is
24482used to track the locations of the chunks of data, so you should
24483allocate slightly more space than you actually need and monitor
24484(\fB\-\-monitor\fP) the rate at which the snapshot data is growing
24485so you can \fBavoid\fP running out of space.
24486If \fB\-\-thinpool\fP is specified, thin volume is created that will
24487use given original logical volume as an external origin that
24488serves unprovisioned blocks.
24489Only read-only volumes can be used as external origins.
24490To make the volume external origin, lvm expects the volume to be inactive.
24491External origin volume can be used/shared for many thin volumes
24492even from different thin pools. See
24493.BR lvconvert (8)
24494for online conversion to thin volumes with external origin.
24495.
24496.HP
24497.BR \-i | \-\-stripes
24498.IR Stripes
24499.br
24500Gives the number of stripes.
24501This is equal to the number of physical volumes to scatter
24502the logical volume data. When creating a RAID 4/5/6 logical volume,
24503the extra devices which are necessary for parity are
24504internally accounted for. Specifying \fB\-i 3\fP
24505would cause 3 devices for striped and RAID 0 logical volumes,
245064 devices for RAID 4/5, 5 devices for RAID 6 and 6 devices for RAID 10.
24507Alternatively, RAID 0 will stripe across 2 devices,
24508RAID 4/5 across 3 PVs, RAID 6 across 5 PVs and RAID 10 across
245094 PVs in the volume group if the \fB\-i\fP argument is omitted.
24510In order to stripe across all PVs of the VG if the \fB\-i\fP argument is
24511omitted, set raid_stripe_all_devices=1 in the allocation
24512section of \fBlvm.conf (5)\fP or add
24513.br
24514\fB\-\-config allocation/raid_stripe_all_devices=1\fP
24515.br
24516to the command.
24517
24518Note the current maxima for stripes depend on the created RAID type.
24519For raid10, the maximum of stripes is 32,
24520for raid0, it is 64,
24521for raid4/5, it is 63
24522and for raid6 it is 62.
24523
24524See the \fB\-\-nosync\fP option to optionally avoid initial syncrhonization of RaidLVs.
24525
24526Two implementations of basic striping are available in the kernel.
24527The original device-mapper implementation is the default and should
24528normally be used. The alternative implementation using MD, available
24529since version 1.7 of the RAID device-mapper kernel target (kernel
24530version 4.2) is provided to facilitate the development of new RAID
24531features. It may be accessed with \fB--type raid0[_meta]\fP, but is best
24532avoided at present because of assorted restrictions on resizing and converting
24533such devices.
24534.HP
24535.BR \-I | \-\-stripesize
24536.IR StripeSize
24537.br
24538Gives the number of kilobytes for the granularity of the stripes.
24539.br
24540StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
24541For metadata in LVM2 format, the stripe size may be a larger
24542power of 2 but must not exceed the physical extent size.
24543.
24544.HP
24545.BR \-T | \-\-thin
24546.br
24547Creates thin pool or thin logical volume or both.
24548Specifying the optional argument \fB\-\-size\fP or \fB\-\-extents\fP
24549will cause the creation of the thin pool logical volume.
24550Specifying the optional argument \fB\-\-virtualsize\fP will cause
24551the creation of the thin logical volume from given thin pool volume.
24552Specifying both arguments will cause the creation of both
24553thin pool and thin volume using this pool.
24554See \fBlvmthin\fP(7) for more info about thin provisioning support.
24555Thin provisioning requires device mapper kernel driver
24556from kernel 3.2 or greater.
24557.
24558.HP
24559.BR \-\-thinpool
24560.IR ThinPoolLogicalVolume { Name | Path }
24561.br
24562Specifies the name of thin pool volume name. The other way to specify pool name
24563is to append name to Volume group name argument.
24564.
24565.HP
24566.BR \-\-type
24567.IR SegmentType
24568.br
24569Creates a logical volume with the specified segment type.
24570Supported types are:
24571.BR cache ,
24572.BR cache-pool ,
24573.BR error ,
24574.BR linear ,
24575.BR mirror,
24576.BR raid0 ,
24577.BR raid1 ,
24578.BR raid4 ,
24579.BR raid5_la ,
24580.BR raid5_ls
24581.RB (=
24582.BR raid5 ),
24583.BR raid5_ra ,
24584.BR raid5_rs ,
24585.BR raid6_nc ,
24586.BR raid6_nr ,
24587.BR raid6_zr
24588.RB (=
24589.BR raid6 ),
24590.BR raid10 ,
24591.BR snapshot ,
24592.BR striped,
24593.BR thin ,
24594.BR thin-pool
24595or
24596.BR zero .
24597Segment type may have a commandline switch alias that will
24598enable its use.
24599When the type is not explicitly specified an implicit type
24600is selected from combination of options:
24601.BR \-H | \-\-cache | \-\-cachepool
24602(cache or cachepool),
24603.BR \-T | \-\-thin | \-\-thinpool
24604(thin or thinpool),
24605.BR \-m | \-\-mirrors
24606(raid1 or mirror),
24607.BR \-s | \-\-snapshot | \-V | \-\-virtualsize
24608(snapshot or thin),
24609.BR \-i | \-\-stripes
24610(striped).
24611The default segment type is \fBlinear\fP.
24612.
24613.HP
24614.BR \-V | \-\-virtualsize
24615.SIZE_E \%VirtualSize
24616.br
24617Creates a thinly provisioned device or a sparse device of the given size (in MiB by default).
24618See
24619.BR lvm.conf (5)
24620settings \fBglobal/sparse_segtype_default\fP
24621to configure default sparse segment type.
24622See \fBlvmthin\fP(7) for more info about thin provisioning support.
24623Anything written to a sparse snapshot will be returned when reading from it.
24624Reading from other areas of the device will return blocks of zeros.
24625Virtual snapshot (sparse snapshot) is implemented by creating
24626a hidden virtual device of the requested size using the zero target.
24627A suffix of _vorigin is used for this device.
24628Note: using sparse snapshots is not efficient for larger
24629device sizes (GiB), thin provisioning should be used for this case.
24630.
24631.HP
24632.BR \-W | \-\-wipesignatures
24633.RB { y | n }
24634.br
24635Controls detection and subsequent wiping of signatures on newly created
24636Logical Volume. There's a prompt for each signature detected to confirm
24637its wiping (unless \fB--yes\fP is used where LVM assumes 'yes' answer
24638for each prompt automatically). If this option is not specified, then by
24639default \fB-W\fP | \fB--wipesignatures y\fP is assumed each time the
24640zeroing is done (\fB\-Z\fP | \fB\-\-zero y\fP). This default behaviour
24641can be controlled by \fB\%allocation/wipe_signatures_when_zeroing_new_lvs\fP
24642setting found in
24643.BR lvm.conf (5).
24644.br
24645If blkid wiping is used (\fBallocation/use_blkid_wiping\fP setting in
24646.BR lvm.conf (5))
24647and LVM2 is compiled with blkid wiping support, then \fBblkid\fP(8) library is used
24648to detect the signatures (use \fBblkid \-k\fP command to list the signatures that are recognized).
24649Otherwise, native LVM2 code is used to detect signatures (MD RAID, swap and LUKS
24650signatures are detected only in this case).
24651.br
24652Logical volume is not wiped if the read only flag is set.
24653.
24654.HP
24655.BR \-Z | \-\-zero
24656.RB { y | n }
24657.br
24658Controls zeroing of the first 4KiB of data in the new logical volume.
24659Default is \fBy\fPes.
24660Snapshot COW volumes are always zeroed.
24661Logical volume is not zeroed if the read only flag is set.
24662.br
24663Warning: trying to mount an unzeroed logical volume can cause the system to
24664hang.
24665.
24666.SH Examples
24667.
24668Creates a striped logical volume with 3 stripes, a stripe size of 8KiB
24669and a size of 100MiB in the volume group named vg00.
24670The logical volume name will be chosen by lvcreate:
24671.sp
24672.B lvcreate \-i 3 \-I 8 \-L 100M vg00
24673
24674Creates a mirror logical volume with 2 sides with a useable size of 500 MiB.
24675This operation would require 3 devices (or option
24676\fB\-\-alloc \%anywhere\fP) - two for the mirror
24677devices and one for the disk log:
24678.sp
24679.B lvcreate \-m1 \-L 500M vg00
24680
24681Creates a mirror logical volume with 2 sides with a useable size of 500 MiB.
24682This operation would require 2 devices - the log is "in-memory":
24683.sp
24684.B lvcreate \-m1 \-\-mirrorlog core \-L 500M vg00
24685
24686Creates a snapshot logical volume named "vg00/snap" which has access to the
24687contents of the original logical volume named "vg00/lvol1"
24688at snapshot logical volume creation time. If the original logical volume
24689contains a file system, you can mount the snapshot logical volume on an
24690arbitrary directory in order to access the contents of the filesystem to run
24691a backup while the original filesystem continues to get updated:
24692.sp
24693.B lvcreate \-\-size 100m \-\-snapshot \-\-name snap /dev/vg00/lvol1
24694
24695Creates a snapshot logical volume named "vg00/snap" with size
24696for overwriting 20% of the original logical volume named "vg00/lvol1".:
24697.sp
24698.B lvcreate \-s \-l 20%ORIGIN \-\-name snap vg00/lvol1
24699
24700Creates a sparse device named /dev/vg1/sparse of size 1TiB with space for just
24701under 100MiB of actual data on it:
24702.sp
24703.B lvcreate \-\-virtualsize 1T \-\-size 100M \-\-snapshot \-\-name sparse vg1
24704
24705Creates a linear logical volume "vg00/lvol1" using physical extents
24706/dev/sda:0\-7 and /dev/sdb:0\-7 for allocation of extents:
24707.sp
24708.B lvcreate \-L 64M \-n lvol1 vg00 /dev/sda:0\-7 /dev/sdb:0\-7
24709
24710Creates a 5GiB RAID5 logical volume "vg00/my_lv", with 3 stripes (plus
24711a parity drive for a total of 4 devices) and a stripesize of 64KiB:
24712.sp
24713.B lvcreate \-\-type raid5 \-L 5G \-i 3 \-I 64 \-n my_lv vg00
24714
24715Creates a RAID5 logical volume "vg00/my_lv", using all of the free
24716space in the VG and spanning all the PVs in the VG (note that the command
24717will fail if there's more than 8 PVs in the VG in which case \fB\-i 7\fP
24718has to be used to get to the currently possible maximum of
247198 devices including parity for RaidLVs):
24720.sp
24721.B lvcreate \-\-config allocation/raid_stripe_all_devices=1 \-\-type raid5 \-l 100%FREE \-n my_lv vg00
24722
24723Creates a 5GiB RAID10 logical volume "vg00/my_lv", with 2 stripes on
247242 2-way mirrors. Note that the \fB-i\fP and \fB-m\fP arguments behave
24725differently.
24726The \fB-i\fP specifies the number of stripes.
24727The \fB-m\fP specifies the number of
24728.B additional
24729copies:
24730.sp
24731.B lvcreate \-\-type raid10 \-L 5G \-i 2 \-m 1 \-n my_lv vg00
24732
24733Creates 100MiB pool logical volume for thin provisioning
24734build with 2 stripes 64KiB and chunk size 256KiB together with
247351TiB thin provisioned logical volume "vg00/thin_lv":
24736.sp
24737.B lvcreate \-i 2 \-I 64 \-c 256 \-L100M \-T vg00/pool \-V 1T \-\-name thin_lv
24738
24739Creates a thin snapshot volume "thinsnap" of thin volume "thinvol" that
24740will share the same blocks within the thin pool.
24741Note: the size MUST NOT be specified, otherwise the non-thin snapshot
24742is created instead:
24743.sp
24744.B lvcreate \-s vg00/thinvol \-\-name thinsnap
24745
24746Creates a thin snapshot volume of read-only inactive volume "origin"
24747which then becomes the thin external origin for the thin snapshot volume
24748in vg00 that will use an existing thin pool "vg00/pool":
24749.sp
24750.B lvcreate \-s \-\-thinpool vg00/pool origin
24751
24752Create a cache pool LV that can later be used to cache one
24753logical volume.
24754.sp
24755.B lvcreate \-\-type cache-pool \-L 1G \-n my_lv_cachepool vg /dev/fast1
24756
24757If there is an existing cache pool LV, create the large slow
24758device (i.e. the origin LV) and link it to the supplied cache pool LV,
24759creating a cache LV.
24760.sp
24761.B lvcreate \-\-cache \-L 100G \-n my_lv vg/my_lv_cachepool /dev/slow1
24762
24763If there is an existing logical volume, create the small and fast
24764cache pool LV and link it to the supplied existing logical
24765volume (i.e. the origin LV), creating a cache LV.
24766.sp
24767.B lvcreate \-\-type cache \-L 1G \-n my_lv_cachepool vg/my_lv /dev/fast1
24768
24769.\" Create a 1G cached LV "lvol1" with 10M cache pool "vg00/pool".
24770.\" .sp
24771.\" .B lvcreate \-\-cache \-L 1G \-n lv \-\-pooldatasize 10M vg00/pool
24772.
24773.SH SEE ALSO
24774.
24775.nh
24776.BR lvm (8),
24777.BR lvm.conf (5),
24778.BR lvmcache (7),
24779.BR lvmthin (7),
24780.BR lvconvert (8),
24781.BR lvchange (8),
24782.BR lvextend (8),
24783.BR lvreduce (8),
24784.BR lvremove (8),
24785.BR lvrename (8)
24786.BR lvs (8),
24787.BR lvscan (8),
24788.BR vgcreate (8),
24789.BR blkid (8)
24790\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmlockd.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000065137\013062740170\0020147\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMLOCKD" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
24791
24792.SH NAME
24793lvmlockd \(em LVM locking daemon
24794
24795.SH DESCRIPTION
24796LVM commands use lvmlockd to coordinate access to shared storage.
24797.br
24798When LVM is used on devices shared by multiple hosts, locks will:
24799
24800\[bu]
24801coordinate reading and writing of LVM metadata
24802.br
24803\[bu]
24804validate caching of LVM metadata
24805.br
24806\[bu]
24807prevent concurrent activation of logical volumes
24808.br
24809
24810lvmlockd uses an external lock manager to perform basic locking.
24811.br
24812Lock manager (lock type) options are:
24813
24814\[bu]
24815sanlock: places locks on disk within LVM storage.
24816.br
24817\[bu]
24818dlm: uses network communication and a cluster manager.
24819.br
24820
24821.SH OPTIONS
24822
24823lvmlockd [options]
24824
24825For default settings, see lvmlockd \-h.
24826
24827.B \-\-help | \-h
24828 Show this help information.
24829
24830.B \-\-version | \-V
24831 Show version of lvmlockd.
24832
24833.B \-\-test | \-T
24834 Test mode, do not call lock manager.
24835
24836.B \-\-foreground | \-f
24837 Don't fork.
24838
24839.B \-\-daemon\-debug | \-D
24840 Don't fork and print debugging to stdout.
24841
24842.B \-\-pid\-file | \-p
24843.I path
24844 Set path to the pid file.
24845
24846.B \-\-socket\-path | \-s
24847.I path
24848 Set path to the socket to listen on.
24849
24850.B \-\-syslog\-priority | \-S err|warning|debug
24851 Write log messages from this level up to syslog.
24852
24853.B \-\-gl\-type | \-g sanlock|dlm
24854 Set global lock type to be sanlock or dlm.
24855
24856.B \-\-host\-id | \-i
24857.I num
24858 Set the local sanlock host id.
24859
24860.B \-\-host\-id\-file | \-F
24861.I path
24862 A file containing the local sanlock host_id.
24863
24864.B \-\-sanlock\-timeout | \-o
24865.I seconds
24866 Override the default sanlock I/O timeout.
24867
24868.B \-\-adopt | \-A 0|1
24869 Adopt locks from a previous instance of lvmlockd.
24870
24871
24872.SH USAGE
24873
24874.SS Initial set up
24875
24876Using LVM with lvmlockd for the first time includes some one\-time set up
24877steps:
24878
24879.SS 1. choose a lock manager
24880
24881.I dlm
24882.br
24883If dlm (or corosync) are already being used by other cluster
24884software, then select dlm. dlm uses corosync which requires additional
24885configuration beyond the scope of this document. See corosync and dlm
24886documentation for instructions on configuration, setup and usage.
24887
24888.I sanlock
24889.br
24890Choose sanlock if dlm/corosync are not otherwise required.
24891sanlock does not depend on any clustering software or configuration.
24892
24893.SS 2. configure hosts to use lvmlockd
24894
24895On all hosts running lvmlockd, configure lvm.conf:
24896.nf
24897locking_type = 1
24898use_lvmlockd = 1
24899.fi
24900
24901.I sanlock
24902.br
24903Assign each host a unique host_id in the range 1\-2000 by setting
24904.br
24905/etc/lvm/lvmlocal.conf local/host_id
24906
24907.SS 3. start lvmlockd
24908
24909Use a service/init file if available, or just run "lvmlockd".
24910
24911.SS 4. start lock manager
24912
24913.I sanlock
24914.br
24915systemctl start wdmd sanlock
24916
24917.I dlm
24918.br
24919Follow external clustering documentation when applicable, otherwise:
24920.br
24921systemctl start corosync dlm
24922
24923.SS 5. create VG on shared devices
24924
24925vgcreate \-\-shared <vgname> <devices>
24926
24927The shared option sets the VG lock type to sanlock or dlm depending on
24928which lock manager is running. LVM commands will perform locking for the
24929VG using lvmlockd. lvmlockd will use the chosen lock manager.
24930
24931.SS 6. start VG on all hosts
24932
24933vgchange \-\-lock\-start
24934
24935lvmlockd requires shared VGs to be started before they are used. This is
24936a lock manager operation to start (join) the VG lockspace, and it may take
24937some time. Until the start completes, locks for the VG are not available.
24938LVM commands are allowed to read the VG while start is in progress. (An
24939init/unit file can also be used to start VGs.)
24940
24941.SS 7. create and activate LVs
24942
24943Standard lvcreate and lvchange commands are used to create and activate
24944LVs in a shared VG.
24945
24946An LV activated exclusively on one host cannot be activated on another.
24947When multiple hosts need to use the same LV concurrently, the LV can be
24948activated with a shared lock (see lvchange options \-aey vs \-asy.)
24949(Shared locks are disallowed for certain LV types that cannot be used from
24950multiple hosts.)
24951
24952
24953.SS Normal start up and shut down
24954
24955After initial set up, start up and shut down include the following general
24956steps. They can be performed manually or using the system service
24957manager.
24958
24959\[bu]
24960start lvmetad
24961.br
24962\[bu]
24963start lvmlockd
24964.br
24965\[bu]
24966start lock manager
24967.br
24968\[bu]
24969vgchange \-\-lock\-start
24970.br
24971\[bu]
24972activate LVs in shared VGs
24973.br
24974
24975The shut down sequence is the reverse:
24976
24977\[bu]
24978deactivate LVs in shared VGs
24979.br
24980\[bu]
24981vgchange \-\-lock\-stop
24982.br
24983\[bu]
24984stop lock manager
24985.br
24986\[bu]
24987stop lvmlockd
24988.br
24989\[bu]
24990stop lvmetad
24991.br
24992
24993.P
24994
24995.SH TOPICS
24996
24997.SS VG access control
24998
24999The following terms are used to describe different forms of VG access
25000control.
25001
25002.I "lockd VG"
25003
25004A "lockd VG" is a shared VG that has a "lock type" of dlm or sanlock.
25005Using it requires lvmlockd. These VGs exist on shared storage that is
25006visible to multiple hosts. LVM commands use lvmlockd to perform locking
25007for these VGs when they are used.
25008
25009If the lock manager for the lock type is not available (e.g. not started
25010or failed), lvmlockd is unable to acquire locks for LVM commands. LVM
25011commands that only read the VG will generally be allowed to continue
25012without locks in this case (with a warning). Commands to modify or
25013activate the VG will fail without the necessary locks.
25014
25015.I "local VG"
25016
25017A "local VG" is meant to be used by a single host. It has no lock type or
25018lock type "none". LVM commands and lvmlockd do not perform locking for
25019these VGs. A local VG typically exists on local (non\-shared) devices and
25020cannot be used concurrently from different hosts.
25021
25022If a local VG does exist on shared devices, it should be owned by a single
25023host by having its system ID set, see
25024.BR lvmsystemid (7).
25025Only the host with a matching system ID can use the local VG. A VG
25026with no lock type and no system ID should be excluded from all but one
25027host using lvm.conf filters. Without any of these protections, a local VG
25028on shared devices can be easily damaged or destroyed.
25029
25030.I "clvm VG"
25031
25032A "clvm VG" is a VG on shared storage (like a lockd VG) that requires
25033clvmd for clustering. See below for converting a clvm VG to a lockd VG.
25034
25035
25036.SS lockd VGs from hosts not using lvmlockd
25037
25038Only hosts that use lockd VGs should be configured to run lvmlockd.
25039However, shared devices used by lockd VGs may be visible from hosts not
25040using lvmlockd. From a host not using lvmlockd, visible lockd VGs are
25041ignored in the same way as foreign VGs (see
25042.BR lvmsystemid (7).)
25043
25044The \-\-shared option for reporting and display commands causes lockd VGs
25045to be displayed on a host not using lvmlockd, like the \-\-foreign option
25046does for foreign VGs.
25047
25048
25049.SS vgcreate comparison
25050
25051The type of VG access control is specified in the vgcreate command.
25052See
25053.BR vgcreate (8)
25054for all vgcreate options.
25055
25056.B vgcreate <vgname> <devices>
25057
25058.IP \[bu] 2
25059Creates a local VG with the local system ID when neither lvmlockd nor clvm are configured.
25060.IP \[bu] 2
25061Creates a local VG with the local system ID when lvmlockd is configured.
25062.IP \[bu] 2
25063Creates a clvm VG when clvm is configured.
25064
25065.P
25066
25067.B vgcreate \-\-shared <vgname> <devices>
25068.IP \[bu] 2
25069Requires lvmlockd to be configured and running.
25070.IP \[bu] 2
25071Creates a lockd VG with lock type sanlock|dlm depending on which lock
25072manager is running.
25073.IP \[bu] 2
25074LVM commands request locks from lvmlockd to use the VG.
25075.IP \[bu] 2
25076lvmlockd obtains locks from the selected lock manager.
25077
25078.P
25079
25080.B vgcreate \-c|\-\-clustered y <vgname> <devices>
25081.IP \[bu] 2
25082Requires clvm to be configured and running.
25083.IP \[bu] 2
25084Creates a clvm VG with the "clustered" flag.
25085.IP \[bu] 2
25086LVM commands request locks from clvmd to use the VG.
25087
25088.P
25089
25090.SS creating the first sanlock VG
25091
25092Creating the first sanlock VG is not protected by locking and requires
25093special attention. This is because sanlock locks exist within the VG, so
25094they are not available until the VG exists. The first sanlock VG will
25095contain the "global lock".
25096
25097.IP \[bu] 2
25098The first vgcreate command needs to be given the path to a device that has
25099not yet been initialized with pvcreate. The pvcreate initialization will
25100be done by vgcreate. This is because the pvcreate command requires the
25101global lock, which will not be available until after the first sanlock VG
25102is created.
25103
25104.IP \[bu] 2
25105While running vgcreate for the first sanlock VG, ensure that the device
25106being used is not used by another LVM command. Allocation of shared
25107devices is usually protected by the global lock, but this cannot be done
25108for the first sanlock VG which will hold the global lock.
25109
25110.IP \[bu] 2
25111While running vgcreate for the first sanlock VG, ensure that the VG name
25112being used is not used by another LVM command. Uniqueness of VG names is
25113usually ensured by the global lock.
25114
25115.IP \[bu] 2
25116Because the first sanlock VG will contain the global lock, this VG needs
25117to be accessible to all hosts that will use sanlock shared VGs. All hosts
25118will need to use the global lock from the first sanlock VG.
25119
25120See below for more information about managing the sanlock global lock.
25121
25122
25123.SS using lockd VGs
25124
25125There are some special considerations when using lockd VGs.
25126
25127When use_lvmlockd is first enabled in lvm.conf, and before the first lockd
25128VG is created, no global lock will exist. In this initial state, LVM
25129commands try and fail to acquire the global lock, producing a warning, and
25130some commands are disallowed. Once the first lockd VG is created, the
25131global lock will be available, and LVM will be fully operational.
25132
25133When a new lockd VG is created, its lockspace is automatically started on
25134the host that creates it. Other hosts need to run 'vgchange
25135\-\-lock\-start' to start the new VG before they can use it.
25136
25137From the 'vgs' command, lockd VGs are indicated by "s" (for shared) in the
25138sixth attr field. The specific lock type and lock args for a lockd VG can
25139be displayed with 'vgs \-o+locktype,lockargs'.
25140
25141lockd VGs need to be "started" and "stopped", unlike other types of VGs.
25142See the following section for a full description of starting and stopping.
25143
25144vgremove of a lockd VG will fail if other hosts have the VG started.
25145Run vgchange \-\-lock-stop <vgname> on all other hosts before vgremove.
25146(It may take several seconds before vgremove recognizes that all hosts
25147have stopped a sanlock VG.)
25148
25149.SS starting and stopping VGs
25150
25151Starting a lockd VG (vgchange \-\-lock\-start) causes the lock manager to
25152start (join) the lockspace for the VG on the host where it is run. This
25153makes locks for the VG available to LVM commands on the host. Before a VG
25154is started, only LVM commands that read/display the VG are allowed to
25155continue without locks (and with a warning).
25156
25157Stopping a lockd VG (vgchange \-\-lock\-stop) causes the lock manager to
25158stop (leave) the lockspace for the VG on the host where it is run. This
25159makes locks for the VG inaccessible to the host. A VG cannot be stopped
25160while it has active LVs.
25161
25162When using the lock type sanlock, starting a VG can take a long time
25163(potentially minutes if the host was previously shut down without cleanly
25164stopping the VG.)
25165
25166A lockd VG can be started after all the following are true:
25167.br
25168\[bu]
25169lvmlockd is running
25170.br
25171\[bu]
25172the lock manager is running
25173.br
25174\[bu]
25175the VG is visible to the system
25176.br
25177
25178A lockd VG can be stopped if all LVs are deactivated.
25179
25180All lockd VGs can be started/stopped using:
25181.br
25182vgchange \-\-lock-start
25183.br
25184vgchange \-\-lock-stop
25185
25186
25187Individual VGs can be started/stopped using:
25188.br
25189vgchange \-\-lock\-start <vgname> ...
25190.br
25191vgchange \-\-lock\-stop <vgname> ...
25192
25193To make vgchange not wait for start to complete:
25194.br
25195vgchange \-\-lock\-start \-\-lock\-opt nowait ...
25196
25197lvmlockd can be asked directly to stop all lockspaces:
25198.br
25199lvmlockctl \-\-stop\-lockspaces
25200
25201To start only selected lockd VGs, use the lvm.conf
25202activation/lock_start_list. When defined, only VG names in this list are
25203started by vgchange. If the list is not defined (the default), all
25204visible lockd VGs are started. To start only "vg1", use the following
25205lvm.conf configuration:
25206
25207.nf
25208activation {
25209 lock_start_list = [ "vg1" ]
25210 ...
25211}
25212.fi
25213
25214
25215.SS automatic starting and automatic activation
25216
25217Scripts or programs on a host that automatically start VGs will use the
25218"auto" option to indicate that the command is being run automatically by
25219the system:
25220
25221vgchange \-\-lock\-start \-\-lock\-opt auto [<vgname> ...]
25222
25223Without any additional configuration, including the "auto" option has no
25224effect; all VGs are started unless restricted by lock_start_list.
25225
25226However, when the lvm.conf activation/auto_lock_start_list is defined, the
25227auto start command performs an additional filtering phase to all VGs being
25228started, testing each VG name against the auto_lock_start_list. The
25229auto_lock_start_list defines lockd VGs that will be started by the auto
25230start command. Visible lockd VGs not included in the list are ignored by
25231the auto start command. If the list is undefined, all VG names pass this
25232filter. (The lock_start_list is also still used to filter all VGs.)
25233
25234The auto_lock_start_list allows a user to select certain lockd VGs that
25235should be automatically started by the system (or indirectly, those that
25236should not).
25237
25238To use auto activation of lockd LVs (see auto_activation_volume_list),
25239auto starting of the corresponding lockd VGs is necessary.
25240
25241
25242.SS internal command locking
25243
25244To optimize the use of LVM with lvmlockd, be aware of the three kinds of
25245locks and when they are used:
25246
25247.I GL lock
25248
25249The global lock (GL lock) is associated with global information, which is
25250information not isolated to a single VG. This includes:
25251
25252\[bu]
25253The global VG namespace.
25254.br
25255\[bu]
25256The set of orphan PVs and unused devices.
25257.br
25258\[bu]
25259The properties of orphan PVs, e.g. PV size.
25260.br
25261
25262The global lock is used in shared mode by commands that read this
25263information, or in exclusive mode by commands that change it.
25264
25265The command 'vgs' acquires the global lock in shared mode because it
25266reports the list of all VG names.
25267
25268The vgcreate command acquires the global lock in exclusive mode because it
25269creates a new VG name, and it takes a PV from the list of unused PVs.
25270
25271When an LVM command is given a tag argument, or uses select, it must read
25272all VGs to match the tag or selection, which causes the global lock to be
25273acquired.
25274
25275.I VG lock
25276
25277A VG lock is associated with each VG. The VG lock is acquired in shared
25278mode to read the VG and in exclusive mode to change the VG (modify the VG
25279metadata or activate LVs). This lock serializes access to a VG with all
25280other LVM commands accessing the VG from all hosts.
25281
25282The command 'vgs' will not only acquire the GL lock to read the list of
25283all VG names, but will acquire the VG lock for each VG prior to reading
25284it.
25285
25286The command 'vgs <vgname>' does not acquire the GL lock (it does not need
25287the list of all VG names), but will acquire the VG lock on each VG name
25288argument.
25289
25290.I LV lock
25291
25292An LV lock is acquired before the LV is activated, and is released after
25293the LV is deactivated. If the LV lock cannot be acquired, the LV is not
25294activated. LV locks are persistent and remain in place after the
25295activation command is done. GL and VG locks are transient, and are held
25296only while an LVM command is running.
25297
25298.I lock retries
25299
25300If a request for a GL or VG lock fails due to a lock conflict with another
25301host, lvmlockd automatically retries for a short time before returning a
25302failure to the LVM command. If those retries are insufficient, the LVM
25303command will retry the entire lock request a number of times specified by
25304global/lvmlockd_lock_retries before failing. If a request for an LV lock
25305fails due to a lock conflict, the command fails immediately.
25306
25307
25308.SS managing the global lock in sanlock VGs
25309
25310The global lock exists in one of the sanlock VGs. The first sanlock VG
25311created will contain the global lock. Subsequent sanlock VGs will each
25312contain disabled global locks that can be enabled later if necessary.
25313
25314The VG containing the global lock must be visible to all hosts using
25315sanlock VGs. This can be a reason to create a small sanlock VG, visible
25316to all hosts, and dedicated to just holding the global lock. While not
25317required, this strategy can help to avoid difficulty in the future if VGs
25318are moved or removed.
25319
25320The vgcreate command typically acquires the global lock, but in the case
25321of the first sanlock VG, there will be no global lock to acquire until the
25322first vgcreate is complete. So, creating the first sanlock VG is a
25323special case that skips the global lock.
25324
25325vgcreate for a sanlock VG determines it is the first one to exist if no
25326other sanlock VGs are visible. It is possible that other sanlock VGs do
25327exist but are not visible on the host running vgcreate. In this case,
25328vgcreate would create a new sanlock VG with the global lock enabled. When
25329the other VG containing a global lock appears, lvmlockd will see more than
25330one VG with a global lock enabled, and LVM commands will report that there
25331are duplicate global locks.
25332
25333If the situation arises where more than one sanlock VG contains a global
25334lock, the global lock should be manually disabled in all but one of them
25335with the command:
25336
25337lvmlockctl \-\-gl\-disable <vgname>
25338
25339(The one VG with the global lock enabled must be visible to all hosts.)
25340
25341An opposite problem can occur if the VG holding the global lock is
25342removed. In this case, no global lock will exist following the vgremove,
25343and subsequent LVM commands will fail to acquire it. In this case, the
25344global lock needs to be manually enabled in one of the remaining sanlock
25345VGs with the command:
25346
25347lvmlockctl \-\-gl\-enable <vgname>
25348
25349A small sanlock VG dedicated to holding the global lock can avoid the case
25350where the GL lock must be manually enabled after a vgremove.
25351
25352
25353.SS internal lvmlock LV
25354
25355A sanlock VG contains a hidden LV called "lvmlock" that holds the sanlock
25356locks. vgreduce cannot yet remove the PV holding the lvmlock LV. To
25357remove this PV, change the VG lock type to "none", run vgreduce, then
25358change the VG lock type back to "sanlock". Similarly, pvmove cannot be
25359used on a PV used by the lvmlock LV.
25360
25361To place the lvmlock LV on a specific device, create the VG with only that
25362device, then use vgextend to add other devices.
25363
25364
25365.SS shared LVs
25366
25367When an LV is used concurrently from multiple hosts (e.g. by a
25368multi\-host/cluster application or file system), the LV can be activated
25369on multiple hosts concurrently using a shared lock.
25370
25371To activate the LV with a shared lock: lvchange \-asy vg/lv.
25372
25373With lvmlockd, an unspecified activation mode is always exclusive, i.e.
25374\-ay defaults to \-aey.
25375
25376If the LV type does not allow the LV to be used concurrently from multiple
25377hosts, then a shared activation lock is not allowed and the lvchange
25378command will report an error. LV types that cannot be used concurrently
25379from multiple hosts include thin, cache, raid, mirror, and snapshot.
25380
25381lvextend on LV with shared locks is not yet allowed. The LV must be
25382deactivated, or activated exclusively to run lvextend.
25383
25384
25385.SS recover from lost PV holding sanlock locks
25386
25387The general approach is to change the VG lock type to "none", and then
25388change the lock type back to "sanlock". This recreates the internal
25389lvmlock LV and the necessary locks on it. Additional steps may be
25390required to deal with the missing PV.
25391
25392
25393.SS locking system failures
25394
25395.B lvmlockd failure
25396
25397If lvmlockd fails or is killed while holding locks, the locks are orphaned
25398in the lock manager. lvmlockd can be restarted with an option to adopt
25399locks in the lock manager that had been held by the previous instance.
25400
25401.B dlm/corosync failure
25402
25403If dlm or corosync fail, the clustering system will fence the host using a
25404method configured within the dlm/corosync clustering environment.
25405
25406LVM commands on other hosts will be blocked from acquiring any locks until
25407the dlm/corosync recovery process is complete.
25408
25409.B sanlock lease storage failure
25410
25411If the PV under a sanlock VG's lvmlock LV is disconnected, unresponsive or
25412too slow, sanlock cannot renew the lease for the VG's locks. After some
25413time, the lease will expire, and locks that the host owns in the VG can be
25414acquired by other hosts. The VG must be forcibly deactivated on the host
25415with the expiring lease before other hosts can acquire its locks.
25416
25417When the sanlock daemon detects that the lease storage is lost, it runs
25418the command lvmlockctl \-\-kill <vgname>. This command emits a syslog
25419message stating that lease storage is lost for the VG and LVs must be
25420immediately deactivated.
25421
25422If no LVs are active in the VG, then the lockspace with an expiring lease
25423will be removed, and errors will be reported when trying to use the VG.
25424Use the lvmlockctl \-\-drop command to clear the stale lockspace from
25425lvmlockd.
25426
25427If the VG has active LVs when the lock storage is lost, the LVs must be
25428quickly deactivated before the lockspace lease expires. After all LVs are
25429deactivated, run lvmlockctl \-\-drop <vgname> to clear the expiring
25430lockspace from lvmlockd. If all LVs in the VG are not deactivated within
25431about 40 seconds, sanlock will reset the host using the local watchdog.
25432The machine reset is effectively a severe form of "deactivating" LVs
25433before they can be activated on other hosts. The reset is considered a
25434better alternative than having LVs used by multiple hosts at once, which
25435could easily damage or destroy their content.
25436
25437In the future, the lvmlockctl kill command may automatically attempt to
25438forcibly deactivate LVs before the sanlock lease expires. Until then, the
25439user must notice the syslog message and manually deactivate the VG before
25440sanlock resets the machine.
25441
25442.B sanlock daemon failure
25443
25444If the sanlock daemon fails or exits while a lockspace is started, the
25445local watchdog will reset the host. This is necessary to protect any
25446application resources that depend on sanlock leases which will be lost
25447without sanlock running.
25448
25449
25450.SS changing dlm cluster name
25451
25452When a dlm VG is created, the cluster name is saved in the VG metadata.
25453To use the VG, a host must be in the named dlm cluster. If the dlm
25454cluster name changes, or the VG is moved to a new cluster, the dlm cluster
25455name saved in the VG must also be changed.
25456
25457To see the dlm cluster name saved in the VG, use the command:
25458.br
25459vgs -o+locktype,lockargs <vgname>
25460
25461To change the dlm cluster name in the VG when the VG is still used by the
25462original cluster:
25463
25464.IP \[bu] 2
25465Stop the VG on all hosts:
25466.br
25467vgchange --lock-stop <vgname>
25468
25469.IP \[bu] 2
25470Change the VG lock type to none:
25471.br
25472vgchange \-\-lock\-type none <vgname>
25473
25474.IP \[bu] 2
25475Change the dlm cluster name on the host or move the VG to the new cluster.
25476The new dlm cluster must now be active on the host. Verify the new name
25477by:
25478.br
25479cat /sys/kernel/config/dlm/cluster/cluster_name
25480
25481.IP \[bu] 2
25482Change the VG lock type back to dlm which sets the new cluster name:
25483.br
25484vgchange \-\-lock\-type dlm <vgname>
25485
25486.IP \[bu] 2
25487Start the VG on hosts to use it:
25488.br
25489vgchange --lock-start <vgname>
25490
25491.P
25492
25493To change the dlm cluster name in the VG when the dlm cluster name has
25494already changed, or the VG has already moved to a different cluster:
25495
25496.IP \[bu] 2
25497Ensure the VG is not being used by any hosts.
25498
25499.IP \[bu] 2
25500The new dlm cluster must be active on the host making the change.
25501The current dlm cluster name can be seen by:
25502.br
25503cat /sys/kernel/config/dlm/cluster/cluster_name
25504
25505.IP \[bu] 2
25506Change the VG lock type to none:
25507.br
25508vgchange \-\-lock\-type none \-\-force <vgname>
25509
25510.IP \[bu] 2
25511Change the VG lock type back to dlm which sets the new cluster name:
25512.br
25513vgchange \-\-lock\-type dlm <vgname>
25514
25515.IP \[bu] 2
25516Start the VG on hosts to use it:
25517.br
25518vgchange --lock-start <vgname>
25519
25520
25521.SS changing a local VG to a lockd VG
25522
25523All LVs must be inactive to change the lock type.
25524
25525lvmlockd must be configured and running as described in USAGE.
25526
25527Change a local VG to a lockd VG with the command:
25528.br
25529vgchange \-\-lock\-type sanlock|dlm <vgname>
25530
25531Start the VG on hosts to use it:
25532.br
25533vgchange \-\-lock\-start <vgname>
25534
25535
25536.SS changing a lockd VG to a local VG
25537
25538Stop the lockd VG on all hosts, then run:
25539.br
25540vgchange \-\-lock\-type none <vgname>
25541
25542To change a VG from one lockd type to another (i.e. between sanlock and
25543dlm), first change it to a local VG, then to the new type.
25544
25545
25546.SS changing a clvm VG to a lockd VG
25547
25548All LVs must be inactive to change the lock type.
25549
25550First change the clvm VG to a local VG. Within a running clvm cluster,
25551change a clvm VG to a local VG with the command:
25552
25553vgchange \-cn <vgname>
25554
25555If the clvm cluster is no longer running on any nodes, then extra options
25556can be used to forcibly make the VG local. Caution: this is only safe if
25557all nodes have stopped using the VG:
25558
25559vgchange \-\-config 'global/locking_type=0 global/use_lvmlockd=0'
25560.RS
25561\-cn <vgname>
25562.RE
25563
25564After the VG is local, follow the steps described in "changing a local VG
25565to a lockd VG".
25566
25567
25568.SS limitations of lockd VGs
25569
25570Things that do not yet work in lockd VGs:
25571.br
25572\[bu]
25573creating a new thin pool and a new thin LV in a single command
25574.br
25575\[bu]
25576using lvcreate to create cache pools or cache LVs (use lvconvert)
25577.br
25578\[bu]
25579using external origins for thin LVs
25580.br
25581\[bu]
25582splitting mirrors and snapshots from LVs
25583.br
25584\[bu]
25585vgsplit
25586.br
25587\[bu]
25588vgmerge
25589.br
25590\[bu]
25591resizing an LV that is active in the shared mode on multiple hosts
25592
25593
25594.SS lvmlockd changes from clvmd
25595
25596(See above for converting an existing clvm VG to a lockd VG.)
25597
25598While lvmlockd and clvmd are entirely different systems, LVM command usage
25599remains similar. Differences are more notable when using lvmlockd's
25600sanlock option.
25601
25602Visible usage differences between lockd VGs with lvmlockd and clvm VGs
25603with clvmd:
25604
25605.IP \[bu] 2
25606lvm.conf must be configured to use either lvmlockd (use_lvmlockd=1) or
25607clvmd (locking_type=3), but not both.
25608
25609.IP \[bu] 2
25610vgcreate \-\-shared creates a lockd VG, and vgcreate \-\-clustered y
25611creates a clvm VG.
25612
25613.IP \[bu] 2
25614lvmlockd adds the option of using sanlock for locking, avoiding the
25615need for network clustering.
25616
25617.IP \[bu] 2
25618lvmlockd defaults to the exclusive activation mode whenever the activation
25619mode is unspecified, i.e. \-ay means \-aey, not \-asy.
25620
25621.IP \[bu] 2
25622lvmlockd commands always apply to the local host, and never have an effect
25623on a remote host. (The activation option 'l' is not used.)
25624
25625.IP \[bu] 2
25626lvmlockd works with thin and cache pools and LVs.
25627
25628.IP \[bu] 2
25629lvmlockd works with lvmetad.
25630
25631.IP \[bu] 2
25632lvmlockd saves the cluster name for a lockd VG using dlm. Only hosts in
25633the matching cluster can use the VG.
25634
25635.IP \[bu] 2
25636lvmlockd requires starting/stopping lockd VGs with vgchange \-\-lock-start
25637and \-\-lock-stop.
25638
25639.IP \[bu] 2
25640vgremove of a sanlock VG may fail indicating that all hosts have not
25641stopped the VG lockspace. Stop the VG on all hosts using vgchange
25642\-\-lock-stop.
25643
25644.IP \[bu] 2
25645vgreduce or pvmove of a PV in a sanlock VG will fail if it holds the
25646internal "lvmlock" LV that holds the sanlock locks.
25647
25648.IP \[bu] 2
25649lvmlockd uses lock retries instead of lock queueing, so high lock
25650contention may require increasing global/lvmlockd_lock_retries to
25651avoid transient lock failures.
25652
25653.IP \[bu] 2
25654lvmlockd includes VG reporting options lock_type and lock_args, and LV
25655reporting option lock_args to view the corresponding metadata fields.
25656
25657.IP \[bu] 2
25658In the 'vgs' command's sixth VG attr field, "s" for "shared" is displayed
25659for lockd VGs.
25660
25661.IP \[bu] 2
25662If lvmlockd fails or is killed while in use, locks it held remain but are
25663orphaned in the lock manager. lvmlockd can be restarted with an option to
25664adopt the orphan locks from the previous instance of lvmlockd.
25665
25666.P
25667\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgdisplay.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006402\013062740170\0020324\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
25668.SH NAME
25669vgdisplay \(em display attributes of volume groups
25670.SH SYNOPSIS
25671.B vgdisplay
25672.RB [ \-A | \-\-activevolumegroups ]
25673.RB [ \-c | \-\-colon ]
25674.RB [ \-\-commandprofile
25675.IR ProfileName ]
25676.RB [ \-\-reportformat
25677.RB { basic | json }]
25678.RB [ \-s | \-\-short ]
25679.RB [ \-S | \-\-select
25680.IR Selection ]
25681.RB [ \-v | \-\-verbose ]
25682.RB [ \-d | \-\-debug ]
25683.RB [ \-h | \-\-help ]
25684.RB [ \-\-ignorelockingfailure ]
25685.RB [ \-\-ignoreskippedcluster ]
25686.RB [ \-\-nosuffix ]
25687.RB [ \-P | \-\-partial ]
25688.RB [ \-\-units
25689.IR hHbBsSkKmMgGtTpPeE ]
25690.RB [ \-\-version ]
25691.RI [ VolumeGroupName ...]
25692.br
25693
25694.br
25695.B vgdisplay
25696.BR \-C | \-\-columns
25697.RB [ \-\-aligned ]
25698.RB [ \-\-binary ]
25699.RB [ \-\-commandprofile
25700.IR ProfileName ]
25701.RB [[ \-\-configreport
25702.IR ReportName ]
25703.RB [ \-o | \-\-options
25704.RI [ + | \- | # ] Field1 [, Field2 ...]
25705.RB [ \-O | \-\-sort
25706.RI [ + | \- ] Key1 [, Key2 ...]]
25707.RB [ \-S | \-\-select
25708.IR Selection ]
25709.RB ...]
25710.RB [ \-d | \-\-debug ]
25711.RB [ \-h | \-? | \-\-help ]
25712.RB [ \-\-ignorelockingfailure ]
25713.RB [ \-\-ignoreskippedcluster ]
25714.RB [ \-\-logonly ]
25715.RB [ \-\-noheadings ]
25716.RB [ \-\-nosuffix ]
25717.RB [ \-P | \-\-partial ]
25718.RB [ \-\-reportformat
25719.RB { basic | json }]
25720.RB [ \-\-separator
25721.IR Separator ]
25722.RB [ \-\-unbuffered ]
25723.RB [ \-\-units
25724.IR hHbBsSkKmMgGtTpPeE ]
25725.RB [ \-v | \-\-verbose ]
25726.RB [ \-\-version ]
25727.RI [ VolumeGroupName ...]
25728.SH DESCRIPTION
25729vgdisplay allows you to see the attributes of
25730.I VolumeGroupName
25731(or all volume groups if none is given) with it's physical and logical
25732volumes and their sizes etc.
25733.P
25734\fBvgs\fP(8) is an alternative that provides the same information
25735in the style of \fBps\fP(1).
25736.SH OPTIONS
25737See \fBlvm\fP(8) for common options.
25738.TP
25739.BR \-A ", " \-\-activevolumegroups
25740Only select the active volume groups. The volume group is considered active
25741if at least one of its logical volumes is active.
25742.TP
25743.BR \-C ", " \-\-columns
25744Display output in columns, the equivalent of \fBvgs\fP(8).
25745Options listed are the same as options given in \fPvgs\fP(8).
25746.TP
25747.BR \-c ", " \-\-colon
25748Generate colon separated output for easier parsing in scripts or programs.
25749N.B. \fBvgs\fP(8) provides considerably more control over the output.
25750.nf
25751
25752The values are:
25753
257541 volume group name
257552 volume group access
257563 volume group status
257574 internal volume group number
257585 maximum number of logical volumes
257596 current number of logical volumes
257607 open count of all logical volumes in this volume group
257618 maximum logical volume size
257629 maximum number of physical volumes
2576310 current number of physical volumes
2576411 actual number of physical volumes
2576512 size of volume group in kilobytes
2576613 physical extent size
2576714 total number of physical extents for this volume group
2576815 allocated number of physical extents for this volume group
2576916 free number of physical extents for this volume group
2577017 uuid of volume group
25771
25772.fi
25773.TP
25774.BR \-s ", " \-\-short
25775Give a short listing showing the existence of volume groups.
25776.TP
25777.BR \-v ", " \-\-verbose
25778Display verbose information containing long listings of physical
25779and logical volumes. If given twice, also display verbose runtime
25780information of vgdisplay's activities.
25781.TP
25782.B \-\-version
25783Display version and exit successfully.
25784.SH SEE ALSO
25785.BR lvm (8),
25786.BR vgs (8),
25787.BR pvcreate (8),
25788.BR vgcreate (8),
25789.BR lvcreate (8)
25790\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvchange.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000037506\013062740170\0020122\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
25791
25792.de UNITS
25793..
25794
25795.
25796.SH NAME
25797.
25798lvchange \(em change attributes of a logical volume
25799.
25800.SH SYNOPSIS
25801.
25802.ad l
25803.B lvchange
25804.RB [ \-a | \-\-activate
25805.RB [ a ][ e | s | l ]{ y | n }]
25806.RB [ \-\-activationmode
25807.RB { complete | degraded | partial }]
25808.RB [ \-\-addtag
25809.IR Tag ]
25810.RB [ \-K | \-\-ignoreactivationskip ]
25811.RB [ \-k | \-\-setactivationskip
25812.RB { y | n }]
25813.RB [ \-\-alloc
25814.IR AllocationPolicy ]
25815.RB [ \-A | \-\-autobackup
25816.RB { y | n }]
25817.RB [ \-\-rebuild
25818.IR PhysicalVolume ]
25819.RB [ \-\-cachemode
25820.RB { passthrough | writeback | writethrough }]
25821.RB [ \-\-cachepolicy
25822.IR Policy ]
25823.RB [ \-\-cachesettings
25824.IR Key \fB= Value ]
25825.RB [ \-\-commandprofile
25826.IR ProfileName ]
25827.RB [ \-C | \-\-contiguous
25828.RB { y | n }]
25829.RB [ \-d | \-\-debug ]
25830.RB [ \-\-deltag
25831.IR Tag ]
25832.RB [ \-\-detachprofile ]
25833.RB [ \-\-discards
25834.RB { ignore | nopassdown | passdown }]
25835.RB [ \-\-errorwhenfull
25836.RB { y | n }]
25837.RB [ \-h | \-? | \-\-help ]
25838.RB \%[ \-\-ignorelockingfailure ]
25839.RB \%[ \-\-ignoremonitoring ]
25840.RB \%[ \-\-ignoreskippedcluster ]
25841.RB \%[ \-\-metadataprofile
25842.IR ProfileName ]
25843.RB [ \-\-monitor
25844.RB { y | n }]
25845.RB [ \-\-noudevsync ]
25846.RB [ \-P | \-\-partial ]
25847.RB [ \-p | \-\-permission
25848.RB { r | rw }]
25849.RB [ \-M | \-\-persistent
25850.RB { y | n }
25851.RB [ \-\-major
25852.IR Major ]
25853.RB [ \-\-minor
25854.IR Minor ]]
25855.RB [ \-\-poll
25856.RB { y | n }]
25857.RB [ \-\- [ raid ] maxrecoveryrate
25858.IR Rate ]
25859.RB [ \-\- [ raid ] minrecoveryrate
25860.IR Rate ]
25861.RB [ \-\- [ raid ] syncaction
25862.RB { check | repair }]
25863.RB [ \-\- [ raid ] writebehind
25864.IR IOCount ]
25865.RB [ \-\- [ raid ] writemostly
25866.BR \fIPhysicalVolume [ : { y | n | t }]]
25867.RB [ \-r | \-\-readahead
25868.RB { \fIReadAheadSectors | auto | none }]
25869.RB [ \-\-refresh ]
25870.RB [ \-\-reportformat
25871.RB { basic | json }]
25872.RB [ \-\-resync ]
25873.RB [ \-S | \-\-select
25874.IR Selection ]
25875.RB [ \-\-sysinit ]
25876.RB [ \-t | \-\-test ]
25877.RB [ \-v | \-\-verbose ]
25878.RB [ \-Z | \-\-zero
25879.RB { y | n }]
25880.RI [ LogicalVolumePath ...]
25881.ad b
25882.
25883.SH DESCRIPTION
25884.
25885lvchange allows you to change the attributes of a logical volume
25886including making them known to the kernel ready for use.
25887.
25888.SH OPTIONS
25889.
25890See \fBlvm\fP(8) for common options.
25891.
25892.HP
25893.BR \-a | \-\-activate
25894.RB [ a ][ e | s | l ]{ y | n }
25895.br
25896Controls the availability of the logical volumes for use.
25897Communicates with the kernel device-mapper driver via
25898libdevmapper to activate (\fB\-ay\fP) or deactivate (\fB\-an\fP) the
25899logical volumes.
25900.br
25901Activation of a logical volume creates a symbolic link
25902\fI/dev/VolumeGroupName/LogicalVolumeName\fP pointing to the device node.
25903This link is removed on deactivation.
25904All software and scripts should access the device through
25905this symbolic link and present this as the name of the device.
25906The location and name of the underlying device node may depend on
25907the distribution and configuration (e.g. udev) and might change
25908from release to release.
25909.br
25910If autoactivation option is used (\fB\-aay\fP),
25911the logical volume is activated only if it matches an item in
25912the \fBactivation/auto_activation_volume_list\fP
25913set in \fBlvm.conf\fP(5).
25914If this list is not set, then all volumes are considered for
25915activation. The \fB\-aay\fP option should be also used during system
25916boot so it's possible to select which volumes to activate using
25917the \fBactivation/auto_activation_volume_list\fP setting.
25918.br
25919In a clustered VG, clvmd is used for activation, and the
25920following options are possible:
25921
25922With \fB\-aey\fP, clvmd activates the LV in exclusive mode
25923(with an exclusive lock), allowing a single node to activate the LV.
25924
25925With \fB\-asy\fP, clvmd activates the LV in shared mode
25926(with a shared lock), allowing multiple nodes to activate the LV concurrently.
25927If the LV type prohibits shared access, such as an LV with a snapshot,
25928the '\fBs\fP' option is ignored and an exclusive lock is used.
25929
25930With \fB\-ay\fP (no mode specified), clvmd activates the LV in shared mode
25931if the LV type allows concurrent access, such as a linear LV.
25932Otherwise, clvmd activates the LV in exclusive mode.
25933
25934With \fB\-aey\fP, \fB\-asy\fP, and \fB\-ay\fP, clvmd attempts to activate the LV
25935on all nodes. If exclusive mode is used, then only one of the
25936nodes will be successful.
25937
25938With \fB\-an\fP, clvmd attempts to deactivate the LV on all nodes.
25939
25940With \fB\-aly\fP, clvmd activates the LV only on the local node, and \fB\-aln\fP
25941deactivates only on the local node. If the LV type allows concurrent
25942access, then shared mode is used, otherwise exclusive.
25943
25944LVs with snapshots are always activated exclusively because they can only
25945be used on one node at once.
25946
25947For local VGs \fB\-ay\fP, \fB\-aey\fP, and \fB\-asy\fP are all equivalent.
25948.
25949.HP
25950.BR \-\-activationmode
25951.RB { complete | degraded | partial }
25952.br
25953The activation mode determines whether logical volumes are allowed to
25954activate when there are physical volumes missing (e.g. due to a device
25955failure). \fBcomplete\fP is the most restrictive; allowing only those
25956logical volumes to be activated that are not affected by the missing
25957PVs. \fBdegraded\fP allows RAID logical volumes to be activated even if
25958they have PVs missing. (Note that the "\fImirror\fP" segment type is not
25959considered a RAID logical volume. The "\fIraid1\fP" segment type should
25960be used instead.) Finally, \fBpartial\fP allows any logical volume to
25961be activated even if portions are missing due to a missing or failed
25962PV. This last option should only be used when performing recovery or
25963repair operations. \fBdegraded\fP is the default mode. To change it,
25964modify \fBactivation_mode\fP in \fBlvm.conf\fP(5).
25965.
25966.HP
25967.BR \-K | \-\-ignoreactivationskip
25968.br
25969Ignore the flag to skip Logical Volumes during activation.
25970.
25971.HP
25972.BR \-k | \-\-setactivationskip
25973.RB { y | n }
25974.br
25975Controls whether Logical Volumes are persistently flagged to be
25976skipped during activation. By default, thin snapshot volumes are
25977flagged for activation skip. To activate such volumes,
25978an extra \fB\-\-ignoreactivationskip\fP option must be used.
25979The flag is not applied during deactivation. To see whether
25980the flag is attached, use \fBlvs\fP(8) command where the state
25981of the flag is reported within \fBlv_attr\fP bits.
25982.
25983.HP
25984.BR \-\-cachemode
25985.RB { passthrough | writeback | writethrough }
25986.br
25987Specifying a cache mode determines when the writes to a cache LV
25988are considered complete. When \fBwriteback\fP is specified, a write is
25989considered complete as soon as it is stored in the cache pool LV.
25990If \fBwritethough\fP is specified, a write is considered complete only
25991when it has been stored in the cache pool LV and on the origin LV.
25992While \fBwritethrough\fP may be slower for writes, it is more
25993resilient if something should happen to a device associated with the
25994cache pool LV. With \fBpassthrough\fP mode, all reads are served
25995from origin LV (all reads miss the cache) and all writes are
25996forwarded to the origin LV; additionally, write hits cause cache
25997block invalidates. See \fBlvmcache(7)\fP for more details.
25998.
25999.HP
26000.BR \-\-cachepolicy
26001.IR Policy ,
26002.BR \-\-cachesettings
26003.IR Key \fB= Value
26004.br
26005Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
26006the cache policy and its associated tunable settings. In most use-cases,
26007default values should be adequate.
26008.
26009.HP
26010.BR \-C | \-\-contiguous
26011.RB { y | n }
26012.br
26013Tries to set or reset the contiguous allocation policy for
26014logical volumes. It's only possible to change a non-contiguous
26015logical volume's allocation policy to contiguous, if all of the
26016allocated physical extents are already contiguous.
26017.
26018.HP
26019.BR \-\-detachprofile
26020.br
26021Detach any metadata configuration profiles attached to given
26022Logical Volumes. See \fBlvm.conf\fP(5) for more information
26023about metadata profiles.
26024.
26025.HP
26026.BR \-\-discards
26027.RB { ignore | nopassdown | passdown }
26028.br
26029Set this to \fBignore\fP to ignore any discards received by a
26030thin pool Logical Volume. Set to \fBnopassdown\fP to process such
26031discards within the thin pool itself and allow the no-longer-needed
26032extents to be overwritten by new data. Set to \fBpassdown\fP (the
26033default) to process them both within the thin pool itself and to
26034pass them down the underlying device.
26035.
26036.HP
26037.BR \-\-errorwhenfull
26038.RB { y | n }
26039.br
26040Sets thin pool behavior when data space is exhaused. See
26041.BR lvcreate (8)
26042for information.
26043.
26044.HP
26045.BR \-\-ignoremonitoring
26046.br
26047Make no attempt to interact with dmeventd unless \fB\-\-monitor\fP
26048is specified.
26049Do not use this if dmeventd is already monitoring a device.
26050.
26051.HP
26052.BR \-\-major
26053.IR Major
26054.br
26055Sets the major number. This option is supported only on older systems
26056(kernel version 2.4) and is ignored on modern Linux systems where major
26057numbers are dynamically assigned.
26058.
26059.HP
26060.BR \-\-minor
26061.IR Minor
26062.br
26063Set the minor number.
26064.
26065.HP
26066.BR \-\-metadataprofile
26067.IR ProfileName
26068.br
26069Uses and attaches \fIProfileName\fP configuration profile to the logical
26070volume metadata. Whenever the logical volume is processed next time,
26071the profile is automatically applied. If the volume group has another
26072profile attached, the logical volume profile is preferred.
26073See \fBlvm.conf\fP(5) for more information about metadata profiles.
26074.
26075.HP
26076.BR \-\-monitor
26077.RB { y | n }
26078.br
26079Start or stop monitoring a mirrored or snapshot logical volume with
26080dmeventd, if it is installed.
26081If a device used by a monitored mirror reports an I/O error,
26082the failure is handled according to
26083\%\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
26084set in \fBlvm.conf\fP(5).
26085.
26086.HP
26087.BR \-\-noudevsync
26088.br
26089Disable udev synchronisation. The
26090process will not wait for notification from udev.
26091It will continue irrespective of any possible udev processing
26092in the background. You should only use this if udev is not running
26093or has rules that ignore the devices LVM2 creates.
26094.
26095.HP
26096.BR \-p | \-\-permission
26097.RB { r | rw }
26098.br
26099Change access permission to read-only or read/write.
26100.
26101.HP
26102.BR \-M | \-\-persistent
26103.RB { y | n }
26104.br
26105Set to \fBy\fP to make the minor number specified persistent.
26106Change of persistent numbers is not supported for pool volumes.
26107.
26108.HP
26109.BR \-\-poll
26110.RB { y | n }
26111.br
26112Without polling a logical volume's backgrounded transformation process
26113will never complete. If there is an incomplete pvmove or lvconvert (for
26114example, on rebooting after a crash), use \fB\-\-poll y\fP to restart the
26115process from its last checkpoint. However, it may not be appropriate to
26116immediately poll a logical volume when it is activated, use
26117\fB\-\-poll n\fP to defer and then \fB\-\-poll y\fP to restart the process.
26118.
26119.HP
26120.BR \-\- [ raid ] rebuild
26121.BR \fIPhysicalVolume
26122.br
26123Option can be repeated multiple times.
26124Selects PhysicalVolume(s) to be rebuild in a RaidLV.
26125Use this option instead of
26126.BR \-\-resync
26127or
26128.BR \-\- [ raid ] syncaction
26129\fBrepair\fP in case the PVs with corrupted data are known and their data
26130should be reconstructed rather than reconstructing default (rotating) data.
26131.br
26132E.g. in a raid1 mirror, the master leg on /dev/sda may hold corrupt data due
26133to a known transient disk error, thus
26134.br
26135\fBlvchange --rebuild /dev/sda LV\fP
26136.br
26137will request the master leg to be rebuild rather than rebuilding
26138all other legs from the master.
26139On a raid5 with rotating data and parity
26140.br
26141\fBlvchange --rebuild /dev/sda LV\fP
26142.br
26143will rebuild all data and parity blocks in the stripe on /dev/sda.
26144.HP
26145.BR \-\- [ raid ] maxrecoveryrate
26146.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
26147.br
26148Sets the maximum recovery rate for a RAID logical volume. \fIRate\fP
26149is specified as an amount per second for each device in the array.
26150If no suffix is given, then KiB/sec/device is assumed. Setting the
26151recovery rate to \fB0\fP means it will be unbounded.
26152.
26153.HP
26154.BR \-\- [ raid ] minrecoveryrate
26155.BR \fIRate [ b | B | s | S | k | K | m | M | g | G ]
26156.br
26157Sets the minimum recovery rate for a RAID logical volume. \fIRate\fP
26158is specified as an amount per second for each device in the array.
26159If no suffix is given, then KiB/sec/device is assumed. Setting the
26160recovery rate to \fB0\fP means it will be unbounded.
26161.
26162.HP
26163.BR \-\- [ raid ] syncaction
26164.RB { check | repair }
26165.br
26166This argument is used to initiate various RAID synchronization operations.
26167The \fBcheck\fP and \fBrepair\fP options provide a way to check the
26168integrity of a RAID logical volume (often referred to as "scrubbing").
26169These options cause the RAID logical volume to
26170read all of the data and parity blocks in the array and check for any
26171discrepancies (e.g. mismatches between mirrors or incorrect parity values).
26172If \fBcheck\fP is used, the discrepancies will be counted but not repaired.
26173If \fBrepair\fP is used, the discrepancies will be corrected as they are
26174encountered. The \fBlvs\fP(8) command can be used to show the number of
26175discrepancies found or repaired.
26176.
26177.HP
26178.BR \-\- [ raid ] writebehind
26179.IR IOCount
26180.br
26181Specify the maximum number of outstanding writes that are allowed to
26182devices in a RAID1 logical volume that are marked as write-mostly.
26183Once this value is exceeded, writes become synchronous (i.e. all writes
26184to the constituent devices must complete before the array signals the
26185write has completed). Setting the value to zero clears the preference
26186and allows the system to choose the value arbitrarily.
26187.
26188.HP
26189.BR \-\- [ raid ] writemostly
26190.BR \fIPhysicalVolume [ : { y | n | t }]
26191.br
26192Mark a device in a RAID1 logical volume as write-mostly. All reads
26193to these drives will be avoided unless absolutely necessary. This keeps
26194the number of I/Os to the drive to a minimum. The default behavior is to
26195set the write-mostly attribute for the specified physical volume in the
26196logical volume. It is possible to also remove the write-mostly flag by
26197appending a "\fB:n\fP" to the physical volume or to toggle the value by specifying
26198"\fB:t\fP". The \fB\-\-writemostly\fP argument can be specified more than one time
26199in a single command; making it possible to toggle the write-mostly attributes
26200for all the physical volumes in a logical volume at once.
26201.
26202.HP
26203.BR \-r | \-\-readahead
26204.RB { \fIReadAheadSectors | auto | none }
26205.br
26206Set read ahead sector count of this logical volume.
26207For volume groups with metadata in lvm1 format, this must
26208be a value between 2 and 120 sectors.
26209The default value is "\fBauto\fP" which allows the kernel to choose
26210a suitable value automatically.
26211"\fBnone\fP" is equivalent to specifying zero.
26212.
26213.HP
26214.BR \-\-refresh
26215.br
26216If the logical volume is active, reload its metadata.
26217This is not necessary in normal operation, but may be useful
26218if something has gone wrong or if you're doing clustering
26219manually without a clustered lock manager.
26220.
26221.HP
26222.BR \-\-resync
26223.br
26224Forces the complete resynchronization of a mirror. In normal
26225circumstances you should not need this option because synchronization
26226happens automatically. Data is read from the primary mirror device
26227and copied to the others, so this can take a considerable amount of
26228time - and during this time you are without a complete redundant copy
26229of your data.
26230.
26231.HP
26232.BR \-\-sysinit
26233.br
26234Indicates that \fBlvchange\fP(8) is being invoked from early system
26235initialisation scripts (e.g. rc.sysinit or an initrd),
26236before writeable filesystems are available. As such,
26237some functionality needs to be disabled and this option
26238acts as a shortcut which selects an appropriate set of options. Currently
26239this is equivalent to using \fB\-\-ignorelockingfailure\fP,
26240\fB\-\-ignoremonitoring\fP, \fB\-\-poll n\fP and setting
26241\fBLVM_SUPPRESS_LOCKING_FAILURE_MESSAGES\fP
26242environment variable.
26243
26244If \fB\-\-sysinit\fP is used in conjunction with
26245\fBlvmetad\fP(8) enabled and running,
26246autoactivation is preferred over manual activation via direct lvchange call.
26247Logical volumes are autoactivated according to
26248\fBauto_activation_volume_list\fP set in \fBlvm.conf\fP(5).
26249.
26250.HP
26251.BR \-Z | \-\-zero
26252.RB { y | n }
26253.br
26254Set zeroing mode for thin pool. Note: already provisioned blocks from pool
26255in non-zero mode are not cleared in unwritten parts when setting zero to
26256\fBy\fP.
26257.
26258.SH ENVIRONMENT VARIABLES
26259.
26260.TP
26261.B LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES
26262Suppress locking failure messages.
26263.
26264.SH Examples
26265.
26266Changes the permission on volume lvol1 in volume group vg00 to be read-only:
26267.sp
26268.B lvchange \-pr vg00/lvol1
26269.
26270.SH SEE ALSO
26271.
26272.nh
26273.BR lvm (8),
26274.BR lvmetad (8),
26275.BR lvs (8),
26276.BR lvcreate (8),
26277.BR vgchange (8),
26278.BR lvmcache (7),
26279.BR lvmthin (7),
26280.BR lvm.conf (5)
26281\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgimportclone.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003267\013062740170\0021220\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGIMPORTCLONE 8 "LVM TOOLS #VERSION#" "Red Hat, Inc." \" -*- nroff -*-
26282.SH NAME
26283vgimportclone \(em import and rename duplicated volume group (e.g. a hardware snapshot)
26284.SH SYNOPSIS
26285.B vgimportclone
26286.RB [ \-n | \-\-basevgname
26287.IR VolumeGroupName ]
26288.RB [ \-i | \-\-import ]
26289.I PhysicalVolume
26290.RI [ PhysicalVolume ...]
26291.SH DESCRIPTION
26292vgimportclone is used to import a duplicated VG (e.g. hardware snapshot).
26293Duplicate VG(s) and PV(s) are not able to be used until they are made
26294to coexist with the origin VG(s) and PV(s).
26295vgimportclone renames the VG associated with the specified PV(s) and
26296changes the associated VG and PV UUIDs.
26297.SH OPTIONS
26298See \fBlvm\fP(8) for common options.
26299.TP
26300.BR \-n ", " \-\-basevgname " " \fIVolumeGroupName
26301By default the snapshot VG will be renamed to the original name plus a
26302numeric suffix to avoid duplicate naming (e.g. 'test_vg' would be renamed
26303to 'test_vg1'). This option will override the base VG name that is
26304used for all VG renames. If a VG already exists with the specified name
26305a numeric suffix will be added (like the previous example) to make it unique.
26306.TP
26307.BR \-i ", " \-\-import
26308Import exported Volume Groups. Otherwise VGs that have been exported
26309will not be changed (nor will their associated PVs).
26310.SH ENVIRONMENT VARIABLES
26311.TP
26312.B LVM_BINARY
26313The LVM2 binary to use. Defaults to "lvm".
26314.SH Examples
26315The origin VG "vg00" has origin PVs "/dev/sda" and "/dev/sdb"
26316and the respective snapshot PVs are "/dev/sdc" and "/dev/sdd".
26317To rename the VG associated with "/dev/sdc" and "/dev/sdd"
26318from "vg00" to "vg00_snap"
26319(and to change associated VG and PV UUIDs) do:
26320.sp
26321.B vgimportclone \-\-basevgname vg00_snap /dev/sdc /dev/sdd
26322
26323.SH SEE ALSO
26324.BR lvm (8),
26325.BR vgrename (8)
26326
26327\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvremove.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002007\013062740170\0020162\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
26328.SH NAME
26329pvremove \(em remove a physical volume
26330.SH SYNOPSIS
26331.B pvremove
26332.RB [ \-\-commandprofile
26333.IR ProfileName ]
26334.RB [ \-d | \-\-debug ]
26335.RB [ \-h | \-\-help ]
26336.RB [ \-t | \-\-test ]
26337.RB [ \-v | \-\-verbose ]
26338.RB [ \-\-version ]
26339.RB [ \-f [ f ]| \-\-force
26340.RB [ \-\-force ]]
26341.RB [ \-\-reportformat
26342.RB { basic | json }]
26343.RB [ \-y | \-\-yes ]
26344.I PhysicalVolume
26345.RI [ PhysicalVolume ...]
26346.SH DESCRIPTION
26347pvremove wipes the label on a device so that LVM will no longer
26348recognise it as a physical volume.
26349.SH OPTIONS
26350See \fBlvm\fP(8) for common options.
26351.TP
26352.BR \-ff ", " \-\-force " " \-\-force
26353Force the removal of a physical volume belonging to an existing volume group.
26354Normally \fBvgreduce\fP(8) should be used instead of this command.
26355You cannot remove a physical volume which in use by some active logical volume.
26356.TP
26357.BR \-y ", " \-\-yes
26358Answer yes to all questions.
26359.SH SEE ALSO
26360.BR lvm (8),
26361.BR pvcreate (8),
26362.BR pvdisplay (8),
26363.BR vgreduce (8)
26364\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmcache.7.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000027375\013062740170\0020117\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMCACHE" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
26365.SH NAME
26366lvmcache \(em LVM caching
26367
26368.SH DESCRIPTION
26369
26370The \fBcache\fP logical volume type uses a small and fast LV to improve
26371the performance of a large and slow LV. It does this by storing the
26372frequently used blocks on the faster LV.
26373LVM refers to the small fast LV as a \fBcache pool LV\fP. The large
26374slow LV is called the \fBorigin LV\fP. Due to requirements from dm-cache
26375(the kernel driver), LVM further splits the cache pool LV into two
26376devices - the \fBcache data LV\fP and \fBcache metadata LV\fP. The cache
26377data LV is where copies of data blocks are kept from the
26378origin LV to increase speed. The cache metadata LV holds the
26379accounting information that specifies where data blocks are stored (e.g.
26380on the origin LV or on the cache data LV). Users should be familiar with
26381these LVs if they wish to create the best and most robust cached
26382logical volumes. All of these associated LVs must be in the same VG.
26383
26384.SH Cache Terms
26385.nf
26386origin LV OriginLV large slow LV
26387cache data LV CacheDataLV small fast LV for cache pool data
26388cache metadata LV CacheMetaLV small fast LV for cache pool metadata
26389cache pool LV CachePoolLV CacheDataLV + CacheMetaLV
26390cache LV CacheLV OriginLV + CachePoolLV
26391.fi
26392
26393.SH Cache Usage
26394
26395The primary method for using a cache type logical volume:
26396
26397
26398.SS 0. create OriginLV
26399
26400Create an LV or identify an existing LV to be the origin LV.
26401
26402.B lvcreate \-n OriginLV \-L LargeSize VG SlowPVs
26403
26404.I Example
26405.br
26406# lvcreate \-n lvol0 \-L 100G vg
26407
26408
26409.SS 1. create CacheDataLV
26410
26411Create the cache data LV. This LV will hold data blocks from the
26412OriginLV. The size of this LV is the size of the cache and will be
26413reported as the size of the cache pool LV.
26414
26415.B lvcreate \-n CacheDataLV \-L CacheSize VG FastPVs
26416
26417.I Example
26418.br
26419# lvcreate \-n cache0 \-L 10G vg /dev/fast
26420
26421
26422.SS 2. create CacheMetaLV
26423
26424Create the cache metadata LV. This LV will hold cache pool metadata. The
26425size of this LV should be 1000 times smaller than the cache data LV, with
26426a minimum size of 8MiB.
26427
26428.B lvcreate \-n CacheMetaLV \-L MetaSize VG FastPVs
26429
26430.I Example
26431.br
26432# lvcreate \-n cache0meta \-L 12M vg /dev/fast
26433
26434.nf
26435# lvs -a vg
26436 LV VG Attr LSize Pool Origin
26437 cache0 vg -wi-a----- 10.00g
26438 cache0meta vg -wi-a----- 12.00m
26439 lvol0 vg -wi-a----- 100.00g
26440.fi
26441
26442
26443.SS 3. create CachePoolLV
26444
26445Combine the data and metadata LVs into a cache pool LV.
26446The behavior of the cache pool LV can be set in this step.
26447.br
26448CachePoolLV takes the name of CacheDataLV.
26449.br
26450CacheDataLV is renamed CachePoolLV_cdata and becomes hidden.
26451.br
26452CacheMetaLV is renamed CachePoolLV_cmeta and becomes hidden.
26453
26454.B lvconvert \-\-type cache-pool \-\-poolmetadata VG/CacheMetaLV
26455.RS
26456.B VG/CacheDataLV
26457.RE
26458
26459.I Example
26460.br
26461# lvconvert \-\-type cache\-pool \-\-poolmetadata vg/cache0meta vg/cache0
26462
26463.nf
26464# lvs -a vg
26465 LV VG Attr LSize Pool Origin
26466 cache0 vg Cwi---C--- 10.00g
26467 [cache0_cdata] vg Cwi------- 10.00g
26468 [cache0_cmeta] vg ewi------- 12.00m
26469 lvol0 vg -wi-a----- 100.00g
26470.fi
26471
26472
26473.SS 4. create CacheLV
26474
26475Create a cache LV by linking the cache pool LV to the origin LV.
26476The user accessible cache LV takes the name of the origin LV,
26477while the origin LV becomes a hidden LV with the name
26478OriginLV_corig. This can be done while the origin LV is in use.
26479.br
26480CacheLV takes the name of OriginLV.
26481.br
26482OriginLV is renamed OriginLV_corig and becomes hidden.
26483
26484.B lvconvert \-\-type cache \-\-cachepool VG/CachePoolLV VG/OriginLV
26485
26486.I Example
26487.br
26488# lvconvert \-\-type cache \-\-cachepool vg/cache0 vg/lvol0
26489
26490.nf
26491# lvs -a vg
26492 LV VG Attr LSize Pool Origin
26493 cache0 vg Cwi---C--- 10.00g
26494 [cache0_cdata] vg Cwi-ao---- 10.00g
26495 [cache0_cmeta] vg ewi-ao---- 12.00m
26496 lvol0 vg Cwi-a-C--- 100.00g cache0 [lvol0_corig]
26497 [lvol0_corig] vg -wi-ao---- 100.00g
26498.fi
26499
26500
26501.SH Cache Removal
26502
26503.SS Split a cache pool LV off of a cache LV
26504
26505\&
26506
26507A cache pool LV can be disconnected from a cache LV, leaving an
26508unused cache pool LV, and an uncached origin LV. This command
26509writes back data from the cache pool to the origin LV when necessary.
26510
26511.B lvconvert --splitcache VG/CacheLV
26512
26513.SS Removing a cache pool LV without removing its linked origin LV
26514
26515\&
26516
26517This writes back data from the cache pool to the origin LV when necessary,
26518then removes the cache pool LV, leaving the uncached origin LV.
26519
26520.B lvremove VG/CachePoolLV
26521
26522An alternative command that also disconnects the cache pool from the cache
26523LV, and deletes the cache pool:
26524
26525.B lvconvert --uncache VG/CacheLV
26526
26527.I Example
26528.nf
26529# lvs vg
26530 LV VG Attr LSize Pool Origin
26531 cache0 vg Cwi---C--- 10.00g
26532 lvol0 vg Cwi-a-C--- 100.00g cache0 [lvol0_corig]
26533
26534# lvremove vg/cache0
26535
26536# lvs vg
26537 LV VG Attr LSize Pool Origin
26538 lvol0 vg -wi-a----- 100.00g
26539.fi
26540
26541.SS Removing a cache LV: both origin LV and the cache pool LV
26542
26543\&
26544
26545Removing a cache LV removes both the origin LV and the linked cache pool
26546LV.
26547
26548.B lvremove VG/CacheLV
26549
26550
26551.SH Cache Topics
26552
26553.SS Tolerate device failures in a cache pool LV
26554
26555\&
26556
26557Users who are concerned about the possibility of failures in their fast
26558devices that could lead to data loss might consider making their cache
26559pool sub-LVs redundant.
26560
26561.I Example
26562.nf
265630. Create an origin LV we wish to cache
26564# lvcreate \-L 10G \-n lv1 vg /dev/slow_devs
26565
265661. Create a 2-way RAID1 cache data LV
26567# lvcreate \-\-type raid1 \-m 1 \-L 1G -n cache1 vg \\
26568 /dev/fast1 /dev/fast2
26569
265702. Create a 2-way RAID1 cache metadata LV
26571# lvcreate \-\-type raid1 \-m 1 \-L 8M -n cache1meta vg \\
26572 /dev/fast1 /dev/fast2
26573
265743. Create a cache pool LV combining cache data LV and cache metadata LV
26575# lvconvert \-\-type cache\-pool \-\-poolmetadata vg/cache1meta vg/cache1
26576
265774. Create a cached LV by combining the cache pool LV and origin LV
26578# lvconvert \-\-type cache \-\-cachepool vg/cache1 vg/lv1
26579.fi
26580
26581.SS Cache mode
26582
26583\&
26584
26585The default cache mode is "writethrough". Writethrough ensures that any
26586data written will be stored both in the cache pool LV and on the origin
26587LV. The loss of a device associated with the cache pool LV in this case
26588would not mean the loss of any data.
26589
26590A second cache mode is "writeback". Writeback delays writing data blocks
26591from the cache pool back to the origin LV. This mode will increase
26592performance, but the loss of a device associated with the cache pool LV
26593can result in lost data.
26594
26595With the \-\-cachemode option, the cache mode can be set when creating a
26596cache LV, or changed on an existing cache LV. The current cache mode of a
26597cache LV can be displayed with the cache_mode reporting option:
26598
26599.B lvs \-o+cache_mode VG/CacheLV
26600
26601.BR lvm.conf (5)
26602.B allocation/cache_mode
26603.br
26604defines the default cache mode.
26605
26606.I Example
26607.nf
266080. Create an origin LV we wish to cache (yours may already exist)
26609# lvcreate \-L 10G \-n lv1 vg /dev/slow
26610
266111. Create a cache data LV
26612# lvcreate \-L 1G \-n cache1 vg /dev/fast
26613
266142. Create a cache metadata LV
26615# lvcreate \-L 8M \-n cache1meta vg /dev/fast
26616
266173. Create a cache pool LV
26618# lvconvert \-\-type cache\-pool \-\-poolmetadata vg/cache1meta vg/cache1
26619
266204. Create a cache LV by combining the cache pool LV and origin LV,
26621 and use the writethrough cache mode.
26622# lvconvert \-\-type cache \-\-cachepool vg/cache1 \\
26623 \-\-cachemode writethrough vg/lv1
26624.fi
26625
26626
26627.SS Cache policy
26628
26629\&
26630
26631The cache subsystem has additional per-LV parameters: the cache policy to
26632use, and possibly tunable parameters for the cache policy. Three policies
26633are currently available: "smq" is the default policy, "mq" is an older
26634implementation, and "cleaner" is used to force the cache to write back
26635(flush) all cached writes to the origin LV.
26636
26637The "mq" policy has a number of tunable parameters. The defaults are
26638chosen to be suitable for the majority of systems, but in special
26639circumstances, changing the settings can improve performance.
26640
26641With the \-\-cachepolicy and \-\-cachesettings options, the cache policy
26642and settings can be set when creating a cache LV, or changed on an
26643existing cache LV (both options can be used together). The current cache
26644policy and settings of a cache LV can be displayed with the cache_policy
26645and cache_settings reporting options:
26646
26647.B lvs \-o+cache_policy,cache_settings VG/CacheLV
26648
26649.I Example
26650.nf
26651Change the cache policy and settings of an existing cache LV.
26652# lvchange \-\-cachepolicy mq \-\-cachesettings \\
26653 \(aqmigration_threshold=2048 random_threshold=4\(aq vg/lv1
26654.fi
26655
26656.BR lvm.conf (5)
26657.B allocation/cache_policy
26658.br
26659defines the default cache policy.
26660
26661.BR lvm.conf (5)
26662.B allocation/cache_settings
26663.br
26664defines the default cache settings.
26665
26666
26667.SS Chunk size
26668
26669\&
26670
26671The size of data blocks managed by a cache pool can be specified with the
26672\-\-chunksize option when the cache LV is created. The default unit
26673is KiB. The value must be a multiple of 32KiB between 32KiB and 1GiB.
26674
26675Using a chunk size that is too large can result in wasteful use of the
26676cache, where small reads and writes can cause large sections of an LV to
26677be mapped into the cache. However, choosing a chunk size that is too
26678small can result in more overhead trying to manage the numerous chunks
26679that become mapped into the cache. Overhead can include both excessive
26680CPU time searching for chunks, and excessive memory tracking chunks.
26681
26682Command to display the cache pool LV chunk size:
26683.br
26684.B lvs \-o+chunksize VG/CacheLV
26685
26686.BR lvm.conf (5)
26687.B cache_pool_chunk_size
26688.br
26689controls the default chunk size used when creating a cache LV.
26690
26691The default value is shown by:
26692.br
26693.B lvmconfig \-\-type default allocation/cache_pool_chunk_size
26694
26695
26696.SS Spare metadata LV
26697
26698\&
26699
26700See
26701.BR lvmthin (7)
26702for a description of the "pool metadata spare" LV.
26703The same concept is used for cache pools.
26704
26705.SS Automatic pool metadata LV
26706
26707\&
26708
26709A cache data LV can be converted to cache pool LV without specifying a
26710cache pool metadata LV. LVM will automatically create a metadata LV from
26711the same VG.
26712
26713.B lvcreate -n CacheDataLV -L CacheSize VG
26714.br
26715.B lvconvert --type cache\-pool VG/CacheDataLV
26716
26717
26718.SS Create a new cache LV without an existing origin LV
26719
26720\&
26721
26722A cache LV can be created using an existing cache pool without an existing
26723origin LV. A new origin LV is created and linked to the cache pool in a
26724single step.
26725
26726.B lvcreate \-\-type cache \-L LargeSize \-n CacheLV
26727.RS
26728.B \-\-cachepool VG/CachePoolLV VG SlowPVs
26729.RE
26730
26731
26732.SS Single step cache pool LV creation
26733
26734\&
26735
26736A cache pool LV can be created with a single lvcreate command, rather than
26737using lvconvert on existing LVs. This one command creates a cache data
26738LV, a cache metadata LV, and combines the two into a cache pool LV.
26739
26740.B lvcreate \-\-type cache\-pool \-L CacheSize \-n CachePoolLV VG FastPVs
26741
26742
26743.SS Convert existing LVs to cache types
26744
26745\&
26746
26747When an existing origin LV is converted to a cache LV, the specified cache
26748pool may be a normal LV, rather than a cache pool LV. In this case, lvm
26749will first convert the normal LV to a cache pool LV. A pool metadata LV
26750may optionally be specified.
26751
26752.B lvcreate -n OriginLV -L LargeSize VG
26753.br
26754.B lvcreate -n CacheDataLV -L CacheSize VG
26755.br
26756.B lvconvert --type cache --cachepool VG/CataDataLV VG/OriginLV
26757
26758This is equivalent to:
26759
26760.B lvcreate -n OriginLV -L LargeSize VG
26761.br
26762.B lvcreate -n CacheDataLV -L CacheSize VG
26763.br
26764.B lvconvert --type cache-pool VG/CacheDataLV
26765.br
26766.B lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
26767
26768
26769.SH SEE ALSO
26770.BR lvm.conf (5),
26771.BR lvchange (8),
26772.BR lvcreate (8),
26773.BR lvdisplay (8),
26774.BR lvextend (8),
26775.BR lvremove (8),
26776.BR lvrename (8),
26777.BR lvresize (8),
26778.BR lvs (8),
26779.BR vgchange (8),
26780.BR vgmerge (8),
26781.BR vgreduce (8),
26782.BR vgsplit (8)
26783\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmsadc.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000361\013062740170\0017751\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMSADC" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
26784
26785.SH "NAME"
26786lvmsadc \(em LVM system activity data collector
26787
26788.SH "SYNOPSIS"
26789.B lvmsadc
26790
26791.SH "DESCRIPTION"
26792lvmsadc is not currently supported under LVM2.
26793
26794.SH "SEE ALSO"
26795.BR lvm (8)
26796\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011461\013062740170\0017672\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
26797# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
26798# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
26799#
26800# This file is part of LVM2.
26801#
26802# This copyrighted material is made available to anyone wishing to use,
26803# modify, copy, or redistribute it subject to the terms and conditions
26804# of the GNU General Public License v.2.
26805#
26806# You should have received a copy of the GNU General Public License
26807# along with this program; if not, write to the Free Software Foundation,
26808# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26809
26810srcdir = @srcdir@
26811top_srcdir = @top_srcdir@
26812top_builddir = @top_builddir@
26813
26814FSADMMAN = fsadm.8
26815BLKDEACTIVATEMAN = blkdeactivate.8
26816DMEVENTDMAN = dmeventd.8
26817LVMETADMAN = lvmetad.8
26818LVMPOLLDMAN = lvmpolld.8
26819LVMLOCKDMAN = lvmlockd.8 lvmlockctl.8
26820CLVMDMAN = clvmd.8
26821CMIRRORDMAN = cmirrord.8
26822LVMCACHEMAN = lvmcache.7
26823LVMTHINMAN = lvmthin.7
26824LVMDBUSDMAN = lvmdbusd.8
26825LVMRAIDMAN = lvmraid.7
26826
26827MAN5=lvm.conf.5
26828MAN7=lvmsystemid.7 lvmreport.7
26829MAN8=lvm-config.8 lvm-dumpconfig.8 lvm-fullreport.8 lvm-lvpoll.8 \
26830 lvchange.8 lvmconfig.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 \
26831 lvm.8 lvmchange.8 lvmconf.8 lvmdiskscan.8 lvmdump.8 lvmsadc.8 lvmsar.8 \
26832 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
26833 lvscan.8 pvchange.8 pvck.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
26834 pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
26835 vgck.8 vgcreate.8 vgconvert.8 vgdisplay.8 vgexport.8 vgextend.8 \
26836 vgimport.8 vgimportclone.8 vgmerge.8 vgmknodes.8 vgreduce.8 vgremove.8 \
26837 vgrename.8 vgs.8 vgscan.8 vgsplit.8
26838MAN8DM=dmsetup.8 dmstats.8
26839MAN8CLUSTER=
26840MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
26841
26842ifeq ($(MAKECMDGOALS),all_man)
26843 MAN_ALL="yes"
26844endif
26845
26846ifeq ($(MAKECMDGOALS),install_all_man)
26847 MAN_ALL="yes"
26848endif
26849
26850ifeq ($(MAN_ALL),"yes")
26851 MAN8+=$(FSADMMAN) $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
26852 MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN)
26853 MAN8CLUSTER+=$(CLVMDMAN) $(CMIRRORDMAN)
26854 MAN7+=$(LVMCACHEMAN) $(LVMTHINMAN) $(LVMRAIDMAN)
26855else
26856 ifeq ("@FSADM@", "yes")
26857 MAN8+=$(FSADMMAN)
26858 endif
26859
26860 ifeq ("@BUILD_LVMDBUSD@", "yes")
26861 MAN8+=$(LVMDBUSDMAN)
26862 endif
26863
26864 ifeq ("@BUILD_LVMETAD@", "yes")
26865 MAN8+=$(LVMETADMAN)
26866 endif
26867
26868 ifeq ("@BUILD_LVMPOLLD@", "yes")
26869 MAN8+=$(LVMPOLLDMAN)
26870 endif
26871
26872 ifeq ("@BUILD_LVMLOCKD@", "yes")
26873 MAN8+=$(LVMLOCKDMAN)
26874 endif
26875
26876 ifeq ("@BLKDEACTIVATE@", "yes")
26877 MAN8DM+=$(BLKDEACTIVATEMAN)
26878 endif
26879
26880 ifeq ("@DMEVENTD@", "yes")
26881 MAN8DM+=$(DMEVENTDMAN)
26882 endif
26883
26884 ifneq ("@CLVMD@", "none")
26885 MAN8CLUSTER+=$(CLVMDMAN)
26886 endif
26887
26888 ifeq ("@BUILD_CMIRRORD@", "yes")
26889 MAN8CLUSTER+=$(CMIRRORDMAN)
26890 endif
26891
26892 ifneq ("@CACHE@", "none")
26893 MAN7+=$(LVMCACHEMAN)
26894 endif
26895
26896 ifneq ("@THIN@", "none")
26897 MAN7+=$(LVMTHINMAN)
26898 endif
26899
26900 ifneq ("@RAID@", "none")
26901 MAN7+=$(LVMRAIDMAN)
26902 endif
26903endif
26904
26905MAN5DIR=$(mandir)/man5
26906MAN7DIR=$(mandir)/man7
26907MAN8DIR=$(mandir)/man8
26908
26909include $(top_builddir)/make.tmpl
26910
26911CLEAN_TARGETS+=$(MAN5) $(MAN7) $(MAN8) $(MAN8CLUSTER) \
26912 $(MAN8SYSTEMD_GENERATORS) $(MAN8DM)
26913DISTCLEAN_TARGETS+=$(FSADMMAN) $(BLKDEACTIVATEMAN) $(DMEVENTDMAN) \
26914 $(LVMETADMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(CLVMDMAN) $(CMIRRORDMAN) \
26915 $(LVMCACHEMAN) $(LVMTHINMAN) $(LVMDBUSDMAN) $(LVMRAIDMAN)
26916
26917all: man device-mapper
26918
26919.PHONY: man install_man5 install_man7 install_man8
26920
26921device-mapper: $(MAN8DM)
26922
26923man: $(MAN5) $(MAN7) $(MAN8) $(MAN8CLUSTER) $(MAN8SYSTEMD_GENERATORS)
26924
26925all_man: man
26926
26927$(MAN5) $(MAN7) $(MAN8) $(MAN8DM) $(MAN8CLUSTER): Makefile
26928
26929Makefile: Makefile.in
26930 @:
26931
26932%: %.in
26933 @case "$@" in \
26934 */*) ;; \
26935 *) echo "Creating $@" ; $(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $< > $@ ;; \
26936 esac
26937
26938install_man5: $(MAN5)
26939 $(INSTALL) -d $(MAN5DIR)
26940 $(INSTALL_DATA) $(MAN5) $(MAN5DIR)/
26941
26942install_man7: $(MAN7)
26943 $(INSTALL) -d $(MAN7DIR)
26944 $(INSTALL_DATA) $(MAN7) $(MAN7DIR)/
26945
26946install_man8: $(MAN8)
26947 $(INSTALL) -d $(MAN8DIR)
26948 $(INSTALL_DATA) $(MAN8) $(MAN8DIR)/
26949
26950install_lvm2: install_man5 install_man7 install_man8
26951
26952install_cluster: $(MAN8CLUSTER)
26953ifdef MAN8CLUSTER
26954 $(INSTALL) -d $(MAN8DIR)
26955 $(INSTALL_DATA) $(MAN8CLUSTER) $(MAN8DIR)/
26956endif
26957
26958install_device-mapper: $(MAN8DM)
26959 $(INSTALL) -d $(MAN8DIR)
26960 $(INSTALL_DATA) $(MAN8DM) $(MAN8DIR)/
26961
26962install_systemd_generators: $(MAN8SYSTEMD_GENERATORS)
26963 $(INSTALL) -d $(MAN8DIR)
26964 $(INSTALL_DATA) $(MAN8SYSTEMD_GENERATORS) $(MAN8DIR)/
26965
26966install: install_lvm2 install_device-mapper install_cluster
26967
26968install_all_man: install install_systemd_generators
26969\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvconvert.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000064244\013062740170\0020354\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVCONVERT 8 "LVM TOOLS #VERSION#" "Red Hat, Inc" \" -*- nroff -*-
26970.SH NAME
26971lvconvert \(em change LV type and other utilities
26972.
26973.SH SYNOPSIS
26974
26975.B lvconvert
26976.RI [ OPTION ]...
26977.IR VolumeGroup / LogicalVolume
26978
26979OPTIONS:
26980.br
26981.BR \-b ,
26982.BR \-\-background
26983.br
26984.BR \-\-cachepolicy
26985.IR Policy
26986.br
26987.BR \-\-cachepool
26988.IR CachePoolLogicalVolume { Name | Path }
26989.br
26990.BR \-\-cachesettings
26991.IB Key = Value
26992.br
26993.BR \-c ,
26994.BR \-\-chunksize
26995.BR \fIChunkSize [ b | B | s | S | k | K | m | M | g | G ]
26996.br
26997.BR \-\-corelog
26998.br
26999.BR \-\-discards
27000.RB { ignore | nopassdown | passdown }
27001.br
27002.BR \-i ,
27003.BR \-\-interval
27004.IR Seconds
27005.br
27006.BR \-\-merge
27007.br
27008.BR \-\-mirrorlog
27009.RB { disk | core | mirrored }
27010.br
27011.BR \-m ,
27012.BR \-\-mirrors
27013.IR Number
27014.br
27015.BR \-n ,
27016.BR \-\-name
27017.IR Name
27018.br
27019.BR \-\-noudevsync
27020.br
27021.BR \-\-originname
27022.IR NewExternalOriginVolumeName
27023.br
27024.BR \-\-poolmetadata
27025.IR PoolMetadataLogicalVolume { Name | Path }
27026.br
27027.BR \-\-poolmetadatasize
27028.BR \fIPoolMetadataSize [ b | B | s | S | k | K | m | M | g | G ]
27029.br
27030.BR \-\-poolmetadataspare
27031.RB { y | n }
27032.br
27033.BR \-r ,
27034.BR \-\-readahead
27035.RB { \fIReadAheadSectors | auto | none }
27036.br
27037.BR \-R ,
27038.BR \-\-regionsize
27039.IR MirrorLogRegionSize
27040.br
27041.BR \-\-repair
27042.br
27043.BR \-\-replace
27044.IR PhysicalVolume
27045.br
27046.BR \-\-splitcache
27047.br
27048.BR \-\-splitmirrors
27049.IR Number
27050.br
27051.BR \-\-splitsnapshot
27052.br
27053.BR \-\-stripes
27054.IR Number
27055.br
27056.BR \-I ,
27057.BR \-\-stripesize
27058.IR StripeSize
27059.br
27060.B \-\-type striped
27061.br
27062.B \-\-type snapshot
27063|
27064.B \-\-snapshot
27065|
27066.B \-s
27067.br
27068.B \-\-type mirror
27069.br
27070.B \-\-type raid*
27071.br
27072.B \-\-type thin
27073|
27074.B \-\-thin
27075|
27076.B \-T
27077.br
27078.B \-\-type cache
27079|
27080.B \-\-cache
27081|
27082.B \-H
27083.br
27084.B \-\-type thin\-pool
27085.br
27086.B \-\-type cache\-pool
27087.br
27088.BR \-\-thinpool
27089.IR ThinPoolLogicalVolume { Name | Path }
27090.br
27091.BR \-\-trackchanges
27092.br
27093.BR \-\-uncache
27094.br
27095.BR \-Z ,
27096.BR \-\-zero
27097.RB { y | n }
27098.br
27099
27100Common options:
27101.br
27102.BR \-A ,
27103.BR \-\-alloc
27104.IR AllocationPolicy
27105.br
27106.BR \-f ,
27107.BR \-\-force
27108.br
27109.BR \-\-commandprofile
27110.IR ProfileName
27111.br
27112.BR \-h ,
27113.BR \-? ,
27114.BR \-\-help
27115.br
27116.BR \-v ,
27117.BR \-\-verbose
27118.br
27119.BR \-y ,
27120.BR \-\-yes
27121.br
27122.BR \-\-version
27123
27124
27125
27126
27127.SH DESCRIPTION
27128
27129lvconvert changes the LV type and includes various LV utilities.
27130
27131To display the current LV type, run the command:
27132
27133.B lvs \-o name,segtype
27134.IR VG / LV
27135
27136To change the LV type, run the command:
27137
27138.B lvconvert \-\-type
27139.I NewType
27140.IR VG / LV
27141
27142.SS LV types
27143
27144The LV type is also called the "segment type" or "segtype".
27145
27146LVs with the following types can be modified by lvconvert:
27147.B striped,
27148.B snapshot,
27149.B mirror,
27150.B raid*,
27151.B thin,
27152.B cache,
27153.B thin\-pool,
27154.B cache\-pool.
27155
27156The specific operations available on each LV type are listed below.
27157
27158The
27159.B linear
27160type is equivalent to the
27161.B striped
27162type when one stripe exists.
27163In that case, the types can sometimes be used interchangably.
27164
27165In most cases, the
27166.B mirror
27167type is deprecated and the
27168.B raid1
27169type should be used. They are both implementations of mirroring.
27170
27171The
27172.B raid*
27173type refers to one of many raid levels, e.g.
27174.B raid1,
27175.B raid5.
27176
27177.SS LV layers
27178
27179In some cases, an LV is a single device mapper (dm) layer above physical
27180devices. In other cases, hidden LVs (dm devices) are layered between the
27181visible LV and physical devices. LVs in the middle layers are sometimes
27182called sub LVs.
27183
27184Changing the LV type will often change the composition of sub LVs.
27185
27186Sub LVs can be displayed with the command
27187.B lvs -a.
27188
27189A command run on a visible LV sometimes operates on a sub LV rather than
27190the specified LV. These cases are noted below.
27191
27192Sometimes a sub LV must be specified directly on the command line, but
27193this is a non-standard form. These cases may change in the future to
27194avoid the direct use of hidden LVs.
27195
27196.SH COMMANDS
27197
27198.SS Operations on a StripedLV with type striped or linear:
27199
27200\&
27201
27202.B lvconvert \-\-merge
27203VG/StripedLV
27204./" FIXME: use --merge-mirror
27205.br
27206\[bu]
27207Merge StripedLV into an LV when it is a previously split mirror.
27208.br
27209\[bu]
27210Options \-\-background, \-\-interval.
27211.br
27212\[bu]
27213See corresponding operation --splitmirrors.
27214
27215.B lvconvert \-\-type snapshot
27216VG/StripedLV VG/SnapshotLV
27217.br
27218\[bu]
27219Recombine StripedLV with SnapshotLV which was previously split.
27220.br
27221\[bu]
27222Options \-\-chunksize, \-\-zero.
27223.br
27224\[bu]
27225See corresponding operation --splitsnapshot.
27226
27227.B lvconvert \-\-type thin
27228VG/StripedLV
27229.br
27230\[bu]
27231Convert StripedLV to type thin with an external origin.
27232.br
27233\[bu]
27234StripedLV becomes a read\-only external origin LV with a new name.
27235.br
27236\[bu]
27237Requires \-\-thinpool to specify the thin pool to use.
27238.br
27239\[bu]
27240Options \-\-originname.
27241
27242.B lvconvert \-\-type cache
27243VG/StripedLV
27244.br
27245\[bu]
27246Convert StripedLV to type cache.
27247.br
27248\[bu]
27249Requires \-\-cachepool to specify the cache pool to use.
27250.br
27251\[bu]
27252Options \-\-cachepolicy, \-\-cachesettings.
27253
27254.B lvconvert \-\-type thin\-pool
27255VG/StripedLV
27256.br
27257\[bu]
27258Convert StripedLV to type thin\-pool.
27259.br
27260\[bu]
27261The StripedLV is used for thin pool data.
27262.br
27263\[bu]
27264Options \-\-chunksize, \-\-discards, \-\-poolmetadata{size,spare},
27265.br
27266 \-\-readahead, \-\-zero.
27267
27268.B lvconvert \-\-type cache\-pool
27269VG/StripedLV
27270.br
27271\[bu]
27272Convert StripedLV to type cache\-pool.
27273.br
27274\[bu]
27275Options \-\-chunksize, \-\-poolmetadata{size,spare}.
27276
27277.B lvconvert \-\-type mirror
27278VG/StripedLV
27279.br
27280\[bu]
27281Convert StripedLV to type mirror.
27282.br
27283\[bu]
27284Requires \-\-mirrors to specify the number of mirrors to use.
27285.br
27286\[bu]
27287Options \-\-mirrorlog, \-\-regionsize.
27288
27289.B lvconvert \-\-type raid*
27290VG/StripedLV
27291.br
27292\[bu]
27293Convert StripedLV to type raid*.
27294.br
27295\[bu]
27296Required options depend on the raid level.
27297
27298.SS Operations on RaidLV with type raid*:
27299
27300\&
27301
27302.B lvconvert \-\-mirrors
27303Number
27304VG/RaidLV
27305.br
27306\[bu]
27307Change the number of images in raid1 RaidLV.
27308
27309.B lvconvert \-\-splitmirrors
27310Number
27311VG/RaidLV
27312.br
27313\[bu]
27314Split images from raid1 RaidLV and use them to create a new LV.
27315.br
27316\[bu]
27317Requires \-\-name for the new LV, or the use of \-\-trackchanges.
27318
27319.B lvconvert \-\-merge
27320VG/RaidLV
27321./" FIXME: use --merge-mirror
27322.br
27323\[bu]
27324Merge RaidLV into an LV when it is a previously split mirror.
27325.br
27326\[bu]
27327Options \-\-background, \-\-interval.
27328.br
27329\[bu]
27330See corresponding operation --splitmirrors.
27331
27332.B lvconvert \-\-repair
27333VG/RaidLV
27334.br
27335\[bu]
27336Options \-\-background, \-\-interval.
27337.br
27338\[bu]
27339Replace failed PVs in RaidLV.
27340
27341.B lvconvert \-\-replace
27342PV
27343VG/RaidLV
27344.br
27345\[bu]
27346Replace specific PV(s) in a raid* LV with another PV.
27347.br
27348\[bu]
27349The new PV(s) to use can be optionally specified after the LV.
27350.br
27351\[bu]
27352Repeat to replace multiple: \-\-replace PV1 \-\-replace PV2 ...
27353
27354.B lvconvert \-\-type snapshot
27355VG/RaidLV
27356VG/SnapshotLV
27357.br
27358\[bu]
27359Combine RaidLV with SnapshotLV that was previously split.
27360.br
27361\[bu]
27362Options \-\-chunksize, \-\-zero.
27363.br
27364\[bu]
27365See corresponding operation \-\-splitsnapshot.
27366
27367.B lvconvert \-\-type thin
27368VG/RaidLV
27369.br
27370\[bu]
27371Convert RaidLV to type thin with an external origin.
27372.br
27373\[bu]
27374RaidLV becomes a read\-only external origin LV with a new name.
27375.br
27376\[bu]
27377Requires \-\-thinpool to specify the thin pool to use.
27378.br
27379\[bu]
27380Options \-\-originname.
27381
27382.B lvconvert \-\-type cache
27383VG/RaidLV
27384.br
27385\[bu]
27386Convert RaidLV to type cache.
27387.br
27388\[bu]
27389Requires \-\-cachepool to specify the cache pool to use.
27390.br
27391\[bu]
27392Options \-\-cachepolicy, \-\-cachesettings.
27393
27394.B lvconvert \-\-type thin\-pool
27395VG/RaidLV
27396.br
27397\[bu]
27398Convert RaidLV to type thin\-pool.
27399.br
27400\[bu]
27401The RaidLV is used for thin pool data.
27402.br
27403\[bu]
27404Options \-\-chunksize, \-\-discards, \-\-poolmetadata{size,spare},
27405.br
27406 \-\-readahead, \-\-zero.
27407
27408.B lvconvert \-\-type cache\-pool
27409VG/RaidLV
27410.br
27411\[bu]
27412Convert RaidLV to type cache\-pool.
27413.br
27414\[bu]
27415Options \-\-chunksize, \-\-poolmetadata{size,spare}.
27416
27417.B lvconvert \-\-type raid*
27418VG/RaidLV
27419.br
27420\[bu]
27421Convert RaidLV to use a different raid level.
27422.br
27423\[bu]
27424Required options depend on the raid level.
27425
27426.B lvconvert \-\-type mirror
27427VG/RaidLV
27428.br
27429\[bu]
27430Convert RaidLV to type mirror.
27431
27432.B lvconvert \-\-type striped
27433VG/RaidLV
27434.br
27435\[bu]
27436Convert RaidLV to type striped.
27437
27438.B lvconvert \-\-type linear
27439VG/RaidLV
27440.br
27441\[bu]
27442Convert RaidLV to type linear.
27443
27444.SS Operations on MirrorLV with type mirror:
27445
27446\&
27447
27448.B lvconvert \-\-mirrors
27449Number
27450VG/MirrorLV
27451.br
27452\[bu]
27453Change the number of images in MirrorLV.
27454
27455.B lvconvert \-\-splitmirrors
27456Number
27457VG/MirrorLV
27458.br
27459\[bu]
27460Split images from MirrorLV and use them to create a new LV.
27461.br
27462\[bu]
27463Requires \-\-name for the new LV.
27464
27465.B lvconvert \-\-mirrorlog
27466LogType
27467VG/MirrorLV
27468.br
27469\[bu]
27470Change the type of log used by MirrorLV.
27471
27472.B lvconvert \-\-repair
27473VG/MirrorLV
27474.br
27475\[bu]
27476Options \-\-background, \-\-interval.
27477.br
27478\[bu]
27479Replace failed PVs in MirrorLV.
27480
27481.B lvconvert \-\-type linear
27482VG/MirrorLV
27483.br
27484\[bu]
27485Convert MirrorLV to type linear.
27486
27487.B lvconvert \-\-type raid*
27488VG/MirrorLV
27489.br
27490\[bu]
27491Convert MirrorLV to type raid*.
27492.br
27493\[bu]
27494Required options depend on the raid level.
27495
27496.SS Operations on CachePoolLV with type cache\-pool:
27497
27498\&
27499
27500.B lvconvert \-\-splitcache
27501VG/CachePoolLV
27502.br
27503\[bu]
27504Split the cache LV from CachePoolLV.
27505.br
27506\[bu]
27507Equivalent to --splitcache on CacheLV.
27508
27509.SS Operations on CacheLV with type cache:
27510
27511\&
27512
27513.B lvconvert \-\-splitcache
27514VG/CacheLV
27515.br
27516\[bu]
27517Split and keep the cache pool from CacheLV.
27518
27519.B lvconvert \-\-uncache
27520VG/CacheLV
27521.br
27522\[bu]
27523Split and remove the cache pool from CacheLV.
27524
27525.B lvconvert \-\-splitmirrors
27526Number
27527VG/CacheLV
27528.br
27529\[bu]
27530Split images from the mirrored origin of CacheLV to create a new LV.
27531.br
27532\[bu]
27533Operates on mirror or raid1 sub LV.
27534.br
27535\[bu]
27536Requires \-\-name for the new LV, or the use of \-\-trackchanges.
27537
27538.B lvconvert \-\-type thin\-pool
27539VG/CacheLV
27540.br
27541\[bu]
27542Convert CacheLV to type thin-pool.
27543.br
27544\[bu]
27545The CacheLV is used for thin pool data.
27546.br
27547\[bu]
27548Options \-\-chunksize, \-\-discards, \-\-poolmetadata{size,spare},
27549.br
27550 \-\-readahead, \-\-zero.
27551
27552
27553.SS Operations on ThinPoolLV with type thin\-pool:
27554
27555\&
27556
27557.B lvconvert \-\-splitcache
27558VG/ThinPoolLV
27559.br
27560\[bu]
27561Split and keep the cache pool from the data portion of ThinPoolLV.
27562.br
27563\[bu]
27564Operates on the data sub LV of the thin pool LV.
27565.br
27566\[bu]
27567The data sub LV of the thin pool must be a cache LV.
27568
27569.B lvconvert \-\-uncache
27570VG/ThinPoolLV
27571.br
27572\[bu]
27573Split and remove the cache pool from the data portion of ThinPoolLV.
27574.br
27575\[bu]
27576Operates on the data sub LV of the thin pool LV.
27577.br
27578\[bu]
27579The data sub LV of the thin pool must be a cache LV.
27580
27581.B lvconvert \-\-type cache
27582VG/ThinPoolLV
27583.br
27584\[bu]
27585Convert the data portion of ThinPoolLV to type cache.
27586.br
27587\[bu]
27588Requires \-\-cachepool to specify the cache pool to use.
27589.br
27590\[bu]
27591Operates on the data sub LV of the thin pool LV.
27592.br
27593\[bu]
27594Options \-\-cachepolicy, \-\-cachesettings.
27595
27596.B lvconvert \-\-repair
27597VG/ThinPoolLV
27598.br
27599\[bu]
27600Repair ThinPoolLV.
27601
27602.SS Operations on ThinLV with type thin:
27603
27604\&
27605
27606.B lvconvert \-\-merge
27607VG/ThinLV
27608./" FIXME: use --merge-snapshot
27609.br
27610\[bu]
27611Merge ThinLV into its origin LV.
27612.br
27613\[bu]
27614ThinLV must have been created as a snapshot of another thin LV.
27615.br
27616\[bu]
27617Options \-\-background, \-\-interval.
27618
27619.SS Operations on SnapshotLV with type snapshot:
27620
27621\&
27622
27623.B lvconvert \-\-splitsnapshot
27624VG/SnapshotLV
27625.br
27626\[bu]
27627Separate COW snapshot SnapshotLV from its origin LV.
27628
27629.B lvconvert \-\-merge
27630VG/SnapshotLV
27631./" FIXME: use --merge-snapshot
27632.br
27633\[bu]
27634Merge COW snapshot SnapshotLV into its origin.
27635.br
27636\[bu]
27637Options \-\-background, \-\-interval.
27638
27639.SH OPTIONS
27640.
27641See \fBlvm\fP(8) for common options.
27642.br
27643.
27644.HP
27645.BR \-b ,
27646.BR \-\-background
27647.br
27648If the operation requires polling, this option causes the command to
27649return before the operation is complete, and polling is done in the
27650background.
27651.
27652.HP
27653.BR \-\-cachepolicy
27654.IR Policy
27655.br
27656Specifies the cache policy for a cache LV. Also see
27657.BR lvmcache (7).
27658.
27659.HP
27660.BR \-\-cachepool
27661.IR CachePoolLogicalVolume { Name | Path }
27662.br
27663Specifies the cache pool to use when converting an LV to a cache LV. If
27664CachePoolLogicalVolume is not yet a cache pool, the command will attempt
27665to convert it into a cache pool prior to the cache LV conversion.
27666Also see
27667.BR lvmcache (7).
27668.
27669.HP
27670.BR \-\-cachesettings
27671.IB Key = Value
27672.br
27673Specifies tunable values for a cache LV. (The default values should
27674usually be adequate.) The special string value \fBdefault\fP switches
27675settings back to their default kernel values and removes them from the
27676list of settings stored in LVM metadata.
27677Also see
27678.BR lvmcache (7).
27679.
27680.HP
27681.BR \-c ,
27682.BR \-\-chunksize
27683.BR \fIChunkSize [ b | B | s | S | k | K | m | M | g | G ]
27684.br
27685Sets the chunk size for a snapshot, cache pool or thin pool.
27686The default unit is in kilobytes.
27687.sp
27688For snapshots, the value must be a power of 2 between 4KiB and 512KiB
27689and the default value is 4.
27690.sp
27691For a cache pool the value must be between 32KiB and 1GiB and
27692the default value is 64.
27693.sp
27694For a thin pool the value must be between 64KiB and
276951GiB and the default value starts with 64 and scales
27696up to fit the pool metadata size within 128MiB,
27697if the pool metadata size is not specified.
27698The value must be a multiple of 64KiB.
27699(Early kernel support until thin target version 1.4 required the value
27700to be a power of 2. Discards were not supported for non-power of 2 values
27701until thin target version 1.5.)
27702.
27703.HP
27704.BR \-\-corelog
27705.br
27706Specifies or changes the log type for a mirror LV.
27707It is an alias for \fB\-\-mirrorlog core\fP.
27708(This option does not apply to the \fBraid1\fP LV type.)
27709.
27710.HP
27711.BR \-\-discards
27712.RB { ignore | nopassdown | passdown }
27713.br
27714Specifies if discards will be processed by the thin layer in the
27715kernel and passed down to the Physical Volume. This applies only
27716to thin pools. The default is \fBpassdown\fP.
27717Also see
27718.BR lvmthin (7).
27719.
27720.HP
27721.BR \-H ,
27722.BR \-\-cache
27723.br
27724Alias for
27725.B \-\-type cache.
27726See COMMANDS description for
27727.br
27728.B lvconvert \-\-type cache.
27729.
27730.HP
27731.BR \-i ,
27732.BR \-\-interval
27733.IR Seconds
27734.br
27735Report progress as a percentage at regular intervals.
27736.
27737.HP
27738.BR \-\-merge
27739.br
27740Merges a snapshot that was split from an origin LV using
27741\fB\-\-splitsnapshot\fP, back into the origin LV.
27742
27743Merges a raid1 image that was split from a raid1 LV using
27744\fB\-\-splitsnapshot\fP and \fB\-\-trackchanges\fP, back into
27745the original raid1 LV.
27746
27747To check if the kernel supports the snapshot merge feature, look for
27748"snapshot\-merge" in the output of \fBdmsetup targets\fP.
27749
27750When merging a snapshot, if both the origin and snapshot LVs are not open,
27751the merge will start immediately. Otherwise, the merge will start the
27752first time either the origin or snapshot LV are activated and both are
27753closed. Merging a snapshot into an origin that cannot be closed, for
27754example a root filesystem, is deferred until the next time the origin
27755volume is activated. When merging starts, the resulting LV will have the
27756origin's name, minor number and UUID. While the merge is in progress,
27757reads or writes to the origin appear as being directed to the snapshot
27758being merged. When the merge finishes, the merged snapshot is removed.
27759Multiple snapshots may be specified on the command line or a @tag may be
27760used to specify multiple snapshots be merged to their respective origin.
27761.
27762.HP
27763.BR \-\-mirrorlog
27764.RB { disk | core | mirrored }
27765.br
27766Specifies or changes the log type for a mirror LV.
27767The default is \fBdisk\fP, which is persistent and requires
27768a small amount of storage space, usually on a separate device
27769from the data being mirrored.
27770\fBCore\fP may be useful for short-lived mirrors. It means the mirror is
27771regenerated by copying the data from the first device again every
27772time the device is activated - e.g. possibly after every reboot.
27773Using \fBmirrored\fP will create a persistent log that is itself mirrored.
27774(This option does not apply to the \fBraid1\fP LV type.)
27775.
27776.HP
27777.BR \-m ,
27778.BR \-\-mirrors
27779.IR Number
27780.br
27781Specifies the number mirror images in addition to the original LV image,
27782e.g. \fB\-\-mirrors 1\fP means two copies of the data, the original and
27783one mirror image.
27784
27785The current maximum is 9 providing 10 raid1 images.
27786
27787This option is required when converting an LV to a \fBraid1\fP or
27788\fBmirror\fP LV.
27789
27790This option can be used alone to change the number of mirror images in an
27791existing \fBraid1\fP or \fBmirror\fP LV.
27792
27793The special case \fB\-\-mirrors 0\fP has been used historically to
27794indicate a linear LV with no mirror images.
27795.
27796.HP
27797.BR \-n ,
27798.BR \-\-name
27799.IR Name
27800.br
27801Specifies the name to use when the command is creating a new LV, e.g.
27802.B \-\-splitmirrors.
27803.
27804.HP
27805.BR \-\-noudevsync
27806.br
27807Disables udev synchronisation. The process will not wait for notification
27808from udev. It will continue irrespective of any possible udev processing
27809in the background. You should only use this if udev is not running or has
27810rules that ignore the devices LVM creates.
27811.
27812.HP
27813.BR \-\-originname
27814.IR NewExternalOriginVolumeName
27815.br
27816Specifies the name to use for the external origin LV when converting an LV
27817to a thin LV. The LV being converted becomes a read\-only external origin
27818with this name.
27819.br
27820Without this option, the default name of "lvol<n>" will be generated where
27821<n> is the LVM internal number of the LV.
27822.br
27823.
27824.\" .HP
27825.\" .BR \-\-pooldatasize
27826.\" .IR PoolDataVolumeSize [ \fBbBsSkKmMgGtTpPeE ]
27827.\" .br
27828.\" Sets the size of pool's data logical volume.
27829.\" The option \fB\-\-size\fP could be still used with thin pools.
27830.
27831.HP
27832.BR \-\-poolmetadata
27833.IR PoolMetadataLogicalVolume { Name | Path }
27834.br
27835Specifies the LV to use for thin pool metadata when converting an LV to a
27836thin pool LV.
27837.br
27838Specifies the LV to use for cache pool metadata when converting an LV to a
27839cache pool LV.
27840.br
27841The size should be between 2MiB and 16GiB.
27842.br
27843(This option can also be used when a thin pool or cache pool are created
27844as an auxiliary operation within a different command.)
27845Also see
27846.BR lvmthin (7),
27847and
27848.BR lvmcache (7).
27849.
27850.HP
27851.BR \-\-poolmetadatasize
27852.BR \fIPoolMetadataSize [ b | B | s | S | k | K | m | M | g | G ]
27853.br
27854Specifies the size of a cache pool metadata LV or a thin pool metadata LV.
27855This is used if a command creates a pool metadata LV automatically as part
27856of the operation. This option is not used when an existing LV is
27857specified as the pool metadata LV, i.e. \fB\-\-poolmetadata\fP.
27858The default unit is megabytes.
27859Also see
27860.BR lvmthin (7),
27861and
27862.BR lvmcache (7).
27863.
27864.HP
27865.BR \-\-poolmetadataspare
27866.RB { y | n }
27867.br
27868Specifies if a spare pool metadata LV should be created.
27869A spare pool metadata LV will be used for pool repair.
27870Only one spare pool metadata LV is maintained within a VG, with the size
27871of the largest existing pool metadata LV.
27872The default is \fBy\fPes.
27873.
27874.HP
27875.BR \-r ,
27876.BR \-\-readahead
27877.RB { \fIReadAheadSectors | auto | none }
27878.br
27879Specifies the read ahead sector count of a thin pool metadata LV.
27880The default value is \fBauto\fP which allows the kernel to choose
27881a suitable value automatically.
27882\fBNone\fP is equivalent to specifying zero.
27883.
27884.HP
27885.BR \-R ,
27886.BR \-\-regionsize
27887.IR MirrorLogRegionSize
27888.br
27889A mirror LV is divided into regions of this size (in MB), and the mirror
27890log uses this granularity to track which regions are in sync.
27891(This option does not apply to the \fBraid1\fP LV type.)
27892.
27893.HP
27894.BR \-\-repair
27895.br
27896Replaces failed PVs in a raid1 or mirror LV with other PVs available in
27897the VG. By default, the original number of mirror images will be restored
27898if possible. Specify \fB\-y\fP on the command line to skip the prompts.
27899Use \fB\-f\fP if you do not want any replacement. You may use
27900\fB\-\-use\-policies\fP to use the device replacement policy specified in
27901\fBlvm.conf\fP(5), see \fBactivation/mirror_log_fault_policy\fP or
27902\fBactivation/mirror_device_fault_policy\fP.
27903
27904When used with a thin pool LV, this option automates the use of the
27905\fBthin_repair\fP(8) tool on the thin pool. This repairs a very limitted
27906number of problems. Only inactive thin pools can be repaired. There is
27907no validation of metadata between kernel and LVM. This requires further
27908manual work. After successfull repair the old unmodified metadata are
27909still available in "<pool>_meta<n>" LV.
27910Also see
27911.BR lvmthin (7).
27912.
27913.HP
27914.BR \-\-replace
27915.IR PhysicalVolume
27916.br
27917Remove the specified device \fIPhysicalVolume\fP and replace it with one
27918that is available in the VG, or from a specific list of PVs specified on
27919the command line following the LV name. This option may be repeated multiple
27920times depending on the RaidLV type.
27921.
27922.HP
27923.BR \-s ,
27924.BR \-\-snapshot
27925.br
27926Alias for
27927.B \-\-type snapshot.
27928See COMMANDS description for
27929.br
27930.B lvconvert \-\-type snapshot.
27931.HP
27932.BR \-\-split
27933.br
27934Separates \fISplitableLogicalVolume\fP.
27935This option tries to detect the necessary split operation from its arguments.
27936Avoid using this option and use one of the following instead:
27937.B \-\-splitcache, \-\-splitmirrors, \-\-splitsnapshot.
27938.
27939.HP
27940.BR \-\-splitcache
27941.br
27942Separates a cache pool from a cache LV, and keeps the unused cache pool
27943LV. Before the separation, the cache is flushed. See similar option
27944.B \-\-uncache.
27945Also see
27946.BR lvmcache (7).
27947.
27948.HP
27949.BR \-\-splitmirrors
27950.IR Number
27951.br
27952Splits the specified number of images from a \fBraid1\fP or \fBmirror\fP
27953LV and uses them to create a new LV.
27954
27955If \fB\-\-trackchanges\fP is also specified, changes to the raid1 LV are
27956tracked while the split LV remains detached.
27957.B lvconvert \-\-merge
27958can be used to recombine the split images with the original raid1 LV.
27959
27960A name can be specified for the new LV with \fB\-\-name\fP (a name is
27961required without \fB\-\-trackchanges\fP).
27962.
27963.HP
27964.BR \-\-splitsnapshot
27965.br
27966Separates a COW snapshot from its origin LV. The LV that is split off
27967contains the chunks that differ from the origin LV along with metadata
27968describing them. This LV can be wiped and then destroyed with lvremove.
27969See corresponding operation
27970.B lvconvert \-\-type snapshot.
27971.
27972.HP
27973.BR \-\-stripes
27974.IR Number
27975.br
27976Specifies the number of stripes in a striped LV. This is the number of
27977physical volumes (devices) that a striped LV is spread across. Data that
27978appears sequential in the LV is spread across multiple devices in units of
27979the stripe size (see \fB\-\-stripesize\fP). This does not apply to
27980existing allocated space, only newly allocated space can be striped.
27981.
27982.HP
27983.BR \-I ,
27984.BR \-\-stripesize
27985.IR StripeSize
27986.br
27987Specifies the stripe size in kilobytes for a striped LV. The stripe size
27988is the number of kilobytes written to each stripe, i.e. to one device,
27989before writing to the next stripe/device. StripeSize must be a power of 2
27990and cannot exceed the VG physical extent (PE) size.
27991.
27992.HP
27993.BR \-\-type
27994.IR SegmentType
27995.br
27996Converts an LV from one segment type to another.
27997See COMMANDS section for a description of converting between each type.
27998.
27999.HP
28000.BR \-\-thinpool
28001.IR ThinPoolLogicalVolume { Name | Path }
28002.br
28003Specifies the thin pool to use when converting an LV to a thin LV. If
28004ThinPoolLogicalVolume is not yet a thin pool, the command will attempt to
28005convert it to a thin pool prior to the thin LV conversion.
28006Also see
28007.BR lvmthin (7).
28008.
28009.HP
28010.BR \-\-trackchanges
28011.br
28012Can be used with \fB\-\-splitmirrors\fP on a raid1 LV. This causes
28013changes to the original raid1 LV to be tracked while the split images
28014remain detached. This allows the read\-only detached image(s) to be
28015merged efficiently back into the raid1 LV later. Only the regions with
28016changed data are resynchronized during merge. (This option only applies
28017to the \fBraid1\fP LV type.)
28018.
28019.HP
28020.BR \-T ,
28021.BR \-\-thin
28022.br
28023Alias for
28024.B \-\-type thin.
28025See COMMANDS description for
28026.br
28027.B lvconvert \-\-type thin.
28028.
28029.HP
28030.BR \-\-uncache
28031.br
28032Separates a cache pool from a cache LV, and removes the unused cache pool
28033LV. Before the separation, the cache is flushed. See similar option
28034.B \-\-splitcache.
28035Also see
28036.BR lvmcache (7).
28037.
28038.HP
28039.BR \-Z ,
28040.BR \-\-zero
28041.RB { y | n }
28042.br
28043For snapshots, this controls zeroing of the first 4KiB of data in the
28044snapshot. If the LV is read\-only, the snapshot will not be zeroed.
28045
28046For thin pools, this controls zeroing of provisioned blocks.
28047Provisioning of large zeroed chunks negatively impacts performance.
28048Also see
28049.BR lvmthin (7).
28050.
28051
28052.SH Examples
28053.
28054Convert a linear LV to a two-way mirror LV:
28055.br
28056.B lvconvert \-\-type mirror \-\-mirrors 1 vg/lvol1
28057
28058Convert a linear LV to a two-way RAID1 LV:
28059.br
28060.B lvconvert \-\-type raid1 \-\-mirrors 1 vg/lvol1
28061
28062Convert a mirror LV to use an in\-memory log:
28063.br
28064.B lvconvert \-\-mirrorlog core vg/lvol1
28065
28066Convert a mirror LV to use a disk log:
28067.br
28068.B lvconvert \-\-mirrorlog disk vg/lvol1
28069
28070Convert a mirror or raid1 LV to a linear LV:
28071.br
28072.B lvconvert --type linear vg/lvol1
28073
28074Convert a mirror LV to a raid1 LV with the same number of images:
28075.br
28076.B lvconvert \-\-type raid1 vg/lvol1
28077
28078./" Split and merge a COW snapshot:
28079./" TODO
28080Convert a linear LV to a two-way mirror LV, allocating new extents from specific
28081PV ranges:
28082.br
28083.B lvconvert \-\-mirrors 1 vg/lvol1 /dev/sda:0\-15 /dev/sdb:0\-15
28084
28085Convert a mirror LV to a linear LV, freeing physical extents from a specific PV:
28086.br
28087.B lvconvert \-\-type linear vg/lvol1 /dev/sda
28088
28089Split one image from a mirror or raid1 LV, making it a new LV:
28090.br
28091.B lvconvert \-\-splitmirrors 1 \-\-name lv_split vg/lvol1
28092
28093Split one image from a raid1 LV, and track changes made to the raid1 LV
28094while the split image remains detached:
28095.br
28096.B lvconvert \-\-splitmirrors 1 \-\-trackchanges vg/lvol1
28097
28098Merge an image (that was previously created with \-\-splitmirrors and
28099\-\-trackchanges) back into the original raid1 LV:
28100.br
28101.B lvconvert \-\-merge vg/lvol1_rimage_1
28102./" FIXME: use merge-mirror
28103
28104Replace PV /dev/sdb1 with PV /dev/sdf1 in a raid1/4/5/6/10 LV:
28105.br
28106.B lvconvert \-\-replace /dev/sdb1 vg/lvol1 /dev/sdf1
28107
28108Replace 3 PVs /dev/sd[b-d]1 with PVs /dev/sd[f-h]1 in a raid1 LV:
28109.br
28110.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 \-\-replace /dev/sdd1
28111.RS
28112.B vg/lvol1 /dev/sd[fgh]1
28113.RE
28114
28115Replace the maximum of 2 PVs /dev/sd[bc]1 with PVs /dev/sd[gh]1 in a raid6 LV:
28116.br
28117.B lvconvert \-\-replace /dev/sdb1 \-\-replace /dev/sdc1 vg/lvol1 /dev/sd[gh]1
28118
28119Convert an LV into a thin LV in the specified thin pool. The existing LV
28120is used as an external read\-only origin for the new thin LV.
28121.br
28122.B lvconvert \-\-type thin \-\-thinpool vg/tpool1 vg/lvol1
28123
28124Convert an LV into a thin LV in the specified thin pool. The existing LV
28125is used as an external read\-only origin for the new thin LV, and is
28126renamed "external":
28127.br
28128.B lvconvert \-\-type thin \-\-thinpool vg/tpool1
28129.RS
28130.B \-\-originname external vg/lvol1
28131.RE
28132
28133Convert an LV to a cache pool LV using another specified LV for cache pool
28134metadata:
28135.br
28136.B lvconvert \-\-type cache-pool \-\-poolmetadata vg/poolmeta1 vg/lvol1
28137
28138Convert an LV to a cache LV using the specified cache pool and chunk size:
28139.br
28140.B lvconvert \-\-type cache \-\-cachepool vg/cpool1 \-c 128 vg/lvol1
28141
28142Detach and keep the cache pool from a cache LV:
28143.br
28144.B lvconvert \-\-splitcache vg/lvol1
28145
28146Detach and remove the cache pool from a cache LV:
28147.br
28148.B lvconvert \-\-uncache vg/lvol1
28149
28150.SH SEE ALSO
28151.BR lvm (8),
28152.BR lvm.conf (5),
28153.BR lvmcache (7),
28154.BR lvmthin (7),
28155.BR lvdisplay (8),
28156.BR lvextend (8),
28157.BR lvreduce (8),
28158.BR lvremove (8),
28159.BR lvrename (8),
28160.BR lvscan (8),
28161.BR vgcreate (8),
28162.BR cache_dump (8),
28163.BR cache_repair (8),
28164.BR cache_restore (8),
28165.BR thin_dump (8),
28166.BR thin_repair (8),
28167.BR thin_restore (8)
28168\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvrename.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002547\013062740170\0020141\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVRENAME 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
28169.SH NAME
28170lvrename \(em rename a logical volume
28171.SH SYNOPSIS
28172.B lvrename
28173.RB [ \-A | \-\-autobackup
28174.RI { y | n }]
28175.RB [ \-\-commandprofile
28176.IR ProfileName ]
28177.RB [ \-d | \-\-debug ]
28178.RB [ \-h | \-\-help ]
28179.RB [ \-t | \-\-test ]
28180.RB [ \-v | \-\-verbose ]
28181.RB [ \-\-version ]
28182.RB [ \-f | \-\-force ]
28183.RB [ \-\-noudevsync ]
28184.RB [ \-\-reportformat
28185.RB { basic | json }]
28186.RI { OldLogicalVolume { Name | Path }
28187.IR NewLogicalVolume { Name | Path }
28188|
28189.I VolumeGroupName OldLogicalVolumeName NewLogicalVolumeName\fR}
28190.SH DESCRIPTION
28191lvrename renames an existing logical volume or an existing
28192historical logical volume from
28193.IR OldLogicalVolume { Name | Path }
28194to
28195.IR NewLogicalVolume { Name | Path }.
28196.SH OPTIONS
28197See \fBlvm\fP(8) for common options.
28198.TP
28199.BR \-\-noudevsync
28200Disable udev synchronisation. The
28201process will not wait for notification from udev.
28202It will continue irrespective of any possible udev processing
28203in the background. You should only use this if udev is not running
28204or has rules that ignore the devices LVM2 creates.
28205.SH EXAMPLE
28206To rename lvold in volume group vg02 to lvnew:
28207.sp
28208.B lvrename /dev/vg02/lvold vg02/lvnew
28209.sp
28210An alternate syntax to rename this logical volume is:
28211.sp
28212.B lvrename vg02 lvold lvnew
28213.sp
28214.SH SEE ALSO
28215.BR lvm (8),
28216.BR lvchange (8),
28217.BR vgcreate (8),
28218.BR vgrename (8)
28219\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm-fullreport.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012501\013062740170\0021311\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVM-FULLREPORT 8 "LVM TOOLS #VERSION#" "Red Hat, Inc" \" -*- nroff -*-
28220.SH NAME
28221lvm fullreport \(em Report information about PVs, PV segments, VGs, LVs and LV segments, all at once for each VG.
28222.SH SYNOPSIS
28223.B lvm fullreport
28224.RB [ \-a | \-\-all ]
28225.RB [ \-\-aligned ]
28226.RB [ \-\-binary ]
28227.RB [ \-\-commandprofile
28228.IR ProfileName ]
28229.RB [[ \-\-configreport
28230.IR ReportName ]
28231.RB [ \-o | \-\-options
28232.RI [ + | \- | # ] Field1 [, Field2 ...]
28233.RB [ \-O | \-\-sort
28234.RI [ + | \- ] Key1 [, Key2 ...]]
28235.RB [ \-S | \-\-select
28236.IR Selection ]
28237.RB ...]
28238.RB [ \-d | \-\-debug ]
28239.RB [ \-h | \-? | \-\-help ]
28240.RB [ \-\-ignorelockingfailure ]
28241.RB [ \-\-ignoreskippedcluster ]
28242.RB [ \-\-logonly ]
28243.RB [ \-\-nameprefixes ]
28244.RB [ \-\-noheadings ]
28245.RB [ \-\-nosuffix ]
28246.RB [ \-P | \-\-partial ]
28247.RB [ \-\-reportformat
28248.RB { basic | json }]
28249.RB [ \-\-rows ]
28250.RB [ \-\-separator
28251.IR Separator ]
28252.RB [ \-\-unbuffered ]
28253.RB [ \-\-units
28254.IR hHbBsSkKmMgGtTpPeE ]
28255.RB [ \-\-unquoted ]
28256.RB [ \-v | \-\-verbose ]
28257.RB [ \-\-version ]
28258.RI [ VolumeGroupName
28259.RI [ VolumeGroupName ...]]
28260.SH DESCRIPTION
28261lvm fullreport produces formatted output about PVs, PV segments, VGs, LVs
28262and LV segments, all at once for each VG and guarded by per-VG lock
28263for consistency.
28264.SH OPTIONS
28265See \fBlvm\fP(8) for common options.
28266.TP
28267.B \-\-all
28268Include information in the output about internal Logical Volumes that
28269are components of normally-accessible Logical Volumes, such as mirrors,
28270but which are not independently accessible (e.g. not mountable).
28271The names of such Logical Volumes are enclosed within square brackets
28272in the output. For example, after creating a mirror using
28273.B lvcreate -m1 \-\-mirrorlog disk
28274, this option will reveal three internal Logical
28275Volumes, with suffixes mimage_0, mimage_1, and mlog.
28276.TP
28277.B \-\-aligned
28278Use with \fB\-\-separator\fP to align the output columns.
28279.TP
28280.B \-\-binary
28281Use binary values "0" or "1" instead of descriptive literal values
28282for columns that have exactly two valid values to report (not counting
28283the "unknown" value which denotes that the value could not be determined).
28284.TP
28285.B \-\-configreport \fI ReportName
28286Make any subsequent \fB\-o, \-\-options\fP, \fB\-O, \-\-sort\fP or
28287\fB\-S, \-\-select\fP to apply for \fIReportName\fP where \fIReportName\fP
28288is 'pv' for PV subreport, 'pvseg' for PV segment subreport, 'vg' for
28289VG subreport, 'lv' for LV subreport, 'seg' for LV segment subreport or 'log'
28290for log report. If \fB\-\-configreport\fP option is not used to identify a
28291report, then all command's subreports are assumed except log report. The log
28292report is available only if enabled by \fBlog/report_command_log\fP
28293\fBlvm.conf\fP(5) setting or if \fB\-\-logonly\fP option is used.
28294.TP
28295.B \-\-logonly
28296Suppress the main report itself and display only log report on output.
28297.TP
28298.B \-\-nameprefixes
28299Add an "LVM2_" prefix plus the field name to the output. Useful
28300with \fB\-\-noheadings\fP to produce a list of field=value pairs that can
28301be used to set environment variables (for example, in \fBudev\fP(7) rules).
28302.TP
28303.B \-\-noheadings
28304Suppress the headings line that is normally the first line of output.
28305Useful if grepping the output.
28306.TP
28307.B \-\-nosuffix
28308Suppress the suffix on output sizes. Use with \fB\-\-units\fP
28309(except h and H) if processing the output.
28310.TP
28311.BR \-o ", " \-\-options
28312Comma-separated ordered list of columns.
28313.IP
28314Precede the list with '\fI+\fP' to append to the current list
28315of columns, '\fI-\fP' to remove from the current list of columns
28316or '\fI#\fP' to compact given columns. The \fI\-o\fP option can
28317be repeated, providing several lists. These lists are evaluated
28318from left to right.
28319.IP
28320For the list of columns, see \fBpvs\fP(8), \fBvgs\fP(8),
28321\fBlvs\fP(8) man page or check \fBpvs\fP, \fBvgs\fP, \fBlvs -o help\fP
28322output.
28323.TP
28324.BR \-O ", " \-\-sort
28325Comma-separated ordered list of columns to sort by. Replaces the default
28326selection. Precede any column with '\fI\-\fP' for a reverse sort on that
28327column.
28328.TP
28329.B \-\-rows
28330Output columns as rows.
28331.TP
28332.BR \-S ", " \-\-select " " \fISelection
28333Display only rows that match Selection criteria. All rows are displayed with
28334the additional "selected" column (\fB-o selected\fP) showing 1 if the row
28335matches the Selection and 0 otherwise. The Selection criteria are defined
28336by specifying column names and their valid values (that can include reserved
28337values) while making use of supported comparison operators. See \fBlvm\fP(8)
28338and \fB\-S\fP, \fB\-\-select\fP description for more detailed information
28339about constructing the Selection criteria. As a quick help and to see full
28340list of column names that can be used in Selection including the list of
28341reserved values and the set of supported selection operators, check the
28342output of \fBpvs\fP, \fBvgs\fP, \fBlvs -S help\fP command.
28343.TP
28344.B \-\-separator \fISeparator
28345String to use to separate each column. Useful if grepping the output.
28346.TP
28347.B \-\-unbuffered
28348Produce output immediately without sorting or aligning the columns properly.
28349.TP
28350.B \-\-units \fIhHbBsSkKmMgGtTpPeE
28351All sizes are output in these units: (h)uman-readable, (b)ytes, (s)ectors,
28352(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
28353Capitalise to use multiples of 1000 (S.I.) instead of 1024. Can also specify
28354custom units e.g. \-\-units 3M
28355.TP
28356.B \-\-unquoted
28357When used with \fB\-\-nameprefixes\fP, output values in the field=value
28358pairs are not quoted.
28359.SH SEE ALSO
28360.BR lvm (8),
28361.BR pvs (8),
28362.BR vgs (8),
28363.BR lvs (8)
28364\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmpolld.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006053\013062740170\0020155\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMPOLLD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
28365.SH NAME
28366lvmpolld \(em LVM poll daemon
28367.SH SYNOPSIS
28368.B lvmpolld
28369.RB [ \-l | \-\-log
28370.RI { all | wire | debug }]
28371.RB [ \-p | \-\-pidfile
28372.IR pidfile_path ]
28373.RB [ \-s | \-\-socket
28374.IR socket_path ]
28375.RB [ \-B | \-\-binary
28376.IR lvm_binary_path ]
28377.RB [ \-t | \-\-timeout
28378.IR timeout_value ]
28379.RB [ \-f | \-\-foreground ]
28380.RB [ \-h | \-\-help ]
28381.RB [ \-V | \-\-version ]
28382
28383.B lvmpolld
28384.RB [ \-\-dump ]
28385.SH DESCRIPTION
28386lvmpolld is polling daemon for LVM. The daemon receives requests for polling
28387of already initialised operations originating in LVM2 command line tool.
28388The requests for polling originate in the \fBlvconvert\fP, \fBpvmove\fP,
28389\fBlvchange\fP or \fBvgchange\fP LVM2 commands.
28390
28391The purpose of lvmpolld is to reduce the number of spawned background processes
28392per otherwise unique polling operation. There should be only one. It also
28393eliminates the possibility of unsolicited termination of background process by
28394external factors.
28395
28396lvmpolld is used by LVM only if it is enabled in \fBlvm.conf\fP(5) by
28397specifying the \fBglobal/use_lvmpolld\fP setting. If this is not defined in the
28398LVM configuration explicitly then default setting is used instead (see the
28399output of \fBlvmconfig \-\-type default global/use_lvmpolld\fP command).
28400.SH OPTIONS
28401
28402To run the daemon in a test environment both the pidfile_path and the
28403socket_path should be changed from the defaults.
28404.TP
28405.BR \-f ", " \-\-foreground
28406Don't fork, but run in the foreground.
28407.TP
28408.BR \-h ", " \-\-help
28409Show help information.
28410.TP
28411.IR \fB\-l\fP ", " \fB\-\-log\fP " {" all | wire | debug }
28412Select the type of log messages to generate.
28413Messages are logged by syslog.
28414Additionally, when \-f is given they are also sent to standard error.
28415There are two classes of messages: wire and debug. Selecting 'all' supplies both
28416and is equivalent to a comma-separated list \-l wire,debug.
28417.TP
28418.BR \-p ", " \-\-pidfile " " \fIpidfile_path
28419Path to the pidfile. This overrides both the built-in default
28420(#DEFAULT_PID_DIR#/lvmpolld.pid) and the environment variable
28421\fBLVM_LVMPOLLD_PIDFILE\fP. This file is used to prevent more
28422than one instance of the daemon running simultaneously.
28423.TP
28424.BR \-s ", " \-\-socket " " \fIsocket_path
28425Path to the socket file. This overrides both the built-in default
28426(#DEFAULT_RUN_DIR#/lvmpolld.socket) and the environment variable
28427\fBLVM_LVMPOLLD_SOCKET\fP.
28428.TP
28429.BR \-t ", " \-\-timeout " " \fItimeout_value
28430The daemon may shutdown after being idle for the given time (in seconds). When the
28431option is omitted or the value given is zero the daemon never shutdowns on idle.
28432.TP
28433.BR \-B ", " \-\-binary " " \fIlvm_binary_path
28434Optional path to alternative LVM binary (default: #LVM_PATH#). Use for
28435testing purposes only.
28436.TP
28437.BR \-V ", " \-\-version
28438Display the version of lvmpolld daemon.
28439.TP
28440.B \-\-dump
28441Contact the running lvmpolld daemon to obtain the complete state and print it
28442out in a raw format.
28443.SH ENVIRONMENT VARIABLES
28444.TP
28445.B LVM_LVMPOLLD_PIDFILE
28446Path for the pid file.
28447.TP
28448.B LVM_LVMPOLLD_SOCKET
28449Path for the socket file.
28450
28451.SH SEE ALSO
28452.BR lvm (8),
28453.BR lvm.conf (5)
28454\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/dmstats.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000072423\013062740170\0020007\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH DMSTATS 8 "Jun 23 2016" "Linux" "MAINTENANCE COMMANDS"
28455
28456.de OPT_PROGRAMS
28457. RB \%[ \-\-allprograms | \-\-programid
28458. IR id ]
28459..
28460.
28461.de OPT_REGIONS
28462. RB \%[ \-\-allregions | \-\-regionid
28463. IR id ]
28464..
28465.de OPT_OBJECTS
28466. RB [ \-\-area ]
28467. RB [ \-\-region ]
28468. RB [ \-\-group ]
28469..
28470.
28471.\" Print units suffix, use with arg to print human
28472.\" man2html can't handle too many changes per command
28473.de UNITS
28474. BR b | B | s | S | k | K | m | M | \c
28475. BR g | G | t | T | p | P | e | E ]
28476..
28477.
28478.\" Print help text for units, use with arg to print human
28479.de HELP_UNITS
28480. RB ( b )ytes,
28481. RB ( s )ectors,
28482. RB ( k )ilobytes,
28483. RB ( m )egabytes,
28484. RB ( g )igabytes,
28485. RB ( t )erabytes,
28486. RB ( p )etabytes,
28487. RB ( e )xabytes.
28488. nop Capitalise to use multiples of 1000 (S.I.) instead of 1024.
28489..
28490.
28491.SH NAME
28492.
28493dmstats \(em device-mapper statistics management
28494.
28495.SH SYNOPSIS
28496.
28497.B dmsetup
28498.B stats
28499.I command
28500.RB [ options ]
28501.sp
28502.
28503.PD 0
28504.HP
28505.B dmstats
28506.de CMD_COMMAND
28507. ad l
28508. IR command
28509. RI [ device_name
28510. RB | \-\-uuid
28511. IR uuid | \fB\-\-major
28512. IR major
28513. BR \-\-minor
28514. IR minor ]
28515. ad b
28516..
28517.CMD_COMMAND
28518.
28519.HP
28520.B dmstats
28521.de CMD_CLEAR
28522. ad l
28523. BR clear
28524. IR device_name
28525. OPT_PROGRAMS
28526. OPT_REGIONS
28527. ad b
28528..
28529.CMD_CLEAR
28530.
28531.HP
28532.B dmstats
28533.de CMD_CREATE
28534. ad l
28535. BR create
28536. RB [ device_name...
28537. RB | file_path... ]
28538. RB [ \-\-alldevices ]
28539. RB [ \-\-areas
28540. IR nr_areas | \fB\-\-areasize
28541. IR area_size ]
28542. RB [ \-\-bounds
28543. IR \%histogram_boundaries ]
28544. RB [ \-\-filemap ]
28545. RB [ \-\-nogroup ]
28546. RB [ \-\-precise ]
28547. RB [ \-\-start
28548. IR start_sector
28549. BR \-\-length
28550. IR length | \fB\-\-segments ]
28551. RB \%[ \-\-userdata
28552. IR user_data ]
28553. RB [ \-\-programid
28554. IR id ]
28555. ad b
28556..
28557.CMD_CREATE
28558.
28559.HP
28560.B dmstats
28561.de CMD_DELETE
28562. ad l
28563. BR delete
28564. RI [ device_name ]
28565. RB [ \-\-alldevices ]
28566. OPT_PROGRAMS
28567. OPT_REGIONS
28568. ad b
28569..
28570.CMD_DELETE
28571.
28572.HP
28573.B dmstats
28574.de CMD_GROUP
28575. ad l
28576. BR group
28577. RI [ device_name ]
28578. RB [ \-\-alias
28579. IR name ]
28580. RB [ \-\-alldevices ]
28581. RB [ \-\-regions
28582. IR regions ]
28583. ad b
28584..
28585.CMD_GROUP
28586.HP
28587.B dmstats
28588.de CMD_HELP
28589. ad l
28590. BR help
28591. RB [ \-c | \-C | \-\-columns ]
28592. ad b
28593..
28594.CMD_HELP
28595.
28596.HP
28597.B dmstats
28598.de CMD_LIST
28599. ad l
28600. BR list
28601. RI [ device_name ]
28602. RB [ \-\-histogram ]
28603. OPT_PROGRAMS
28604. RB [ \-\-units
28605. IR units ]
28606. OPT_OBJECTS
28607. RB \%[ \-\-nosuffix ]
28608. RB [ \-\-notimesuffix ]
28609. RB \%[ \-v | \-\-verbose [ \-v | \-\-verbose ]]
28610. ad b
28611..
28612.CMD_LIST
28613.
28614.HP
28615.B dmstats
28616.de CMD_PRINT
28617. ad l
28618. BR print
28619. RI [ device_name ]
28620. RB [ \-\-clear ]
28621. OPT_PROGRAMS
28622. OPT_REGIONS
28623. ad b
28624..
28625.CMD_PRINT
28626.
28627.HP
28628.B dmstats
28629.de CMD_REPORT
28630. ad l
28631. BR report
28632. RI [ device_name ]
28633. RB [ \-\-interval
28634. IR seconds ]
28635. RB [ \-\-count
28636. IR count ]
28637. RB [ \-\-units
28638. IR units ]
28639. RB [ \-\-histogram ]
28640. OPT_PROGRAMS
28641. OPT_REGIONS
28642. OPT_OBJECTS
28643. RB [ \-O | \-\-sort
28644. IR sort_fields ]
28645. RB [ \-S | \-\-select
28646. IR selection ]
28647. RB [ \-\-units
28648. IR units ]
28649. RB [ \-\-nosuffix ]
28650. RB \%[ \-\-notimesuffix ]
28651. ad b
28652..
28653.CMD_REPORT
28654.HP
28655.B dmstats
28656.de CMD_UNGROUP
28657. ad l
28658. BR ungroup
28659. RI [ device_name ]
28660. RB [ \-\-alldevices ]
28661. RB [ \-\-groupid
28662. IR id ]
28663. ad b
28664..
28665.CMD_UNGROUP
28666.
28667.PD
28668.ad b
28669.
28670.SH DESCRIPTION
28671.
28672The dmstats program manages IO statistics regions for devices that use
28673the device-mapper driver. Statistics regions may be created, deleted,
28674listed and reported on using the tool.
28675
28676The first argument to dmstats is a \fIcommand\fP.
28677
28678The second argument is the \fIdevice name\fP,
28679\fIuuid\fP or \fImajor\fP and \fIminor\fP numbers.
28680
28681Further options permit the selection of regions, output format
28682control, and reporting behaviour.
28683
28684When no device argument is given dmstats will by default operate on all
28685device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
28686commands require the use of \fB\-\-alldevices\fP when used in this way.
28687.
28688.SH OPTIONS
28689.
28690.HP
28691.BR \-\-alias
28692.IR name
28693.br
28694Specify an alias name for a group.
28695.
28696.HP
28697.BR \-\-alldevices
28698.br
28699If no device arguments are given allow operation on all devices when
28700creating or deleting regions.
28701.
28702.HP
28703.BR \-\-allprograms
28704.br
28705Include regions from all program IDs for list and report operations.
28706.br
28707.HP
28708.BR \-\-allregions
28709.br
28710Include all present regions for commands that normally accept a single
28711region identifier.
28712.
28713.HP
28714.BR \-\-area
28715.br
28716When peforming a list or report, include objects of type area in the
28717results.
28718.
28719.HP
28720.BR \-\-areas
28721.IR nr_areas
28722.br
28723Specify the number of statistics areas to create within a new region.
28724.
28725.HP
28726.BR \-\-areasize
28727.IR area_size \c
28728.RB [ \c
28729.UNITS
28730.br
28731Specify the size of areas into which a new region should be divided. An
28732optional suffix selects units of:
28733.HELP_UNITS
28734.
28735.HP
28736.BR \-\-clear
28737.br
28738When printing statistics counters, also atomically reset them to zero.
28739.
28740.HP
28741.BR \-\-count
28742.IR count
28743.br
28744Specify the iteration count for repeating reports. If the count
28745argument is zero reports will continue to repeat until interrupted.
28746.
28747.HP
28748.BR \-\-group
28749.br
28750When peforming a list or report, include objects of type group in the
28751results.
28752.
28753.HP
28754.BR \-\-filemap
28755.br
28756Instead of creating regions on a device as specified by command line
28757options, open the file found at each \fBfile_path\fP argument, and
28758create regions corresponding to the locations of the on-disk extents
28759allocated to the file(s).
28760.
28761.HP
28762.BR \-\-groupid
28763.IR id
28764.br
28765Specify the group to operate on.
28766.
28767.HP
28768.BR \-\-bounds
28769.IR histogram_boundaries \c
28770.RB [ ns | us | ms | s ]
28771.br
28772Specify the boundaries of a latency histogram to be tracked for the
28773region as a comma separated list of latency values. Latency values are
28774given in nanoseconds. An optional unit suffix of
28775.BR ns ,
28776.BR us ,
28777.BR ms ,
28778or \fBs\fP may be given after each value to specify units of
28779nanoseconds, microseconds, miliseconds or seconds respectively.
28780.
28781.HP
28782.BR \-\-histogram
28783.br
28784When used with the \fBreport\fP and \fBlist\fP commands select default
28785fields that emphasize latency histogram data.
28786.
28787.HP
28788.BR \-\-interval
28789.IR seconds
28790.br
28791Specify the interval in seconds between successive iterations for
28792repeating reports. If \fB\-\-interval\fP is specified but
28793\fB\-\-count\fP is not,
28794reports will continue to repeat until interrupted.
28795.
28796.HP
28797.BR \-\-length
28798.IR length \c
28799.RB [ \c
28800.UNITS
28801.br
28802Specify the length of a new statistics region in sectors. An optional
28803suffix selects units of:
28804.HELP_UNITS
28805.
28806.HP
28807.BR \-j | \-\-major
28808.IR major
28809.br
28810Specify the major number.
28811.
28812.HP
28813.BR \-m | \-\-minor
28814.IR minor
28815.br
28816Specify the minor number.
28817.
28818.HP
28819.BR \-\-nogroup
28820.br
28821When creating regions mapping the extents of a file in the file
28822system, do not create a group or set an alias.
28823.
28824.HP
28825.BR \-\-nosuffix
28826.br
28827Suppress the suffix on output sizes. Use with \fB\-\-units\fP
28828(except h and H) if processing the output.
28829.
28830.HP
28831.BR \-\-notimesuffix
28832.br
28833Suppress the suffix on output time values. Histogram boundary values
28834will be reported in units of nanoseconds.
28835.
28836.HP
28837.BR \-o | \-\-options
28838.br
28839Specify which report fields to display.
28840.
28841.HP
28842.BR \-O | \-\-sort
28843.IR sort_fields
28844.br
28845Sort output according to the list of fields given. Precede any
28846sort field with '\fB-\fP' for a reverse sort on that column.
28847.
28848.HP
28849.BR \-\-precise
28850.br
28851Attempt to use nanosecond precision counters when creating new
28852statistics regions.
28853.
28854.HP
28855.BR \-\-programid
28856.IR id
28857.br
28858Specify a program ID string. When creating new statistics regions this
28859string is stored with the region. Subsequent operations may supply a
28860program ID in order to select only regions with a matching value. The
28861default program ID for dmstats-managed regions is "dmstats".
28862.
28863.HP
28864.BR \-\-region
28865.br
28866When peforming a list or report, include objects of type region in the
28867results.
28868.
28869.HP
28870.BR \-\-regionid
28871.IR id
28872.br
28873Specify the region to operate on.
28874.
28875.HP
28876.BR \-\-regions
28877.IR region_list
28878.br
28879Specify a list of regions to group. The group list is a comma-separated
28880list of region identifiers. Continuous sequences of identifiers may be
28881expressed as a hyphen separated range, for example: '1-10'.
28882.
28883.HP
28884.BR \-\-relative
28885.br
28886If displaying the histogram report show relative (percentage) values
28887instead of absolute counts.
28888.
28889.HP
28890.BR \-S | \-\-select
28891.IR selection
28892.br
28893Display only rows that match \fIselection\fP criteria. All rows with the
28894additional "selected" column (\fB\-o selected\fP) showing 1 if the row matches
28895the \fIselection\fP and 0 otherwise. The selection criteria are defined by
28896specifying column names and their valid values while making use of
28897supported comparison operators.
28898.
28899.HP
28900.BR \-\-start
28901.IR start \c
28902.RB [ \c
28903.UNITS
28904.br
28905Specify the start offset of a new statistics region in sectors. An
28906optional suffix selects units of:
28907.HELP_UNITS
28908.
28909.HP
28910.BR \-\-segments
28911.br
28912When used with \fBcreate\fP, create a new statistics region for each
28913target contained in the given device(s). This causes a separate region
28914to be allocated for each segment of the device.
28915
28916The newly created regions are automatically placed into a group unless
28917the \fB\-\-nogroup\fP option is given. When grouping is enabled a group
28918alias may be specified using the \fB\-\-alias\fP option.
28919.
28920.HP
28921.BR \-\-units
28922.RI [ units ] \c
28923.RB [ h | H | \c
28924.UNITS
28925.br
28926Set the display units for report output.
28927All sizes are output in these units:
28928.RB ( h )uman-readable,
28929.HELP_UNITS
28930Can also specify custom units e.g. \fB\-\-units\ 3M\fP.
28931.
28932.HP
28933.BR \-\-userdata
28934.IR user_data
28935.br
28936Specify user data (a word) to be stored with a new region. The value
28937is added to any internal auxilliary data (for example, group
28938information), and stored with the region in the aux_data field provided
28939by the kernel. Whitespace is not permitted.
28940.
28941.HP
28942.BR \-u | \-\-uuid
28943.br
28944Specify the uuid.
28945.
28946.HP
28947.BR \-v | \-\-verbose " [" \-v | \-\-verbose ]
28948.br
28949Produce additional output.
28950.
28951.SH COMMANDS
28952.
28953.HP
28954.CMD_CLEAR
28955.br
28956Instructs the kernel to clear statistics counters for the speficied
28957regions (with the exception of in-flight IO counters).
28958.
28959.HP
28960.CMD_CREATE
28961.br
28962Creates one or more new statistics regions on the specified device(s).
28963
28964The region will span the entire device unless \fB\-\-start\fP and
28965\fB\-\-length\fP or \fB\-\-segments\fP are given. The \fB\-\-start\fP an
28966\fB\-\-length\fP options allow a region of arbitrary length to be placed
28967at an arbitrary offset into the device. The \fB\-\-segments\fP option
28968causes a new region to be created for each target in the corresponding
28969device-mapper device's table.
28970
28971If the \fB\-\-precise\fP option is used the command will attempt to
28972create a region using nanosecond precision counters.
28973
28974If \fB\-\-bounds\fP is given a latency histogram will be tracked for
28975the new region. The boundaries of the histogram bins are given as a
28976comma separated list of latency values. There is an implicit lower bound
28977of zero on the first bin and an implicit upper bound of infinity (or the
28978configured interval duration) on the final bin.
28979
28980Latencies are given in nanoseconds. An optional unit suffix of ns, us,
28981ms, or s may be given after each value to specify units of nanoseconds,
28982microseconds, miliseconds or seconds respectively, so for example, 10ms
28983is equivalent to 10000000. Latency values with a precision of less than
28984one milisecond can only be used when precise timestamps are enabled: if
28985\fB\-\-precise\fP is not given and values less than one milisecond are
28986used it will be enabled automatically.
28987
28988An optional \fBprogram_id\fP or \fBuser_data\fP string may be associated
28989with the region. A \fBprogram_id\fP may then be used to select regions
28990for subsequent list, print, and report operations. The \fBuser_data\fP
28991stores an arbitrary string and is not used by dmstats or the
28992device-mapper kernel statistics subsystem.
28993
28994By default dmstats creates regions with a \fBprogram_id\fP of
28995"dmstats".
28996
28997On success the \fBregion_id\fP of the newly created region is printed
28998to stdout.
28999
29000If the \fB\-\-filemap\fP option is given with a regular file, or list
29001of files, as the \fBfile_path\fP argument, instead of creating regions
29002with parameters specified on the command line, \fBdmstats\fP will open
29003the files located at \fBfile_path\fP and create regions corresponding to
29004the physical extents allocated to the file. This can be used to monitor
29005statistics for individual files in the file system, for example, virtual
29006machine images, swap areas, or large database files.
29007
29008To work with the \fB\-\-filemap\fP option, files must be located on a
29009local file system, backed by a device-mapper device, that supports
29010physical extent data using the FIEMAP ioctl (Ext4 and XFS for e.g.).
29011
29012By default regions that map a file are placed into a group and the
29013group alias is set to the basename of the file. This behaviour can be
29014overridden with the \fB\-\-alias\fP and \fB\-\-nogroup\fP options.
29015
29016Use the \fB\-\-group\fP option to only display information for groups
29017when listing and reporting.
29018.
29019.HP
29020.CMD_DELETE
29021.br
29022Delete the specified statistics region. All counters and resources used
29023by the region are released and the region will not appear in the output
29024of subsequent list, print, or report operations.
29025
29026All regions registered on a device may be removed using
29027\fB\-\-allregions\fP.
29028
29029To remove all regions on all devices both \fB\-\-allregions\fP and
29030\fB\-\-alldevices\fP must be used.
29031
29032If a \fB\-\-groupid\fP is given instead of a \fB\-\-regionid\fP the
29033command will attempt to delete the group and all regions that it
29034contains.
29035
29036If a deleted region is the first member of a group of regions the group
29037will also be removed.
29038.
29039.HP
29040.CMD_GROUP
29041.br
29042Combine one or more statistics regions on the specified device into a
29043group.
29044
29045The list of regions to be grouped is specified with \fB\-\-regions\fP
29046and an optional alias may be assigned with \fB\-\-alias\fP. The set of
29047regions is given as a comma-separated list of region identifiers. A
29048continuous range of identifers spanning from \fBR1\fP to \fBR2\fP may
29049be expressed as '\fBR1\fP-\fBR2\fP'.
29050
29051Regions that have a histogram configured can be grouped: in this case
29052the number of histogram bins and their bounds must match exactly.
29053
29054On success the group list and newly created \fBgroup_id\fP are
29055printed to stdout.
29056
29057The group metadata is stored with the first (lowest numbered)
29058\fBregion_id\fP in the group: deleting this region will also delete
29059the group and other group members will be returned to their prior
29060state.
29061.
29062.HP
29063.CMD_HELP
29064.br
29065Outputs a summary of the commands available, optionally including
29066the list of report fields.
29067.
29068.HP
29069.CMD_LIST
29070.br
29071List the statistics regions, areas, or groups registered on the device.
29072If the \fB\-\-allprograms\fP switch is given all regions will be listed
29073regardless of region program ID values.
29074
29075By default only regions and groups are included in list output. If
29076\fB\-v\fP or \fB\-\-verbose\fP is given the report will also include a
29077row of information for each configured group and for each area contained
29078in each region displayed.
29079
29080Regions that contain a single area are by default omitted from the
29081verbose list since their properties are identical to the area that they
29082contain - to view all regions regardless of the number of areas present
29083use \fB\-\-region\fP). To also view the areas contained within regions
29084use \fB\-\-area\fP.
29085
29086If \fB\-\-histogram\fP is given the report will include the bin count
29087and latency boundary values for any configured histograms.
29088.HP
29089.CMD_PRINT
29090.br
29091Print raw statistics counters for the specified region or for all
29092present regions.
29093.
29094.HP
29095.CMD_REPORT
29096.br
29097Start a report for the specified object or for all present objects. If
29098the count argument is specified, the report will repeat at a fixed
29099interval set by the \fB\-\-interval\fP option. The default interval is
29100one second.
29101
29102If the \fB\-\-allprograms\fP switch is given, all regions will be
29103listed, regardless of region program ID values.
29104
29105If the \fB\-\-histogram\fP is given the report will include the histogram
29106values and latency boundaries.
29107
29108If the \fB\-\-relative\fP is used the default histogram field displays
29109bin values as a percentage of the total number of I/Os.
29110
29111Object types (areas, regions and groups) to include in the report are
29112selected using the \fB\-\-area\fP, \fB\-\-region\fP, and \fB\-\-group\fP
29113options.
29114.
29115.HP
29116.CMD_UNGROUP
29117.br
29118Remove an existing group and return all the group's regions to their
29119original state.
29120
29121The group to be removed is specified using \fB\-\-groupid\fP.
29122.
29123.SH REGIONS, AREAS, AND GROUPS
29124.
29125The device-mapper statistics facility allows separate performance
29126counters to be maintained for arbitrary regions of devices. A region may
29127span any range: from a single sector to the whole device. A region may
29128be further sub-divided into a number of distinct areas (one or more),
29129each with its own counter set. In this case a summary value for the
29130entire region is also available for use in reports.
29131
29132In addition, one or more regions on one device can be combined into
29133a statistics group. Groups allow several regions to be aggregated and
29134reported as a single entity; counters for all regions and areas are
29135summed and used to report totals for all group members. Groups also
29136permit the assignment of an optional alias, allowing meaningful names
29137to be associated with sets of regions.
29138
29139The group metadata is stored with the first (lowest numbered)
29140\fBregion_id\fP in the group: deleting this region will also delete
29141the group and other group members will be returned to their prior
29142state.
29143
29144By default new regions span the entire device. The \fB\-\-start\fP and
29145\fB\-\-length\fP options allows a region of any size to be placed at any
29146location on the device.
29147
29148Using offsets it is possible to create regions that map individual
29149objects within a block device (for example: partitions, files in a file
29150system, or stripes or other structures in a RAID volume). Groups allow
29151several non-contiguous regions to be assembled together for reporting
29152and data aggregation.
29153
29154A region may be either divided into the specified number of equal-sized
29155areas, or into areas of the given size by specifying one of
29156\fB\-\-areas\fP or \fB\-\-areasize\fP when creating a region with the
29157\fBcreate\fP command. Depending on the size of the areas and the device
29158region the final area within the region may be smaller than requested.
29159.P
29160.B Region identifiers
29161.P
29162Each region is assigned an identifier when it is created that is used to
29163reference the region in subsequent operations. Region identifiers are
29164unique within a given device (including across different \fBprogram_id\fP
29165values).
29166
29167Depending on the sequence of create and delete operations, gaps may
29168exist in the sequence of \fBregion_id\fP values for a particular device.
29169
29170The \fBregion_id\fP should be treated as an opaque identifier used to
29171reference the region.
29172.
29173.P
29174.B Group identifiers
29175.P
29176Groups are also assigned an integer identifier at creation time;
29177like region identifiers, group identifiers are unique within the
29178containing device.
29179
29180The \fBgroup_id\fP should be treated as an opaque identifier used to
29181reference the group.
29182.
29183.SH REPORT FIELDS
29184.
29185The dmstats report provides several types of field that may be added to
29186the default field set, or used to create custom reports.
29187
29188All performance counters and metrics are calculated per-area.
29189.
29190.SS Derived metrics
29191.
29192A number of metrics fields are included that provide high level
29193performance indicators. These are based on the fields provided by the
29194conventional Linux iostat program and are derived from the basic counter
29195values provided by the kernel for each area.
29196.TP
29197.B reads_merged_per_sec
29198Reads merged per second.
29199.TP
29200.B writes_merged_per_sec
29201Writes merged per second.
29202.TP
29203.B reads_per_sec
29204Reads completed per second.
29205.TP
29206.B writes_per_sec
29207Writes completed per second.
29208.TP
29209.B read_size_per_sec
29210Size of data read per second.
29211.TP
29212.B write_size_per_sec
29213Size of data written per second.
29214.TP
29215.B avg_request_size
29216Average request size.
29217.TP
29218.B queue_size
29219Average queue size.
29220.TP
29221.B await
29222The average wait time for read and write operations.
29223.TP
29224.B r_await
29225The average wait time for read operations.
29226.TP
29227.B w_await
29228The average wait time for write operations.
29229.TP
29230.B throughput
29231The device throughput in operations per second.
29232.TP
29233.B service_time
29234The average service time (in milliseconds) for operations issued
29235to the device.
29236.TP
29237.B util
29238Percentage of CPU time during which I/O requests were issued to the
29239device (bandwidth utilization for the device). Device saturation occurs
29240when this value is close to 100%.
29241.
29242.SS Group, region and area meta fields
29243.
29244Meta fields provide information about the groups, regions, or areas that
29245the statistics values relate to. This includes the region and area
29246identifier, start, length, and counts, as well as the program ID and
29247user data values.
29248.TP
29249.B region_id
29250Region identifier. This is a non-negative integer returned by the kernel
29251when a statistics region is created.
29252.TP
29253.B region_start
29254The region start location. Display units are selected by the
29255\fB\-\-units\fP option.
29256.TP
29257.B region_len
29258The length of the region. Display units are selected by the
29259\fB\-\-units\fP option.
29260.TP
29261.B area_id
29262Area identifier. Area identifiers are assigned by the device-mapper
29263statistics library and uniquely identify each area within a region. Each
29264ID corresponds to a distinct set of performance counters for that area
29265of the statistics region. Area identifiers are always monotonically
29266increasing within a region so that higher ID values correspond to
29267greater sector addresses within the area and no gaps in the sequence of
29268identifiers exist.
29269.TP
29270.B area_start
29271The area start location. Display units are selected by the
29272\fB\-\-units\fP option.
29273.TP
29274.B area_len
29275The length of the area. Display units are selected by the
29276\fB\-\-units\fP option.
29277.TP
29278.B area_count
29279The number of areas in this region.
29280.TP
29281.B program_id
29282The program ID value associated with this region.
29283.TP
29284.B user_data
29285The user data value associated with this region.
29286.TP
29287.B group_id
29288Group identifier. This is a non-negative integer returned by the dmstats
29289\fBgroup\fP command when a statistics group is created.
29290.TP
29291.B interval_ns
29292The estimated interval over which the current counter values have
29293accumulated. The value is reported as an interger expressed in units
29294of nanoseconds.
29295.TP
29296.B interval
29297The estimated interval over which the current counter values have
29298accumulated. The value is reported as a real number in units of
29299seconds.
29300.
29301.SS Basic counters
29302.
29303Basic counters provide access to the raw counter data from the kernel,
29304allowing further processing to be carried out by another program.
29305.P
29306The kernel provides thirteen separate counters for each statistics
29307area. The first eleven of these match the counters provided in
29308/proc/diskstats or /sys/block/*/*/stat. The final pair provide separate
29309counters for read and write time.
29310.TP
29311.B read_count
29312Count of reads completed this interval.
29313.TP
29314.B reads_merged_count
29315Count of reads merged this interval.
29316.TP
29317.B read_sector_count
29318Count of 512 byte sectors read this interval.
29319.TP
29320.B read_time
29321Accumulated duration of all read requests (ns).
29322.TP
29323.B write_count
29324Count of writes completed this interval.
29325.TP
29326.B writes_merged_count
29327Count of writes merged this interval.
29328.TP
29329.B write_sector_count
29330Count of 512 byte sectors written this interval.
29331.TP
29332.B write_nsecs
29333Accumulated duration of all write requests (ns).
29334.TP
29335.B in_progress_count
29336Count of requests currently in progress.
29337.TP
29338.B io_ticks
29339Nanoseconds spent servicing requests.
29340.TP
29341.B queue_ticks
29342This field is incremented at each I/O start, I/O completion, I/O merge,
29343or read of these stats by the number of I/Os in progress multiplied by
29344the number of milliseconds spent doing I/O since the last update of this
29345field. This can provide an easy measure of both I/O completion time and
29346the backlog that may be accumulating.
29347.TP
29348.B read_ticks
29349Nanoseconds spent servicing reads.
29350.TP
29351.B write_ticks
29352Nanoseconds spent servicing writes.
29353.
29354.SS Histogram fields
29355.
29356Histograms measure the frequency distribution of user specified I/O
29357latency intervals. Histogram bin boundaries are specified when a region
29358is created.
29359.P
29360A brief representation of the histogram values and latency intervals can
29361be included in the report using these fields.
29362.TP
29363.B hist_count
29364A list of the histogram counts for the current statistics area in order
29365of ascending latency value. Each value represents the number of I/Os
29366with latency times falling into that bin's time range during the sample
29367period.
29368.TP
29369.B hist_count_bounds
29370A list of the histogram counts for the current statistics area in order
29371of ascending latency value including bin boundaries: each count is
29372prefixed by the lower bound of the corresponding histogram bin.
29373.TP
29374.B hist_count_ranges
29375A list of the histogram counts for the current statistics area in order
29376of ascending latency value including bin boundaries: each count is
29377prefixed by both the lower and upper bounds of the corresponding
29378histogram bin.
29379.TP
29380.B hist_percent
29381A list of the relative histogram values for the current statistics area
29382in order of ascending latency value, expressed as a percentage. Each
29383value represents the proportion of I/Os with latency times falling into
29384that bin's time range during the sample period.
29385.TP
29386.B hist_percent_bounds
29387A list of the relative histogram values for the current statistics area
29388in order of ascending latency value, expressed as a percentage and
29389including bin boundaries. Each value represents the proportion of I/Os
29390with latency times falling into that bin's time range during the sample
29391period and is prefixed with the corresponding bin's lower bound.
29392.TP
29393.B hist_percent_ranges
29394A list of the relative histogram values for the current statistics area
29395in order of ascending latency value, expressed as a percentage and
29396including bin boundaries. Each value represents the proportion of I/Os
29397with latency times falling into that bin's time range during the sample
29398period and is prefixed with the corresponding bin's lower and upper
29399bounds.
29400.TP
29401.B hist_bounds
29402A list of the histogram boundary values for the current statistics area
29403in order of ascending latency value. The values are expressed in whole
29404units of seconds, miliseconds, microseconds or nanoseconds with a suffix
29405indicating the unit.
29406.TP
29407.B hist_ranges
29408A list of the histogram bin ranges for the current statistics area in
29409order of ascending latency value. The values are expressed as
29410"LOWER-UPPER" in whole units of seconds, miliseconds, microseconds or
29411nanoseconds with a suffix indicating the unit.
29412.TP
29413.B hist_bins
29414The number of latency histogram bins configured for the area.
29415.
29416.SH EXAMPLES
29417.
29418Create a whole-device region with one area on vg00/lvol1
29419.br
29420#
29421.B dmstats create vg00/lvol1
29422.br
29423vg00/lvol1: Created new region with 1 area(s) as region ID 0
29424.P
29425Create a 32M region 1G into device d0
29426.br
29427#
29428.B dmstats create \-\-start 1G \-\-length 32M d0
29429.br
29430d0: Created new region with 1 area(s) as region ID 0
29431.P
29432Create a whole-device region with 8 areas on every device
29433.br
29434.br
29435#
29436.B dmstats create \-\-areas 8
29437.br
29438vg00-lvol1: Created new region with 8 area(s) as region ID 0
29439.br
29440vg00-lvol2: Created new region with 8 area(s) as region ID 0
29441.br
29442vg00-lvol3: Created new region with 8 area(s) as region ID 0
29443.br
29444vg01-lvol0: Created new region with 8 area(s) as region ID 2
29445.br
29446vg01-lvol1: Created new region with 8 area(s) as region ID 0
29447.br
29448vg00-lvol2: Created new region with 8 area(s) as region ID 1
29449.P
29450Delete all regions on all devices
29451.br
29452.br
29453#
29454.B dmstats delete \-\-alldevices \-\-allregions
29455.P
29456Create a whole-device region with areas 10GiB in size on vg00/lvol1
29457using dmsetup
29458.br
29459.br
29460#
29461.B dmsetup stats create \-\-areasize 10G vg00/lvol1
29462.br
29463vg00-lvol1: Created new region with 5 area(s) as region ID 1
29464.P
29465Create a 1GiB region with 16 areas at the start of vg00/lvol1
29466.br
29467#
29468.B dmstats create \-\-start 0 \-\-len 1G \-\-areas=16 vg00/lvol1
29469.br
29470vg00-lvol1: Created new region with 16 area(s) as region ID 0
29471.P
29472List the statistics regions registered on vg00/lvol1
29473.br
29474#
29475.B dmstats list vg00/lvol1
29476.br
29477Name RgID RStart RSize #Areas ASize ProgID
29478.br
29479vg00-lvol1 0 0 61.00g 1 61.00g dmstats
29480.br
29481vg00-lvol1 1 61.00g 19.20g 1 19.20g dmstats
29482.br
29483vg00-lvol1 2 80.20g 2.14g 1 2.14g dmstats
29484.P
29485Display five statistics reports for vg00/lvol1 at an interval of one second
29486.br
29487.br
29488#
29489.B dmstats report \-\-interval 1 \-\-count 5 vg00/lvol1
29490.br
29491#
29492.B dmstats report
29493.br
29494Name RgID ArID AStart ASize RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize Util% AWait RdAWa WrAWa
29495.br
29496vg_hex-lv_home 0 0 0 61.00g 0.00 0.00 0.00 218.00 0 1.04m 4.50k 2.97 81.70 13.62 0.00 13.62
29497.br
29498vg_hex-lv_home 1 0 61.00g 19.20g 0.00 0.00 0.00 5.00 0 548.00k 109.50k 0.14 11.00 27.40 0.00 27.40
29499.br
29500vg_hex-lv_home 2 0 80.20g 2.14g 0.00 0.00 0.00 14.00 0 1.15m 84.00k 0.39 18.70 27.71 0.00 27.71
29501.P
29502Create one region for reach target contained in device vg00/lvol1
29503.br
29504.br
29505#
29506.B dmstats create \-\-segments vg00/lvol1
29507.br
29508vg00-lvol1: Created new region with 1 area(s) as region ID 0
29509.br
29510vg00-lvol1: Created new region with 1 area(s) as region ID 1
29511.br
29512vg00-lvol1: Created new region with 1 area(s) as region ID 2
29513.P
29514Create regions mapping each file in the directory images/ and place
29515them into separate groups, each named after the corresponding file
29516.br
29517#
29518.B dmstats create --filemap images/*
29519.br
29520images/vm1.qcow2: Created new group with 87 region(s) as group ID 0.
29521.br
29522images/vm1-1.qcow2: Created new group with 8 region(s) as group ID 87.
29523.br
29524images/vm2.qcow2: Created new group with 11 region(s) as group ID 95.
29525.br
29526images/vm2-1.qcow2: Created new group with 1454 region(s) as group ID 106.
29527.br
29528images/vm3.img: Created new group with 2 region(s) as group ID 1560.
29529.P
29530Print raw counters for region 4 on device d0
29531.br
29532#
29533.B dmstats print \-\-regionid 4 d0
29534.br
295352097152+65536 0 0 0 0 29 0 264 701 0 41 701 0 41
29536.
29537.SH AUTHORS
29538.
29539Bryn M. Reeves <bmr@redhat.com>
29540.
29541.SH SEE ALSO
29542.
29543.BR dmsetup (8)
29544
29545LVM2 resource page: https://www.sourceware.org/lvm2/
29546.br
29547Device-mapper resource page: http://sources.redhat.com/dm/
29548.br
29549
29550Device-mapper statistics kernel documentation
29551.br
29552.I Documentation/device-mapper/statistics.txt
29553\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmdump.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006641\013062740170\0020013\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMDUMP 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
29554.SH NAME
29555lvmdump \(em create lvm2 information dumps for diagnostic purposes
29556.SH SYNOPSIS
29557.B lvmdump
29558.RB [ \-a ]
29559.RB [ \-c ]
29560.RB [ \-d
29561.IR directory ]
29562.RB [ \-h ]
29563.RB [ \-l ]
29564.RB [ \-m ]
29565.RB [ \-p ]
29566.RB [ \-s ]
29567.RB [ \-u ]
29568.SH DESCRIPTION
29569lvmdump is a tool to dump various information concerning LVM2.
29570By default, it creates a tarball suitable for submission along
29571with a problem report.
29572.PP
29573The content of the tarball is as follows:
29574.br
29575- dmsetup info
29576.br
29577- table of currently running processes
29578.br
29579- recent entries from /var/log/messages (containing system messages)
29580.br
29581- complete lvm configuration and cache (content of /etc/lvm)
29582.br
29583- list of device nodes present under /dev
29584.br
29585- list of files present /sys/block
29586.br
29587- list of files present /sys/devices/virtual/block
29588.br
29589- if enabled with \-m, metadata dump will be also included
29590.br
29591- if enabled with \-a, debug output of vgscan, pvscan and list of all available volume groups, physical volumes and logical volumes will be included
29592.br
29593- if enabled with \-c, cluster status info
29594.br
29595- if enabled with \-l, lvmetad state if running
29596.br
29597- if enabled with \-p, lvmpolld state if running
29598.br
29599- if enabled with \-s, system info and context
29600.br
29601- if enabled with \-u, udev info and context
29602.SH OPTIONS
29603.TP
29604.B \-a
29605Advanced collection.
29606\fBWARNING\fR: if lvm is already hung, then this script may hang as well
29607if \fB\-a\fR is used.
29608.TP
29609.B \-c
29610If clvmd is running, gather cluster data as well.
29611.TP
29612.B \-d \fIdirectory
29613Dump into a directory instead of tarball
29614By default, lvmdump will produce a single compressed tarball containing
29615all the information. Using this option, it can be instructed to only
29616produce the raw dump tree, rooted in \fIdirectory\fP.
29617.TP
29618.B \-h
29619Print help message
29620.TP
29621.B \-l
29622Include \fBlvmetad\fP(8) daemon dump if it is running. The dump contains
29623cached information that is currently stored in lvmetad: VG metadata,
29624PV metadata and various mappings in between these metadata for quick
29625access.
29626.TP
29627.B \-m
29628Gather LVM metadata from the PVs
29629This option generates a 1:1 dump of the metadata area from all PVs visible
29630to the system, which can cause the dump to increase in size considerably.
29631However, the metadata dump may represent a valuable diagnostic resource.
29632.TP
29633.B \-p
29634Include \fBlvmpolld\fP(8) daemon dump if it is running. The dump contains
29635all in-progress operation currently monitored by the daemon and partial
29636history for all yet uncollected results of polling operations already finished
29637including reason.
29638.TP
29639.B \-s
29640Gather system info and context. Currently, this encompasses info gathered
29641by calling lsblk command and various systemd info and context: overall state
29642of systemd units present in the system, more detailed status of units
29643controlling LVM functionality and the content of systemd journal for
29644current boot.
29645.TP
29646.B \-u
29647Gather udev info and context: /etc/udev/udev.conf file, udev daemon version
29648(output of 'udevadm info \-\-version' command), udev rules currently used in the system
29649(content of /lib/udev/rules.d and /etc/udev/rules.d directory),
29650list of files in /lib/udev directory and dump of current udev
29651database content (the output of 'udevadm info \-\-export\-db' command).
29652.SH ENVIRONMENT VARIABLES
29653.TP
29654\fBLVM_BINARY\fP
29655The LVM2 binary to use.
29656Defaults to "lvm".
29657Sometimes you might need to set this to "/sbin/lvm.static", for example.
29658.TP
29659\fBDMSETUP_BINARY\fP
29660The dmsetup binary to use.
29661Defaults to "dmsetup".
29662.PP
29663.SH SEE ALSO
29664.BR lvm (8)
29665\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgchange.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000033513\013062740170\0020107\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
29666.SH NAME
29667vgchange \(em change attributes of a volume group
29668.SH SYNOPSIS
29669.B vgchange
29670.RB [ \-\-addtag
29671.IR Tag ]
29672.RB [ \-\-alloc
29673.IR AllocationPolicy ]
29674.RB [ \-A | \-\-autobackup
29675.RI { y | n }]
29676.RB [ \-a | \-\-activate
29677.RI [ a | e | s | l ]
29678.RI { y | n }]
29679.RB [ \-\-activationmode
29680.IB { complete | degraded | partial } ]
29681.RB [ \-K | \-\-ignoreactivationskip ]
29682.RB [ \-\-monitor
29683.RI { y | n }]
29684.RB [ \-\-poll
29685.RI { y | n }]
29686.RB [ \-c | \-\-clustered
29687.RI { y | n }]
29688.RB [ \-u | \-\-uuid ]
29689.RB [ \-\-commandprofile
29690.IR ProfileName ]
29691.RB [ \-d | \-\-debug ]
29692.RB [ \-\-deltag
29693.IR Tag ]
29694.RB [ \-\-detachprofile ]
29695.RB [ \-h | \-\-help ]
29696.RB [ \-\-ignorelockingfailure ]
29697.RB [ \-\-ignoremonitoring ]
29698.RB [ \-\-ignoreskippedcluster ]
29699.RB [ \-\-sysinit ]
29700.RB [ \-\-noudevsync ]
29701.RB [ \-\-lock\-start ]
29702.RB [ \-\-lock\-stop ]
29703.RB [ \-\-lock\-type
29704.IR LockType ]
29705.RB [ \-l | \-\-logicalvolume
29706.IR MaxLogicalVolumes ]
29707.RB [ \-p | \-\-maxphysicalvolumes
29708.IR MaxPhysicalVolumes ]
29709.RB [ \-\-metadataprofile
29710.IR ProfileName ]
29711.RB [ \-\- [ vg ] metadatacopies
29712.IR NumberOfCopies | unmanaged | all ]
29713.RB [ \-P | \-\-partial ]
29714.RB [ \-s | \-\-physicalextentsize
29715.IR PhysicalExtentSize [ bBsSkKmMgGtTpPeE ]]
29716.RB [ \-\-reportformat
29717.RB { basic | json }]
29718.RB [ \-S | \-\-select
29719.IR Selection ]
29720.RB [ \-\-systemid
29721.IR SystemID ]
29722.RB [ \-\-refresh ]
29723.RB [ \-t | \-\-test ]
29724.RB [ \-v | \-\-verbose ]
29725.RB [ \-\-version ]
29726.RB [ \-x | \-\-resizeable
29727.RI { y | n }]
29728.RI [ VolumeGroupName ...]
29729.SH DESCRIPTION
29730vgchange allows you to change the attributes of one or more
29731volume groups. Its main purpose is to activate and deactivate
29732.IR VolumeGroupName ,
29733or all volume groups if none is specified. Only active volume groups
29734are subject to changes and allow access to their logical volumes.
29735[Not yet implemented: During volume group activation, if
29736.B vgchange
29737recognizes snapshot logical volumes which were dropped because they ran
29738out of space, it displays a message informing the administrator that such
29739snapshots should be removed (see
29740.BR lvremove (8)).
29741]
29742.SH OPTIONS
29743See \fBlvm\fP(8) for common options.
29744.TP
29745.BR \-A ", " \-\-autobackup " {" \fIy | \fIn }
29746Controls automatic backup of metadata after the change. See
29747.BR vgcfgbackup (8).
29748Default is yes.
29749.TP
29750.BR \-a ", " \-\-activate " [" \fIa | \fIe | \fIs | \fIl ]{ \fIy | \fIn }
29751Controls the availability of the logical volumes in the volume
29752group for input/output.
29753In other words, makes the logical volumes known/unknown to the kernel.
29754If autoactivation option is used (\-aay), each logical volume in
29755the volume group is activated only if it matches an item in the
29756activation/auto_activation_volume_list set in lvm.conf. If this
29757list is not set, then all volumes are considered for activation.
29758The \-aay option should be also used during system boot so it's
29759possible to select which volumes to activate using the
29760activation/auto_activation_volume_list settting.
29761.IP
29762Activation of a logical volume creates a symbolic link
29763/dev/VolumeGroupName/LogicalVolumeName pointing to the device node.
29764This link is removed on deactivation.
29765All software and scripts should access the device through
29766this symbolic link and present this as the name of the device.
29767The location and name of the underlying device node may depend on
29768the distribution and configuration (e.g. udev) and might change
29769from release to release.
29770.IP
29771In a clustered VG, clvmd is used for activation, and the
29772following options are possible:
29773
29774With \-aey, clvmd activates the LV in exclusive mode
29775(with an exclusive lock), allowing a single node to activate the LV.
29776
29777With \-asy, clvmd activates the LV in shared mode
29778(with a shared lock), allowing multiple nodes to activate the LV concurrently.
29779If the LV type prohibits shared access, such as an LV with a snapshot,
29780the 's' option is ignored and an exclusive lock is used.
29781
29782With \-ay (no mode specified), clvmd activates the LV in shared mode
29783if the LV type allows concurrent access, such as a linear LV.
29784Otherwise, clvmd activates the LV in exclusive mode.
29785
29786With \-aey, \-asy, and \-ay, clvmd attempts to activate the LV
29787on all nodes. If exclusive mode is used, then only one of the
29788nodes will be successful.
29789
29790With \-an, clvmd attempts to deactivate the LV on all nodes.
29791
29792With \-aly, clvmd activates the LV only on the local node, and \-aln
29793deactivates only on the local node. If the LV type allows concurrent
29794access, then shared mode is used, otherwise exclusive.
29795
29796LVs with snapshots are always activated exclusively because they can only
29797be used on one node at once.
29798
29799For local VGs, \-ay, \-aey, and \-asy are all equivalent.
29800.IP
29801In a shared VG, lvmlockd is used for locking if LVM is compiled with lockd
29802support, and the following options are possible:
29803
29804With \-aey, the command activates the LV in exclusive mode, allowing a
29805single host to activate the LV (the host running the command). Before
29806activating the LV, the command uses lvmlockd to acquire an exclusive lock
29807on the LV. If the lock cannot be acquired, the LV is not activated and an
29808error is reported. This would happen if the LV is active on another host.
29809
29810With \-asy, the command activates the LV in shared mode, allowing multiple
29811hosts to activate the LV concurrently. Before activating the LV, the
29812command uses lvmlockd to acquire a shared lock on the LV. If the lock
29813cannot be acquired, the LV is not activated and an error is reported.
29814This would happen if the LV is active exclusively on another host. If the
29815LV type prohibits shared access, such as a snapshot, the command will
29816report an error and fail.
29817
29818With \-an, the command deactivates the LV on the host running the command.
29819After deactivating the LV, the command uses lvmlockd to release the
29820current lock on the LV.
29821
29822With lvmlockd, an unspecified mode is always exclusive, \-ay defaults to
29823\-aey.
29824
29825.TP
29826.BR \-\-activationmode " {" \fIcomplete | \fIdegraded | \fIpartial }
29827The activation mode determines whether logical volumes are allowed to
29828activate when there are physical volumes missing (e.g. due to a device
29829failure). \fIcomplete\fP is the most restrictive; allowing only those
29830logical volumes to be activated that are not affected by the missing
29831PVs. \fIdegraded\fP allows RAID logical volumes to be activated even if
29832they have PVs missing. (Note that the "mirror" segment type is not
29833considered a RAID logical volume. The "raid1" segment type should
29834be used instead.) Finally, \fIpartial\fP allows any logical volume to
29835be activated even if portions are missing due to a missing or failed
29836PV. This last option should only be used when performing recovery or
29837repair operations. \fIdegraded\fP is the default mode. To change it, modify
29838.B activation_mode
29839in
29840.BR lvm.conf (5).
29841.TP
29842.BR \-K ", " \-\-ignoreactivationskip
29843Ignore the flag to skip Logical Volumes during activation.
29844.TP
29845.BR \-c ", " \-\-clustered " {" \fIy | \fIn }
29846If clustered locking is enabled, this indicates whether this
29847Volume Group is shared with other nodes in the cluster or whether
29848it contains only local disks that are not visible on the other nodes.
29849If the cluster infrastructure is unavailable on a particular node at a
29850particular time, you may still be able to use Volume Groups that
29851are not marked as clustered.
29852.TP
29853.BR \-\-detachprofile
29854Detach any metadata configuration profiles attached to given
29855Volume Groups. See \fBlvm.conf\fP(5) for more information
29856about \fBmetadata profiles\fP.
29857.TP
29858.BR \-u ", " \-\-uuid
29859Generate new random UUID for specified Volume Groups.
29860.TP
29861.BR \-\-monitor " {" \fIy | \fIn }
29862Start or stop monitoring a mirrored or snapshot logical volume with
29863dmeventd, if it is installed.
29864If a device used by a monitored mirror reports an I/O error,
29865the failure is handled according to
29866.B mirror_image_fault_policy
29867and
29868.B mirror_log_fault_policy
29869set in
29870.BR lvm.conf (5).
29871.TP
29872.BR \-\-poll " {" \fIy | \fIn }
29873Without polling a logical volume's backgrounded transformation process
29874will never complete. If there is an incomplete pvmove or lvconvert (for
29875example, on rebooting after a crash), use \fB\-\-poll y\fP to restart the
29876process from its last checkpoint. However, it may not be appropriate to
29877immediately poll a logical volume when it is activated, use
29878\fB\-\-poll n\fP to defer and then \fB\-\-poll y\fP to restart the process.
29879.TP
29880.BR \-\-sysinit
29881Indicates that vgchange(8) is being invoked from early system initialisation
29882scripts (e.g. rc.sysinit or an initrd), before writeable filesystems are
29883available. As such, some functionality needs to be disabled and this option
29884acts as a shortcut which selects an appropriate set of options. Currently
29885this is equivalent to using
29886.BR \-\-ignorelockingfailure ,
29887.BR \-\-ignoremonitoring ,
29888.B \-\-poll n
29889and setting \fBLVM_SUPPRESS_LOCKING_FAILURE_MESSAGES\fP
29890environment variable.
29891
29892If \fB\-\-sysinit\fP is used in conjunction with lvmetad(8) enabled and running,
29893autoactivation is preferred over manual activation via direct vgchange call.
29894Logical volumes are autoactivated according to auto_activation_volume_list
29895set in lvm.conf(5).
29896.TP
29897.BR \-\-noudevsync
29898Disable udev synchronisation. The
29899process will not wait for notification from udev.
29900It will continue irrespective of any possible udev processing
29901in the background. You should only use this if udev is not running
29902or has rules that ignore the devices LVM2 creates.
29903.TP
29904.BR \-\-ignoremonitoring
29905Make no attempt to interact with dmeventd unless
29906.BR \-\-monitor
29907is specified.
29908Do not use this if dmeventd is already monitoring a device.
29909.TP
29910.BR \-\-lock\-start
29911Start the lockspace of a shared VG in lvmlockd. lvmlockd locks becomes
29912available for the VG, allowing LVM to use the VG. See
29913.BR lvmlockd (8).
29914.TP
29915.BR \-\-lock\-stop
29916Stop the lockspace of a shared VG in lvmlockd. lvmlockd locks become
29917unavailable for the VG, preventing LVM from using the VG. See
29918.BR lvmlockd (8).
29919.TP
29920.BR \-\-lock\-type " " \fILockType
29921Change the VG lock type to or from a shared lock type used with lvmlockd. See
29922.BR lvmlockd (8).
29923.TP
29924.BR \-l ", " \-\-logicalvolume " " \fIMaxLogicalVolumes
29925Changes the maximum logical volume number of an existing inactive
29926volume group.
29927.TP
29928.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes
29929Changes the maximum number of physical volumes that can belong
29930to this volume group.
29931For volume groups with metadata in lvm1 format, the limit is 255.
29932If the metadata uses lvm2 format, the value 0 removes this restriction:
29933there is then no limit. If you have a large number of physical volumes in
29934a volume group with metadata in lvm2 format, for tool performance reasons,
29935you should consider some use of \fB\-\-pvmetadatacopies 0\fP as described in
29936\fBpvcreate(8)\fP, and/or use \fB\-\-vgmetadatacopies\fP.
29937.TP
29938.BR \-\-metadataprofile " " \fIProfileName
29939Uses and attaches ProfileName configuration profile to the volume group
29940metadata. Whenever the volume group is processed next time, the profile
29941is automatically applied. The profile is inherited by all logical volumes
29942in the volume group unless the logical volume itself has its own profile
29943attached. See \fBlvm.conf\fP(5) for more information about \fBmetadata profiles\fP.
29944.TP
29945.BR \-\- [ vg ] metadatacopies " " \fINumberOfCopies | \fIunmanaged | \fIall
29946Sets the desired number of metadata copies in the volume group. If set to
29947a non-zero value, LVM will automatically manage the 'metadataignore'
29948flags on the physical volumes (see \fBpvchange\fP or \fBpvcreate \-\-metadataignore\fP) in order
29949to achieve \fINumberOfCopies\fP copies of metadata. If set to \fIunmanaged\fP,
29950LVM will not automatically manage the 'metadataignore' flags. If set to
29951\fIall\fP, LVM will first clear all of the 'metadataignore' flags on all
29952metadata areas in the volume group, then set the value to \fIunmanaged\fP.
29953The \fBvgmetadatacopies\fP option is useful for volume groups containing
29954large numbers of physical volumes with metadata as it may be used to
29955minimize metadata read and write overhead.
29956.TP
29957.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize [ \fIBbBsSkKmMgGtTpPeE ]
29958Changes the physical extent size on physical volumes of this volume group.
29959A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
29960is the default if no suffix is present. For LVM2 format, the value must be a
29961power of 2 of at least 1 sector (where the sector size is the largest sector
29962size of the PVs currently used in the VG) or, if not a power of 2, at least
29963128KiB. For the older LVM1 format, it must be a power of 2 of at least 8KiB.
29964The default is 4 MiB.
29965
29966Before increasing the physical extent size, you might need to use lvresize,
29967pvresize and/or pvmove so that everything fits. For example, every
29968contiguous range of extents used in a logical volume must start and
29969end on an extent boundary.
29970
29971If the volume group metadata uses lvm1 format, extents can vary in size from
299728KiB to 16GiB and there is a limit of 65534 extents in each logical volume.
29973The default of 4 MiB leads to a maximum logical volume size of around 256GiB.
29974
29975If the volume group metadata uses lvm2 format those restrictions do not apply,
29976but having a large number of extents will slow down the tools but have no
29977impact on I/O performance to the logical volume. The smallest PE is 1KiB.
29978
29979The 2.4 kernel has a limitation of 2TiB per block device.
29980.TP
29981.BR \-\-systemid " " \fISystemID
29982Changes the system ID of the VG. Using this option requires caution
29983because the VG may become foreign to the host running the command,
29984leaving the host unable to access it. See
29985.BR lvmsystemid (7).
29986.TP
29987.BR \-\-refresh
29988If any logical volume in the volume group is active, reload its metadata.
29989This is not necessary in normal operation, but may be useful
29990if something has gone wrong or if you're doing clustering
29991manually without a clustered lock manager.
29992.TP
29993.BR \-x ", " \-\-resizeable " {" \fIy | \fIn }
29994Enables or disables the extension/reduction of this volume group
29995with/by physical volumes.
29996.SH Examples
29997To activate all known volume groups in the system:
29998.sp
29999.B vgchange \-a y
30000
30001To change the maximum number of logical volumes of inactive volume group
30002vg00 to 128.
30003.sp
30004.B vgchange \-l 128 /dev/vg00
30005
30006
30007.SH SEE ALSO
30008.BR lvchange (8),
30009.BR lvm (8),
30010.BR vgcreate (8)
30011\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmlockctl.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005176\013062740170\0020503\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMLOCKCTL" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
30012
30013.SH NAME
30014lvmlockctl \(em Control for lvmlockd
30015
30016.SH DESCRIPTION
30017This command interacts with
30018.BR lvmlockd (8).
30019
30020.SH OPTIONS
30021
30022lvmlockctl [options]
30023
30024.B \-\-help | \-h
30025 Show this help information.
30026
30027.B \-\-quit | \-q
30028 Tell lvmlockd to quit.
30029
30030.B \-\-info | \-i
30031 Print lock state information from lvmlockd.
30032
30033.B \-\-dump | \-d
30034 Print log buffer from lvmlockd.
30035
30036.B \-\-wait | \-w 0|1
30037 Wait option for other commands.
30038
30039.B \-\-force | \-f 0|1
30040 Force option for other commands.
30041
30042.B \-\-kill | \-k
30043.I vgname
30044 Kill access to the VG when sanlock cannot renew lease.
30045
30046.B \-\-drop | \-r
30047.I vgname
30048 Clear locks for the VG when it is unused after kill (-k).
30049
30050.B \-\-gl\-enable | \-E
30051.I vgname
30052 Tell lvmlockd to enable the global lock in a sanlock VG.
30053
30054.B \-\-gl\-disable | \-D
30055.I vgname
30056 Tell lvmlockd to disable the global lock in a sanlock VG.
30057
30058.B \-\-stop\-lockspaces | \-S
30059 Stop all lockspaces.
30060
30061
30062.SH USAGE
30063
30064.SS info
30065
30066This collects and displays lock state from lvmlockd. The display is
30067primitive, incomplete and will change in future version. To print the raw
30068lock state from lvmlockd, combine this option with --dump|-d.
30069
30070.SS dump
30071
30072This collects the circular log buffer of debug statements from lvmlockd
30073and prints it.
30074
30075.SS kill
30076
30077This is run by sanlock when it loses access to the storage holding leases
30078for a VG. It currently emits a syslog message stating that the VG must
30079be immediately deactivated. In the future it may automatically attempt to
30080forcibly deactivate the VG. For more, see
30081.BR lvmlockd (8).
30082
30083.SS drop
30084
30085This should only be run after a VG has been successfully deactivated
30086following an lvmlockctl \-\-kill command. It clears the stale lockspace
30087from lvmlockd. In the future, this may become automatic along with an
30088automatic handling of \-\-kill. For more, see
30089.BR lvmlockd (8).
30090
30091.SS gl\-enable
30092
30093This enables the global lock in a sanlock VG. This is necessary if the VG
30094that previously held the global lock is removed. For more, see
30095.BR lvmlockd (8).
30096
30097.SS gl\-disable
30098
30099This disables the global lock in a sanlock VG. This is necessary if the
30100global lock has mistakenly been enabled in more than one VG. The global
30101lock should be disabled in all but one sanlock VG. For more, see
30102.BR lvmlockd (8).
30103
30104.SS stop\-lockspaces
30105
30106This tells lvmlockd to stop all lockspaces. It can be useful to stop
30107lockspaces for VGs that the vgchange \-\-lock\-stop comand can no longer
30108see, or to stop the dlm global lockspace which is not directly stopped by
30109the vgchange command. The wait and force options can be used with this
30110command.
30111
30112
30113\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvmove.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015302\013062740170\0017635\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
30114.SH NAME
30115pvmove \(em move physical extents
30116.SH SYNOPSIS
30117.B pvmove
30118.RB [ \-\-abort ]
30119.RB [ \-\-alloc
30120.IR AllocationPolicy ]
30121.RB [ \-\-atomic ]
30122.RB [ \-b | \-\-background ]
30123.RB [ \-\-commandprofile
30124.IR ProfileName ]
30125.RB [ \-d | \-\-debug ]
30126.RB [ \-h | \-\-help ]
30127.RB [ \-i | \-\-interval
30128.IR Seconds ]
30129.RB [ \-\-noudevsync ]
30130.RB [ \-\-reportformat
30131.RB { basic | json }]
30132.RB [ \-v | \-\-verbose ]
30133.RB [ \-n | \-\-name
30134.IR LogicalVolume ]
30135.RI [ SourcePhysicalVolume [ :PE [ \-PE ]...]
30136.RI [ DestinationPhysicalVolume [ :PE [ \-PE ]...]...]]
30137.SH DESCRIPTION
30138pvmove allows you to move the allocated physical extents (PEs) on
30139.I SourcePhysicalVolume
30140to one or more other physical volumes (PVs).
30141You can optionally specify a source
30142.I LogicalVolume
30143in which case only extents used by that LV will be moved to
30144free (or specified) extents on
30145.IR DestinationPhysicalVolume (s).
30146If no
30147.I DestinationPhysicalVolume
30148is specified, the normal allocation rules for the Volume Group are used.
30149
30150If pvmove gets interrupted for any reason (e.g. the machine crashes)
30151then run pvmove again without any PhysicalVolume arguments to
30152restart any moves that were in progress from the last checkpoint.
30153Alternatively use \fBpvmove \-\-abort\fP at any time to abort. The
30154resulting location of logical volumes after an abort is issued depends
30155on whether the
30156.B \-\-atomic
30157option was used when starting the pvmove process.
30158
30159You can run more than one pvmove at once provided they are moving data
30160off different SourcePhysicalVolumes, but additional pvmoves will ignore
30161any Logical Volumes already in the process of being changed, so some
30162data might not get moved.
30163
30164\fBpvmove\fP works as follows:
30165
301661. A temporary 'pvmove' Logical Volume is created to store
30167details of all the data movements required.
30168
301692. Every Logical Volume in the Volume Group is searched
30170for contiguous data that need moving
30171according to the command line arguments.
30172For each piece of data found, a new segment is added to the end of the
30173pvmove LV.
30174This segment takes the form of a temporary mirror to copy the data
30175from the original location to a newly-allocated location.
30176The original LV is updated to use the new temporary mirror segment
30177in the pvmove LV instead of accessing the data directly.
30178
301793. The Volume Group metadata is updated on disk.
30180
301814. The first segment of the pvmove Logical Volume is activated and starts
30182to mirror the first part of the data. Only one segment is mirrored at once
30183as this is usually more efficient.
30184
301855. A daemon repeatedly checks progress at the specified time interval.
30186When it detects that the first temporary mirror is in-sync,
30187it breaks that mirror so that only the new location for that data gets used
30188and writes a checkpoint into the Volume Group metadata on disk.
30189Then it activates the mirror for the next segment of the pvmove LV.
30190
301916. When there are no more segments left to be mirrored,
30192the temporary Logical Volume is removed and the Volume Group metadata
30193is updated so that the Logical Volumes reflect the new data locations.
30194
30195Note that this new process cannot support the original LVM1
30196type of on-disk metadata. Metadata can be converted using \fBvgconvert\fP(8).
30197
30198If the
30199.B \-\-atomic
30200option is used, a slightly different approach is used for the move. Again,
30201a temporary 'pvmove' logical volume is created to store the details of all
30202the data movements required. This temporary LV contains all the segments of
30203the various LVs that need to be moved. However this time, an identical
30204logical volume is allocated that contains the same number of segments and
30205a mirror is created to copy the contents from the first temporary LV to the
30206second. When a complete copy is accomplished, the temporary logical volumes
30207are removed, leaving behind the segments on the destination physical volume.
30208If an abort is issued during the move, all logical volumes being moved will
30209remain on the source physical volume.
30210
30211.SH OPTIONS
30212See \fBlvm\fP(8) for common options.
30213.TP
30214.B \-\-abort
30215Abort any moves in progress. If the
30216.B \-\-atomic
30217option was used to start the pvmove, all logical volumes will remain on
30218the source physical volume. Otherwise, those segments that have completed
30219the move will stay on the destination physical volume, while those that
30220have not will remain on the source physical volume.
30221.TP
30222.B \-\-atomic
30223Make the entire operation atomic. That is, ensure that all affected logical
30224volumes are moved to the destination physical volume together; unless the move
30225has been aborted. If the move has been aborted, all logical volumes will
30226remain on the source physical volume.
30227.TP
30228.B \-\-noudevsync
30229Disable udev synchronisation. The
30230process will not wait for notification from udev.
30231It will continue irrespective of any possible udev processing
30232in the background. You should only use this if udev is not running
30233or has rules that ignore the devices LVM2 creates.
30234.TP
30235.BR \-b ", " \-\-background
30236Run the daemon in the background.
30237.TP
30238.BR \-i ", " \-\-interval " " \fISeconds
30239Report progress as a percentage at regular intervals.
30240.TP
30241.BR \-n ", " \-\-name " " \fILogicalVolume
30242Move only the extents belonging to
30243.I LogicalVolume
30244from
30245.I SourcePhysicalVolume
30246instead of all allocated extents to the destination physical volume(s).
30247
30248.SH Examples
30249To move all Physical Extents that are used by simple Logical Volumes on
30250/dev/sdb1 to free Physical Extents elsewhere in the Volume Group use:
30251.sp
30252.B pvmove /dev/sdb1
30253.P
30254Additionally, a specific destination device /dev/sdc1
30255can be specified like this:
30256.sp
30257.B pvmove /dev/sdb1 /dev/sdc1
30258.P
30259To perform the action only on extents belonging to the single Logical Volume
30260lvol1 do this:
30261.sp
30262.B pvmove \-n lvol1 /dev/sdb1 /dev/sdc1
30263.P
30264Rather than moving the contents of the entire device, it is possible to
30265move a range of Physical Extents - for example numbers 1000 to 1999
30266inclusive on /dev/sdb1 - like this:
30267.sp
30268.B pvmove /dev/sdb1:1000\-1999
30269.P
30270A range can also be specified as start+length, so
30271.sp
30272.B pvmove /dev/sdb1:1000+1000
30273.P
30274also refers to 1000 Physical Extents starting from Physical Extent number 1000.
30275(Counting starts from 0, so this refers to the 1001st to the 2000th inclusive.)
30276.P
30277To move a range of Physical Extents to a specific location (which must have
30278sufficient free extents) use the form:
30279.sp
30280.B pvmove /dev/sdb1:1000\-1999 /dev/sdc1
30281.sp
30282or
30283.sp
30284.B pvmove /dev/sdb1:1000\-1999 /dev/sdc1:0\-999
30285.P
30286If the source and destination are on the same disk, the
30287.B anywhere
30288allocation policy would be needed, like this:
30289.sp
30290.B pvmove \-\-alloc anywhere /dev/sdb1:1000\-1999 /dev/sdb1:0\-999
30291.P
30292The part of a specific Logical Volume present within in a range of Physical
30293Extents can also be picked out and moved, like this:
30294.sp
30295.B pvmove \-n lvol1 /dev/sdb1:1000\-1999 /dev/sdc1
30296.SH SEE ALSO
30297.BR lvm (8),
30298.BR vgconvert (8)
30299.BR pvs (8)
30300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/cmirrord.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002406\013062740170\0020143\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH CMIRRORD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
30301.SH NAME
30302cmirrord \(em cluster mirror log daemon
30303
30304.SH SYNOPSIS
30305\fBcmirrord\fR [\fB\-f\fR] [\fB\-h\fR]
30306
30307.SH DESCRIPTION
30308\fBcmirrord\fP is the daemon that tracks mirror log information in a cluster.
30309It is specific to device-mapper based mirrors (and by extension, LVM
30310cluster mirrors). Cluster mirrors are not possible without this daemon
30311running.
30312
30313This daemon relies on the cluster infrastructure provided by the
30314Cluster MANager (CMAN), which must be set up and running in order for
30315cmirrord to function. (The cluster infrastructure is also required for
30316\fBclvmd\fP(8).)
30317
30318Output is logged via \fBsyslog\fP(3). The \fBSIGUSR1 signal\fP(7) can be
30319issued to \fBcmirrord\fP to gather current status information for debugging
30320purposes.
30321
30322Once started, \fBcmirrord\fP will run until it is shutdown via \fBSIGINT\fP
30323signal. If there are still active cluster mirrors, however, the signal will be
30324ignored. Active cluster mirrors should be shutdown before stopping the cluster
30325mirror log daemon.
30326
30327.SH OPTIONS
30328.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4
30329Do not fork and log to the terminal.
30330.IP "\fB\-h\fR, \fB\-\-help\fR" 4
30331Print usage.
30332
30333.SH SEE ALSO
30334.BR syslog (3),
30335.BR cluster.conf (5),
30336.BR signal (7),
30337.BR clvmd (8),
30338.BR lvm (8)
30339\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmthin.7.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000113176\013062740170\0020011\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMTHIN" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
30340
30341.SH NAME
30342lvmthin \(em LVM thin provisioning
30343
30344.SH DESCRIPTION
30345
30346Blocks in a standard logical volume are allocated when the LV is created,
30347but blocks in a thin provisioned logical volume are allocated as they are
30348written. Because of this, a thin provisioned LV is given a virtual size,
30349and can then be much larger than physically available storage. The amount
30350of physical storage provided for thin provisioned LVs can be increased
30351later as the need arises.
30352
30353Blocks in a standard LV are allocated (during creation) from the VG, but
30354blocks in a thin LV are allocated (during use) from a special "thin pool
30355LV". The thin pool LV contains blocks of physical storage, and blocks in
30356thin LVs just reference blocks in the thin pool LV.
30357
30358A thin pool LV must be created before thin LVs can be created within it.
30359A thin pool LV is created by combining two standard LVs: a large data LV
30360that will hold blocks for thin LVs, and a metadata LV that will hold
30361metadata. The metadata tracks which data blocks belong to each thin LV.
30362
30363Snapshots of thin LVs are efficient because the data blocks common to a
30364thin LV and any of its snapshots are shared. Snapshots may be taken of
30365thin LVs or of other thin snapshots. Blocks common to recursive snapshots
30366are also shared in the thin pool. There is no limit to or degradation
30367from sequences of snapshots.
30368
30369As thin LVs or snapshot LVs are written to, they consume data blocks in
30370the thin pool. As free data blocks in the pool decrease, more free blocks
30371may need to be supplied. This is done by extending the thin pool data LV
30372with additional physical space from the VG. Removing thin LVs or
30373snapshots from the thin pool can also free blocks in the thin pool.
30374However, removing LVs is not always an effective way of freeing space in a
30375thin pool because the amount is limited to the number of blocks not shared
30376with other LVs in the pool.
30377
30378Incremental block allocation from thin pools can cause thin LVs to become
30379fragmented. Standard LVs generally avoid this problem by allocating all
30380the blocks at once during creation.
30381
30382
30383.SH Thin Terms
30384
30385.TP
30386ThinDataLV
30387.br
30388thin data LV
30389.br
30390large LV created in a VG
30391.br
30392used by thin pool to store ThinLV blocks
30393
30394.TP
30395ThinMetaLV
30396.br
30397thin metadata LV
30398.br
30399small LV created in a VG
30400.br
30401used by thin pool to track data block usage
30402
30403.TP
30404ThinPoolLV
30405.br
30406thin pool LV
30407.br
30408combination of ThinDataLV and ThinMetaLV
30409.br
30410contains ThinLVs and SnapLVs
30411
30412.TP
30413ThinLV
30414.br
30415thin LV
30416.br
30417created from ThinPoolLV
30418.br
30419appears blank after creation
30420
30421.TP
30422SnapLV
30423.br
30424snapshot LV
30425.br
30426created from ThinPoolLV
30427.br
30428appears as a snapshot of another LV after creation
30429
30430
30431
30432.SH Thin Usage
30433
30434The primary method for using lvm thin provisioning:
30435
30436.SS 1. create ThinDataLV
30437
30438Create an LV that will hold thin pool data.
30439
30440.B lvcreate \-n ThinDataLV \-L LargeSize VG
30441
30442.I Example
30443.br
30444# lvcreate \-n pool0 \-L 10G vg
30445
30446.SS 2. create ThinMetaLV
30447
30448Create an LV that will hold thin pool metadata.
30449
30450.B lvcreate \-n ThinMetaLV \-L SmallSize VG
30451
30452.I Example
30453.br
30454# lvcreate \-n pool0meta \-L 1G vg
30455
30456# lvs
30457 LV VG Attr LSize
30458 pool0 vg -wi-a----- 10.00g
30459 pool0meta vg -wi-a----- 1.00g
30460
30461.SS 3. create ThinPoolLV
30462
30463.nf
30464Combine the data and metadata LVs into a thin pool LV.
30465ThinDataLV is renamed to hidden ThinPoolLV_tdata.
30466ThinMetaLV is renamed to hidden ThinPoolLV_tmeta.
30467The new ThinPoolLV takes the previous name of ThinDataLV.
30468.fi
30469
30470.B lvconvert \-\-type thin-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
30471
30472.I Example
30473.br
30474# lvconvert \-\-type thin-pool \-\-poolmetadata vg/pool0meta vg/pool0
30475
30476# lvs vg/pool0
30477 LV VG Attr LSize Pool Origin Data% Meta%
30478 pool0 vg twi-a-tz-- 10.00g 0.00 0.00
30479
30480# lvs \-a
30481 LV VG Attr LSize
30482 pool0 vg twi-a-tz-- 10.00g
30483 [pool0_tdata] vg Twi-ao---- 10.00g
30484 [pool0_tmeta] vg ewi-ao---- 1.00g
30485
30486.SS 4. create ThinLV
30487
30488.nf
30489Create a new thin LV from the thin pool LV.
30490The thin LV is created with a virtual size.
30491Multiple new thin LVs may be created in the thin pool.
30492Thin LV names must be unique in the VG.
30493The '--type thin' option is inferred from the virtual size option.
30494The --thinpool argument specifies which thin pool will
30495contain the ThinLV.
30496.fi
30497
30498.B lvcreate \-n ThinLV \-V VirtualSize \-\-thinpool VG/ThinPoolLV
30499
30500.I Example
30501.br
30502Create a thin LV in a thin pool:
30503.br
30504# lvcreate \-n thin1 \-V 1T \-\-thinpool vg/pool0
30505
30506Create another thin LV in the same thin pool:
30507.br
30508# lvcreate \-n thin2 \-V 1T \-\-thinpool vg/pool0
30509
30510# lvs vg/thin1 vg/thin2
30511 LV VG Attr LSize Pool Origin Data%
30512 thin1 vg Vwi-a-tz-- 1.00t pool0 0.00
30513 thin2 vg Vwi-a-tz-- 1.00t pool0 0.00
30514
30515.SS 5. create SnapLV
30516
30517Create snapshots of an existing ThinLV or SnapLV.
30518.br
30519Do not specify
30520.BR \-L ", " \-\-size
30521when creating a thin snapshot.
30522.br
30523A size argument will cause an old COW snapshot to be created.
30524
30525.B lvcreate \-n SnapLV \-s VG/ThinLV
30526.br
30527.B lvcreate \-n SnapLV \-s VG/PrevSnapLV
30528
30529.I Example
30530.br
30531Create first snapshot of an existing ThinLV:
30532.br
30533# lvcreate \-n thin1s1 \-s vg/thin1
30534
30535Create second snapshot of the same ThinLV:
30536.br
30537# lvcreate \-n thin1s2 \-s vg/thin1
30538
30539Create a snapshot of the first snapshot:
30540.br
30541# lvcreate \-n thin1s1s1 \-s vg/thin1s1
30542
30543# lvs vg/thin1s1 vg/thin1s2 vg/thin1s1s1
30544 LV VG Attr LSize Pool Origin
30545 thin1s1 vg Vwi---tz-k 1.00t pool0 thin1
30546 thin1s2 vg Vwi---tz-k 1.00t pool0 thin1
30547 thin1s1s1 vg Vwi---tz-k 1.00t pool0 thin1s1
30548
30549.SS 6. activate SnapLV
30550
30551Thin snapshots are created with the persistent "activation skip"
30552flag, indicated by the "k" attribute. Use \-K with lvchange
30553or vgchange to activate thin snapshots with the "k" attribute.
30554
30555.B lvchange \-ay \-K VG/SnapLV
30556
30557.I Example
30558.br
30559# lvchange \-ay \-K vg/thin1s1
30560
30561# lvs vg/thin1s1
30562 LV VG Attr LSize Pool Origin
30563 thin1s1 vg Vwi-a-tz-k 1.00t pool0 thin1
30564
30565.SH Thin Topics
30566
30567.B Alternate syntax for specifying type thin\-pool
30568.br
30569.B Automatic pool metadata LV
30570.br
30571.B Specify devices for data and metadata LVs
30572.br
30573.B Tolerate device failures using raid
30574.br
30575.B Spare metadata LV
30576.br
30577.B Metadata check and repair
30578.br
30579.B Activation of thin snapshots
30580.br
30581.B Removing thin pool LVs, thin LVs and snapshots
30582.br
30583.B Manually manage free data space of thin pool LV
30584.br
30585.B Manually manage free metadata space of a thin pool LV
30586.br
30587.B Using fstrim to increase free space in a thin pool LV
30588.br
30589.B Automatically extend thin pool LV
30590.br
30591.B Data space exhaustion
30592.br
30593.B Metadata space exhaustion
30594.br
30595.B Automatic extend settings
30596.br
30597.B Zeroing
30598.br
30599.B Discard
30600.br
30601.B Chunk size
30602.br
30603.B Size of pool metadata LV
30604.br
30605.B Create a thin snapshot of an external, read only LV
30606.br
30607.B Convert a standard LV to a thin LV with an external origin
30608.br
30609.B Single step thin pool LV creation
30610.br
30611.B Single step thin pool LV and thin LV creation
30612.br
30613.B Merge thin snapshots
30614.br
30615.B XFS on snapshots
30616
30617\&
30618
30619.SS Alternate syntax for specifying type thin\-pool
30620
30621\&
30622
30623The fully specified syntax for creating a thin pool LV shown above is:
30624
30625.B lvconvert \-\-type thin-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
30626
30627An existing LV is converted to a thin pool by changing its type to
30628thin-pool. An alternate syntax may be used for the same operation:
30629
30630.B lvconvert \-\-thinpool VG/ThinDataLV \-\-poolmetadata VG/ThinMetaLV
30631
30632The thin-pool type is inferred by lvm; the --thinpool option is not an
30633alias for --type thin-pool. The use of the --thinpool option here is
30634different from the use of the --thinpool option when creating a thin LV,
30635where it specifies the pool in which the thin LV is created.
30636
30637
30638.SS Automatic pool metadata LV
30639
30640\&
30641
30642A thin data LV can be converted to a thin pool LV without specifying a
30643thin pool metadata LV. LVM automatically creates a metadata LV from the
30644same VG.
30645
30646.B lvcreate \-n ThinDataLV \-L LargeSize VG
30647.br
30648.B lvconvert \-\-type thin\-pool VG/ThinDataLV
30649
30650.I Example
30651.br
30652.nf
30653# lvcreate \-n pool0 \-L 10G vg
30654# lvconvert \-\-type thin\-pool vg/pool0
30655
30656# lvs \-a
30657 pool0 vg twi-a-tz-- 10.00g
30658 [pool0_tdata] vg Twi-ao---- 10.00g
30659 [pool0_tmeta] vg ewi-ao---- 16.00m
30660.fi
30661
30662
30663.SS Specify devices for data and metadata LVs
30664
30665\&
30666
30667The data and metadata LVs in a thin pool are best created on
30668separate physical devices. To do that, specify the device name(s)
30669at the end of the lvcreate line. It can be especially helpful
30670to use fast devices for the metadata LV.
30671
30672.B lvcreate \-n ThinDataLV \-L LargeSize VG LargePV
30673.br
30674.B lvcreate \-n ThinMetaLV \-L SmallSize VG SmallPV
30675.br
30676.B lvconvert \-\-type thin\-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
30677
30678.I Example
30679.br
30680.nf
30681# lvcreate \-n pool0 \-L 10G vg /dev/sdA
30682# lvcreate \-n pool0meta \-L 1G vg /dev/sdB
30683# lvconvert \-\-type thin\-pool \-\-poolmetadata vg/pool0meta vg/pool0
30684.fi
30685
30686.BR lvm.conf (5)
30687.B thin_pool_metadata_require_separate_pvs
30688.br
30689controls the default PV usage for thin pool creation.
30690
30691\&
30692
30693.SS Tolerate device failures using raid
30694
30695\&
30696
30697To tolerate device failures, use raid for the pool data LV and
30698pool metadata LV. This is especially recommended for pool metadata LVs.
30699
30700.B lvcreate \-\-type raid1 \-m 1 \-n ThinMetaLV \-L SmallSize VG PVA PVB
30701.br
30702.B lvcreate \-\-type raid1 \-m 1 \-n ThinDataLV \-L LargeSize VG PVC PVD
30703.br
30704.B lvconvert \-\-type thin\-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
30705
30706.I Example
30707.br
30708.nf
30709# lvcreate \-\-type raid1 \-m 1 \-n pool0 \-L 10G vg /dev/sdA /dev/sdB
30710# lvcreate \-\-type raid1 \-m 1 \-n pool0meta \-L 1G vg /dev/sdC /dev/sdD
30711# lvconvert \-\-type thin\-pool \-\-poolmetadata vg/pool0meta vg/pool0
30712.fi
30713
30714
30715.SS Spare metadata LV
30716
30717\&
30718
30719The first time a thin pool LV is created, lvm will create a spare
30720metadata LV in the VG. This behavior can be controlled with the
30721option \-\-poolmetadataspare y|n. (Future thin pool creations will
30722also attempt to create the pmspare LV if none exists.)
30723
30724To create the pmspare ("pool metadata spare") LV, lvm first creates
30725an LV with a default name, e.g. lvol0, and then converts this LV to
30726a hidden LV with the _pmspare suffix, e.g. lvol0_pmspare.
30727
30728One pmspare LV is kept in a VG to be used for any thin pool.
30729
30730The pmspare LV cannot be created explicitly, but may be removed
30731explicitly.
30732
30733.I Example
30734.br
30735.nf
30736# lvcreate \-n pool0 \-L 10G vg
30737# lvcreate \-n pool0meta \-L 1G vg
30738# lvconvert \-\-type thin\-pool \-\-poolmetadata vg/pool0meta vg/pool0
30739
30740# lvs \-a
30741 [lvol0_pmspare] vg ewi-------
30742 pool0 vg twi---tz--
30743 [pool0_tdata] vg Twi-------
30744 [pool0_tmeta] vg ewi-------
30745.fi
30746
30747The "Metadata check and repair" section describes the use of
30748the pmspare LV.
30749
30750
30751.SS Metadata check and repair
30752
30753\&
30754
30755If thin pool metadata is damaged, it may be repairable.
30756Checking and repairing thin pool metadata is analagous to
30757running fsck on a file system.
30758
30759When a thin pool LV is activated, lvm runs the thin_check command
30760to check the correctness of the metadata on the pool metadata LV.
30761
30762.BR lvm.conf (5)
30763.B thin_check_executable
30764.br
30765can be set to an empty string ("") to disable the thin_check step.
30766This is not recommended.
30767
30768.BR lvm.conf (5)
30769.B thin_check_options
30770.br
30771controls the command options used for the thin_check command.
30772
30773If the thin_check command finds a problem with the metadata,
30774the thin pool LV is not activated, and the thin pool metadata needs
30775to be repaired.
30776
30777Simple repair commands are not always successful. Advanced repair may
30778require editing thin pool metadata and lvm metadata. Newer versions of
30779the kernel and lvm tools may be more successful at repair. Report the
30780details of damaged thin metadata to get the best advice on recovery.
30781
30782Command to repair a thin pool:
30783.br
30784.B lvconvert \-\-repair VG/ThinPoolLV
30785
30786Repair performs the following steps:
30787
307881. Creates a new, repaired copy of the metadata.
30789.br
30790lvconvert runs the thin_repair command to read damaged metadata
30791from the existing pool metadata LV, and writes a new repaired
30792copy to the VG's pmspare LV.
30793
307942. Replaces the thin pool metadata LV.
30795.br
30796If step 1 is successful, the thin pool metadata LV is replaced
30797with the pmspare LV containing the corrected metadata.
30798The previous thin pool metadata LV, containing the damaged metadata,
30799becomes visible with the new name ThinPoolLV_tmetaN (where N is 0,1,...).
30800
30801If the repair works, the thin pool LV and its thin LVs can be activated,
30802and the LV containing the damaged thin pool metadata can be removed.
30803It may be useful to move the new metadata LV (previously pmspare) to a
30804better PV.
30805
30806If the repair does not work, the thin pool LV and its thin LVs are lost.
30807
30808If metadata is manually restored with thin_repair directly,
30809the pool metadata LV can be manually swapped with another LV
30810containing new metadata:
30811
30812.B lvconvert \-\-thinpool VG/ThinPoolLV \-\-poolmetadata VG/NewThinMetaLV
30813
30814
30815.SS Activation of thin snapshots
30816
30817\&
30818
30819When a thin snapshot LV is created, it is by default given the
30820"activation skip" flag. This flag is indicated by the "k" attribute
30821displayed by lvs:
30822
30823.nf
30824# lvs vg/thin1s1
30825 LV VG Attr LSize Pool Origin
30826 thin1s1 vg Vwi---tz-k 1.00t pool0 thin1
30827.fi
30828
30829This flag causes the snapshot LV to be skipped, i.e. not activated,
30830by normal activation commands. The skipping behavior does not
30831apply to deactivation commands.
30832
30833A snapshot LV with the "k" attribute can be activated using
30834the \-K (or \-\-ignoreactivationskip) option in addition to the
30835standard \-ay (or \-\-activate y) option.
30836
30837Command to activate a thin snapshot LV:
30838.br
30839.B lvchange \-ay \-K VG/SnapLV
30840
30841The persistent "activation skip" flag can be turned off during
30842lvcreate, or later with lvchange using the \-kn
30843(or \-\-setactivationskip n) option.
30844It can be turned on again with \-ky (or \-\-setactivationskip y).
30845
30846When the "activation skip" flag is removed, normal activation
30847commands will activate the LV, and the \-K activation option is
30848not needed.
30849
30850Command to create snapshot LV without the activation skip flag:
30851.br
30852.B lvcreate \-kn \-n SnapLV \-s VG/ThinLV
30853
30854Command to remove the activation skip flag from a snapshot LV:
30855.br
30856.B lvchange \-kn VG/SnapLV
30857
30858.BR lvm.conf (5)
30859.B auto_set_activation_skip
30860.br
30861controls the default activation skip setting used by lvcreate.
30862
30863
30864.SS Removing thin pool LVs, thin LVs and snapshots
30865
30866\&
30867
30868Removing a thin LV and its related snapshots returns the blocks it
30869used to the thin pool LV. These blocks will be reused for other
30870thin LVs and snapshots.
30871
30872Removing a thin pool LV removes both the data LV and metadata LV
30873and returns the space to the VG.
30874
30875lvremove of thin pool LVs, thin LVs and snapshots cannot be
30876reversed with vgcfgrestore.
30877
30878vgcfgbackup does not back up thin pool metadata.
30879
30880
30881.SS Manually manage free data space of thin pool LV
30882
30883\&
30884
30885The available free space in a thin pool LV can be displayed
30886with the lvs command. Free space can be added by extending
30887the thin pool LV.
30888
30889Command to extend thin pool data space:
30890.br
30891.B lvextend \-L Size VG/ThinPoolLV
30892
30893.I Example
30894.br
30895.nf
308961. A thin pool LV is using 26.96% of its data blocks.
30897# lvs
30898 LV VG Attr LSize Pool Origin Data%
30899 pool0 vg twi-a-tz-- 10.00g 26.96
30900
309012. Double the amount of physical space in the thin pool LV.
30902# lvextend \-L+10G vg/pool0
30903
309043. The percentage of used data blocks is half the previous value.
30905# lvs
30906 LV VG Attr LSize Pool Origin Data%
30907 pool0 vg twi-a-tz-- 20.00g 13.48
30908.fi
30909
30910Other methods of increasing free data space in a thin pool LV
30911include removing a thin LV and its related snapsots, or running
30912fstrim on the file system using a thin LV.
30913
30914
30915.SS Manually manage free metadata space of a thin pool LV
30916
30917\&
30918
30919The available metadata space in a thin pool LV can be displayed
30920with the lvs \-o+metadata_percent command.
30921
30922Command to extend thin pool metadata space:
30923.br
30924.B lvextend \-\-poolmetadatasize Size VG/ThinPoolLV
30925
30926.I Example
30927.br
309281. A thin pool LV is using 12.40% of its metadata blocks.
30929.nf
30930# lvs \-oname,size,data_percent,metadata_percent vg/pool0
30931 LV LSize Data% Meta%
30932 pool0 20.00g 13.48 12.40
30933.fi
30934
309352. Display a thin pool LV with its component thin data LV and thin metadata LV.
30936.nf
30937# lvs \-a \-oname,attr,size vg
30938 LV Attr LSize
30939 pool0 twi-a-tz-- 20.00g
30940 [pool0_tdata] Twi-ao---- 20.00g
30941 [pool0_tmeta] ewi-ao---- 12.00m
30942.fi
30943
309443. Double the amount of physical space in the thin metadata LV.
30945.nf
30946# lvextend \-\-poolmetadatasize +12M vg/pool0
30947.fi
30948
309494. The percentage of used metadata blocks is half the previous value.
30950.nf
30951# lvs \-a \-oname,size,data_percent,metadata_percent vg
30952 LV LSize Data% Meta%
30953 pool0 20.00g 13.48 6.20
30954 [pool0_tdata] 20.00g
30955 [pool0_tmeta] 24.00m
30956.fi
30957
30958
30959.SS Using fstrim to increase free space in a thin pool LV
30960
30961\&
30962
30963Removing files in a file system on top of a thin LV does not
30964generally add free space back to the thin pool. Manually running
30965the fstrim command can return space back to the thin pool that had
30966been used by removed files. fstrim uses discards and will not work
30967if the thin pool LV has discards mode set to ignore.
30968
30969.I Example
30970.br
30971A thin pool has 10G of physical data space, and a thin LV has a virtual
30972size of 100G. Writing a 1G file to the file system reduces the
30973free space in the thin pool by 10% and increases the virtual usage
30974of the file system by 1%. Removing the 1G file restores the virtual
309751% to the file system, but does not restore the physical 10% to the
30976thin pool. The fstrim command restores the physical space to the thin pool.
30977
30978.nf
30979# lvs \-a \-oname,attr,size,pool_lv,origin,data_percent,metadata_percent vg
30980LV Attr LSize Pool Origin Data% Meta%
30981pool0 twi-a-tz-- 10.00g 47.01 21.03
30982thin1 Vwi-aotz-- 100.00g pool0 2.70
30983
30984# df \-h /mnt/X
30985Filesystem Size Used Avail Use% Mounted on
30986/dev/mapper/vg-thin1 99G 1.1G 93G 2% /mnt/X
30987
30988# dd if=/dev/zero of=/mnt/X/1Gfile bs=4096 count=262144; sync
30989
30990# lvs
30991pool0 vg twi-a-tz-- 10.00g 57.01 25.26
30992thin1 vg Vwi-aotz-- 100.00g pool0 3.70
30993
30994# df \-h /mnt/X
30995/dev/mapper/vg-thin1 99G 2.1G 92G 3% /mnt/X
30996
30997# rm /mnt/X/1Gfile
30998
30999# lvs
31000pool0 vg twi-a-tz-- 10.00g 57.01 25.26
31001thin1 vg Vwi-aotz-- 100.00g pool0 3.70
31002
31003# df \-h /mnt/X
31004/dev/mapper/vg-thin1 99G 1.1G 93G 2% /mnt/X
31005
31006# fstrim \-v /mnt/X
31007
31008# lvs
31009pool0 vg twi-a-tz-- 10.00g 47.01 21.03
31010thin1 vg Vwi-aotz-- 100.00g pool0 2.70
31011.fi
31012
31013The "Discard" section covers an option for automatically freeing data
31014space in a thin pool.
31015
31016
31017.SS Automatically extend thin pool LV
31018
31019\&
31020
31021The lvm daemon dmeventd (lvm2-monitor) monitors the data usage of thin
31022pool LVs and extends them when the usage reaches a certain level. The
31023necessary free space must exist in the VG to extend thin pool LVs.
31024Monitoring and extension of thin pool LVs are controlled independently.
31025
31026.I monitoring
31027
31028When a thin pool LV is activated, dmeventd will begin monitoring it by
31029default.
31030
31031Command to start or stop dmeventd monitoring a thin pool LV:
31032.br
31033.B lvchange \-\-monitor {y|n} VG/ThinPoolLV
31034
31035The current dmeventd monitoring status of a thin pool LV can be displayed
31036with the command lvs -o+seg_monitor.
31037
31038.I autoextend
31039
31040dmeventd should be configured to extend thin pool LVs before all data
31041space is used. Warnings are emitted through syslog when the use of a thin
31042pool reaches 80%, 85%, 90% and 95%. (See the section "Data space
31043exhaustion" for the effects of not extending a thin pool LV.) The point
31044at which dmeventd extends thin pool LVs, and the amount are controlled
31045with two configuration settings:
31046
31047.BR lvm.conf (5)
31048.B thin_pool_autoextend_threshold
31049.br
31050is a percentage full value that defines when the thin pool LV should be
31051extended. Setting this to 100 disables automatic extention. The minimum
31052value is 50.
31053
31054.BR lvm.conf (5)
31055.B thin_pool_autoextend_percent
31056.br
31057defines how much extra data space should be added to the thin pool LV from
31058the VG, in percent of its current size.
31059
31060.I disabling
31061
31062There are multiple ways that extension of thin pools could be prevented:
31063
31064.IP \[bu] 2
31065If the dmeventd daemon is not running, no monitoring or automatic
31066extension will occur.
31067
31068.IP \[bu]
31069Even when dmeventd is running, all monitoring can be disabled with the
31070lvm.conf monitoring setting.
31071
31072.IP \[bu]
31073To activate or create a thin pool LV without interacting with dmeventd,
31074the --ignoremonitoring option can be used. With this option, the command
31075will not ask dmeventd to monitor the thin pool LV.
31076
31077.IP \[bu]
31078Setting thin_pool_autoextend_threshould to 100 disables automatic
31079extension of thin pool LVs, even if they are being monitored by dmeventd.
31080
31081.P
31082
31083.I Example
31084.br
31085If thin_pool_autoextend_threshold is 70 and thin_pool_autoextend_percent is 20,
31086whenever a pool exceeds 70% usage, it will be extended by another 20%.
31087For a 1G pool, using 700M will trigger a resize to 1.2G. When the usage exceeds
31088840M, the pool will be extended to 1.44G, and so on.
31089
31090
31091.SS Data space exhaustion
31092
31093\&
31094
31095When properly managed, thin pool data space should be extended before it
31096is all used (see the section "Automatically extend thin pool LV"). If
31097thin pool data space is already exhausted, it can still be extended (see
31098the section "Manually manage free data space of thin pool LV".)
31099
31100The behavior of a full thin pool is configurable with the --errorwhenfull
31101y|n option to lvcreate or lvchange. The errorwhenfull setting applies
31102only to writes; reading thin LVs can continue even when data space is
31103exhausted.
31104
31105Command to change the handling of a full thin pool:
31106.br
31107.B lvchange --errorwhenfull {y|n} VG/ThinPoolLV
31108
31109.BR lvm.conf (5)
31110.B error_when_full
31111.br
31112controls the default error when full behavior.
31113
31114The current setting of a thin pool LV can be displayed with the command:
31115lvs -o+lv_when_full.
31116
31117The errorwhenfull setting does not effect the monitoring and autoextend
31118settings, and the monitoring/autoextend settings do not effect the
31119errorwhenfull setting. It is only when monitoring/autoextend are not
31120effective that the thin pool becomes full and the errorwhenfull setting is
31121applied.
31122
31123.I errorwhenfull n
31124
31125This is the default. Writes to thin LVs are accepted and queued, with the
31126expectation that pool data space will be extended soon. Once data space
31127is extended, the queued writes will be processed, and the thin pool will
31128return to normal operation.
31129
31130While waiting to be extended, the thin pool will queue writes for up to 60
31131seconds (the default). If data space has not been extended after this
31132time, the queued writes will return an error to the caller, e.g. the file
31133system. This can result in file system corruption for non-journaled file
31134systems that may require fsck. When a thin pool returns errors for writes
31135to a thin LV, any file system is subject to losing unsynced user data.
31136
31137The 60 second timeout can be changed or disabled with the dm\-thin\-pool
31138kernel module option
31139.B no_space_timeout.
31140This option sets the number of seconds that thin pools will queue writes.
31141If set to 0, writes will not time out. Disabling timeouts can result in
31142the system running out of resources, memory exhaustion, hung tasks, and
31143deadlocks. (The timeout applies to all thin pools on the system.)
31144
31145.I errorwhenfull y
31146
31147Writes to thin LVs immediately return an error, and no writes are queued.
31148In the case of a file system, this can result in corruption that may
31149require fsck (the specific consequences depend on the thin LV user.)
31150
31151.I data percent
31152
31153When data space is exhausted, the lvs command displays 100 under Data% for
31154the thin pool LV:
31155
31156.nf
31157# lvs vg/pool0
31158 LV VG Attr LSize Pool Origin Data%
31159 pool0 vg twi-a-tz-- 512.00m 100.00
31160.fi
31161
31162.I causes
31163
31164A thin pool may run out of data space for any of the following reasons:
31165
31166.IP \[bu] 2
31167Automatic extension of the thin pool is disabled, and the thin pool is not
31168manually extended. (Disabling automatic extension is not recommended.)
31169
31170.IP \[bu]
31171The dmeventd daemon is not running and the thin pool is not manually
31172extended. (Disabling dmeventd is not recommended.)
31173
31174.IP \[bu]
31175Automatic extension of the thin pool is too slow given the rate of writes
31176to thin LVs in the pool. (This can be addressed by tuning the
31177thin_pool_autoextend_threshold and thin_pool_autoextend_percent.
31178See "Automatic extend settings".)
31179
31180.IP \[bu]
31181The VG does not have enough free blocks to extend the thin pool.
31182
31183.P
31184
31185.SS Metadata space exhaustion
31186
31187\&
31188
31189If thin pool metadata space is exhausted (or a thin pool metadata
31190operation fails), errors will be returned for IO operations on thin LVs.
31191
31192When metadata space is exhausted, the lvs command displays 100 under Meta%
31193for the thin pool LV:
31194
31195.nf
31196# lvs \-o lv_name,size,data_percent,metadata_percent vg/pool0
31197 LV LSize Data% Meta%
31198 pool0 100.00
31199.fi
31200
31201The same reasons for thin pool data space exhaustion apply to thin pool
31202metadata space.
31203
31204Metadata space exhaustion can lead to inconsistent thin pool metadata and
31205inconsistent file systems, so the response requires offline checking and
31206repair.
31207
312081. Deactivate the thin pool LV, or reboot the system if this is not possible.
31209
312102. Repair thin pool with lvconvert \-\-repair.
31211.br
31212 See "Metadata check and repair".
31213
312143. Extend pool metadata space with lvextend \-\-poolmetadatasize.
31215.br
31216 See "Manually manage free metadata space of a thin pool LV".
31217
312184. Check and repair file system with fsck.
31219
31220
31221.SS Automatic extend settings
31222
31223\&
31224
31225Thin pool LVs can be extended according to preset values. The presets
31226determine if the LV should be extended based on how full it is, and if so
31227by how much. When dmeventd monitors thin pool LVs, it uses lvextend with
31228these presets. (See "Automatically extend thin pool LV".)
31229
31230Command to extend a thin pool data LV using presets:
31231.br
31232.B lvextend \-\-use\-policies VG/ThinPoolLV
31233
31234The command uses these settings:
31235
31236.BR lvm.conf (5)
31237.B thin_pool_autoextend_threshold
31238.br
31239autoextend the LV when its usage exceeds this percent.
31240
31241.BR lvm.conf (5)
31242.B thin_pool_autoextend_percent
31243.br
31244autoextend the LV by this much additional space.
31245
31246To see the default values of these settings, run:
31247
31248.B lvmconfig \-\-type default \-\-withcomment
31249.RS
31250.B activation/thin_pool_autoextend_threshold
31251.RE
31252
31253.B lvmconfig \-\-type default \-\-withcomment
31254.RS
31255.B activation/thin_pool_autoextend_percent
31256.RE
31257
31258To change these values globally, edit
31259.BR lvm.conf (5).
31260
31261To change these values on a per-VG or per-LV basis, attach a "profile" to
31262the VG or LV. A profile is a collection of config settings, saved in a
31263local text file (using the lvm.conf format). lvm looks for profiles in
31264the profile_dir directory, e.g. /etc/lvm/profile/. Once attached to a VG
31265or LV, lvm will process the VG or LV using the settings from the attached
31266profile. A profile is named and referenced by its file name.
31267
31268To use a profile to customize the lvextend settings for an LV:
31269
31270.IP \[bu] 2
31271Create a file containing settings, saved in profile_dir.
31272For the profile_dir location, run:
31273.br
31274.B lvmconfig config/profile_dir
31275
31276.IP \[bu] 2
31277Attach the profile to an LV, using the command:
31278.br
31279.B lvchange \-\-metadataprofile ProfileName VG/ThinPoolLV
31280
31281.IP \[bu] 2
31282Extend the LV using the profile settings:
31283.br
31284.B lvextend \-\-use\-policies VG/ThinPoolLV
31285
31286.P
31287
31288.I Example
31289.br
31290.nf
31291# lvmconfig config/profile_dir
31292profile_dir="/etc/lvm/profile"
31293
31294# cat /etc/lvm/profile/pool0extend.profile
31295activation {
31296 thin_pool_autoextend_threshold=50
31297 thin_pool_autoextend_percent=10
31298}
31299
31300# lvchange --metadataprofile pool0extend vg/pool0
31301
31302# lvextend --use-policies vg/pool0
31303.fi
31304
31305.I Notes
31306.IP \[bu] 2
31307A profile is attached to a VG or LV by name, where the name references a
31308local file in profile_dir. If the VG is moved to another machine, the
31309file with the profile also needs to be moved.
31310
31311.IP \[bu] 2
31312Only certain settings can be used in a VG or LV profile, see:
31313.br
31314.B lvmconfig \-\-type profilable-metadata.
31315
31316.IP \[bu] 2
31317An LV without a profile of its own will inherit the VG profile.
31318
31319.IP \[bu] 2
31320Remove a profile from an LV using the command:
31321.br
31322.B lvchange --detachprofile VG/ThinPoolLV.
31323
31324.IP \[bu] 2
31325Commands can also have profiles applied to them. The settings that can be
31326applied to a command are different than the settings that can be applied
31327to a VG or LV. See lvmconfig \-\-type profilable\-command. To apply a
31328profile to a command, write a profile, save it in the profile directory,
31329and run the command using the option: \-\-commandprofile ProfileName.
31330
31331
31332.SS Zeroing
31333
31334\&
31335
31336When a thin pool provisions a new data block for a thin LV, the
31337new block is first overwritten with zeros. The zeroing mode is
31338indicated by the "z" attribute displayed by lvs. The option \-Z
31339(or \-\-zero) can be added to commands to specify the zeroing mode.
31340
31341Command to set the zeroing mode when creating a thin pool LV:
31342.br
31343.B lvconvert \-\-type thin\-pool \-Z{y|n}
31344.br
31345.RS
31346.B \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
31347.RE
31348
31349Command to change the zeroing mode of an existing thin pool LV:
31350.br
31351.B lvchange \-Z{y|n} VG/ThinPoolLV
31352
31353If zeroing mode is changed from "n" to "y", previously provisioned
31354blocks are not zeroed.
31355
31356Provisioning of large zeroed chunks impacts performance.
31357
31358.BR lvm.conf (5)
31359.B thin_pool_zero
31360.br
31361controls the default zeroing mode used when creating a thin pool.
31362
31363
31364.SS Discard
31365
31366\&
31367
31368The discard behavior of a thin pool LV determines how discard requests are
31369handled. Enabling discard under a file system may adversely affect the
31370file system performance (see the section on fstrim for an alternative.)
31371Possible discard behaviors:
31372
31373ignore: Ignore any discards that are received.
31374
31375nopassdown: Process any discards in the thin pool itself and allow
31376the no longer needed extends to be overwritten by new data.
31377
31378passdown: Process discards in the thin pool (as with nopassdown), and
31379pass the discards down the the underlying device. This is the default
31380mode.
31381
31382Command to display the current discard mode of a thin pool LV:
31383.br
31384.B lvs \-o+discards VG/ThinPoolLV
31385
31386Command to set the discard mode when creating a thin pool LV:
31387.br
31388.B lvconvert \-\-discards {ignore|nopassdown|passdown}
31389.br
31390.RS
31391.B \-\-type thin\-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV
31392.RE
31393
31394Command to change the discard mode of an existing thin pool LV:
31395.br
31396.B lvchange \-\-discards {ignore|nopassdown|passdown} VG/ThinPoolLV
31397
31398.I Example
31399.br
31400.nf
31401# lvs \-o name,discards vg/pool0
31402pool0 passdown
31403
31404# lvchange \-\-discards ignore vg/pool0
31405.fi
31406
31407.BR lvm.conf (5)
31408.B thin_pool_discards
31409.br
31410controls the default discards mode used when creating a thin pool.
31411
31412
31413.SS Chunk size
31414
31415\&
31416
31417The size of data blocks managed by a thin pool can be specified with the
31418\-\-chunksize option when the thin pool LV is created. The default unit
31419is KiB. The value must be a multiple of 64KiB between 64KiB and 1GiB.
31420
31421When a thin pool is used primarily for the thin provisioning feature, a
31422larger value is optimal. To optimize for many snapshots, a smaller value
31423reduces copying time and consumes less space.
31424
31425Command to display the thin pool LV chunk size:
31426.br
31427.B lvs \-o+chunksize VG/ThinPoolLV
31428
31429.I Example
31430.br
31431.nf
31432# lvs \-o name,chunksize
31433 pool0 64.00k
31434.fi
31435
31436.BR lvm.conf (5)
31437.B thin_pool_chunk_size
31438.br
31439controls the default chunk size used when creating a thin pool.
31440
31441The default value is shown by:
31442.br
31443.B lvmconfig \-\-type default allocation/thin_pool_chunk_size
31444
31445
31446.SS Size of pool metadata LV
31447
31448\&
31449
31450The amount of thin metadata depends on how many blocks are shared between
31451thin LVs (i.e. through snapshots). A thin pool with many snapshots may
31452need a larger metadata LV. Thin pool metadata LV sizes can be from 2MiB
31453to 16GiB.
31454
31455When using lvcreate to create what will become a thin metadata LV, the
31456size is specified with the \-L|\-\-size option.
31457
31458When an LVM command automatically creates a thin metadata LV, the size is
31459specified with the \-\-poolmetadatasize option. When this option is not
31460given, LVM automatically chooses a size based on the data size and chunk
31461size.
31462
31463It can be hard to predict the amount of metadata space that will be
31464needed, so it is recommended to start with a size of 1GiB which should be
31465enough for all practical purposes. A thin pool metadata LV can later be
31466manually or automatically extended if needed.
31467
31468
31469.SS Create a thin snapshot of an external, read only LV
31470
31471\&
31472
31473Thin snapshots are typically taken of other thin LVs or other
31474thin snapshot LVs within the same thin pool. It is also possible
31475to take thin snapshots of external, read only LVs. Writes to the
31476snapshot are stored in the thin pool, and the external LV is used
31477to read unwritten parts of the thin snapshot.
31478
31479.B lvcreate \-n SnapLV \-s VG/ExternalOriginLV \-\-thinpool VG/ThinPoolLV
31480
31481.I Example
31482.br
31483.nf
31484# lvchange \-an vg/lve
31485# lvchange \-\-permission r vg/lve
31486# lvcreate \-n snaplve \-s vg/lve \-\-thinpool vg/pool0
31487
31488# lvs vg/lve vg/snaplve
31489 LV VG Attr LSize Pool Origin Data%
31490 lve vg ori------- 10.00g
31491 snaplve vg Vwi-a-tz-- 10.00g pool0 lve 0.00
31492.fi
31493
31494
31495.SS Convert a standard LV to a thin LV with an external origin
31496
31497\&
31498
31499A new thin LV can be created and given the name of an existing
31500standard LV. At the same time, the existing LV is converted to a
31501read only external LV with a new name. Unwritten portions of the
31502thin LV are read from the external LV.
31503The new name given to the existing LV can be specified with
31504\-\-originname, otherwise the existing LV will be given a default
31505name, e.g. lvol#.
31506
31507Convert ExampleLV into a read only external LV with the new name
31508NewExternalOriginLV, and create a new thin LV that is given the previous
31509name of ExampleLV.
31510
31511.B lvconvert \-\-type thin \-\-thinpool VG/ThinPoolLV
31512.br
31513.RS
31514.B \-\-originname NewExternalOriginLV VG/ExampleLV
31515.RE
31516
31517.I Example
31518.br
31519.nf
31520# lvcreate \-n lv_example \-L 10G vg
31521
31522# lvs
31523 lv_example vg -wi-a----- 10.00g
31524
31525# lvconvert \-\-type thin \-\-thinpool vg/pool0
31526 \-\-originname lv_external \-\-thin vg/lv_example
31527
31528# lvs
31529 LV VG Attr LSize Pool Origin
31530 lv_example vg Vwi-a-tz-- 10.00g pool0 lv_external
31531 lv_external vg ori------- 10.00g
31532.fi
31533
31534
31535.SS Single step thin pool LV creation
31536
31537\&
31538
31539A thin pool LV can be created with a single lvcreate command,
31540rather than using lvconvert on existing LVs.
31541This one command creates a thin data LV, a thin metadata LV,
31542and combines the two into a thin pool LV.
31543
31544.B lvcreate \-\-type thin\-pool \-L LargeSize \-n ThinPoolLV VG
31545
31546.I Example
31547.br
31548.nf
31549# lvcreate \-\-type thin\-pool \-L8M -n pool0 vg
31550
31551# lvs vg/pool0
31552 LV VG Attr LSize Pool Origin Data%
31553 pool0 vg twi-a-tz-- 8.00m 0.00
31554
31555# lvs \-a
31556 pool0 vg twi-a-tz-- 8.00m
31557 [pool0_tdata] vg Twi-ao---- 8.00m
31558 [pool0_tmeta] vg ewi-ao---- 8.00m
31559.fi
31560
31561
31562.SS Single step thin pool LV and thin LV creation
31563
31564\&
31565
31566A thin pool LV and a thin LV can be created with a single
31567lvcreate command. This one command creates a thin data LV,
31568a thin metadata LV, combines the two into a thin pool LV,
31569and creates a thin LV in the new pool.
31570.br
31571\-L LargeSize specifies the physical size of the thin pool LV.
31572.br
31573\-V VirtualSize specifies the virtual size of the thin LV.
31574
31575.B lvcreate \-V VirtualSize \-L LargeSize
31576.RS
31577.B \-n ThinLV \-\-thinpool VG/ThinPoolLV
31578.RE
31579
31580Equivalent to:
31581.br
31582.B lvcreate \-\-type thin\-pool \-L LargeSize VG/ThinPoolLV
31583.br
31584.B lvcreate \-n ThinLV \-V VirtualSize \-\-thinpool VG/ThinPoolLV
31585
31586.I Example
31587.br
31588.nf
31589# lvcreate \-L8M \-V2G \-n thin1 \-\-thinpool vg/pool0
31590
31591# lvs \-a
31592 pool0 vg twi-a-tz-- 8.00m
31593 [pool0_tdata] vg Twi-ao---- 8.00m
31594 [pool0_tmeta] vg ewi-ao---- 8.00m
31595 thin1 vg Vwi-a-tz-- 2.00g pool0
31596.fi
31597
31598
31599.SS Merge thin snapshots
31600
31601\&
31602
31603A thin snapshot can be merged into its origin thin LV using the lvconvert
31604\-\-merge command. The result of a snapshot merge is that the origin thin
31605LV takes the content of the snapshot LV, and the snapshot LV is removed.
31606Any content that was unique to the origin thin LV is lost after the merge.
31607
31608Because a merge changes the content of an LV, it cannot be done while the
31609LVs are open, e.g. mounted. If a merge is initiated while the LVs are open,
31610the effect of the merge is delayed until the origin thin LV is next
31611activated.
31612
31613.B lvconvert \-\-merge VG/SnapLV
31614
31615.I Example
31616.br
31617.nf
31618# lvs vg
31619 LV VG Attr LSize Pool Origin
31620 pool0 vg twi-a-tz-- 10.00g
31621 thin1 vg Vwi-a-tz-- 100.00g pool0
31622 thin1s1 vg Vwi-a-tz-k 100.00g pool0 thin1
31623
31624# lvconvert \-\-merge vg/thin1s1
31625
31626# lvs vg
31627 LV VG Attr LSize Pool Origin
31628 pool0 vg twi-a-tz-- 10.00g
31629 thin1 vg Vwi-a-tz-- 100.00g pool0
31630.fi
31631
31632.I Example
31633.br
31634.nf
31635Delayed merging of open LVs.
31636
31637# lvs vg
31638 LV VG Attr LSize Pool Origin
31639 pool0 vg twi-a-tz-- 10.00g
31640 thin1 vg Vwi-aotz-- 100.00g pool0
31641 thin1s1 vg Vwi-aotz-k 100.00g pool0 thin1
31642
31643# df
31644/dev/mapper/vg-thin1 100G 33M 100G 1% /mnt/X
31645/dev/mapper/vg-thin1s1 100G 33M 100G 1% /mnt/Xs
31646
31647# ls /mnt/X
31648file1 file2 file3
31649# ls /mnt/Xs
31650file3 file4 file5
31651
31652# lvconvert \-\-merge vg/thin1s1
31653Logical volume vg/thin1s1 contains a filesystem in use.
31654Delaying merge since snapshot is open.
31655Merging of thin snapshot thin1s1 will occur on next activation.
31656
31657# umount /mnt/X
31658# umount /mnt/Xs
31659
31660# lvs \-a vg
31661 LV VG Attr LSize Pool Origin
31662 pool0 vg twi-a-tz-- 10.00g
31663 [pool0_tdata] vg Twi-ao---- 10.00g
31664 [pool0_tmeta] vg ewi-ao---- 1.00g
31665 thin1 vg Owi-a-tz-- 100.00g pool0
31666 [thin1s1] vg Swi-a-tz-k 100.00g pool0 thin1
31667
31668# lvchange \-an vg/thin1
31669# lvchange \-ay vg/thin1
31670
31671# mount /dev/vg/thin1 /mnt/X
31672
31673# ls /mnt/X
31674file3 file4 file5
31675.fi
31676
31677
31678.SS XFS on snapshots
31679
31680\&
31681
31682Mounting an XFS file system on a new snapshot LV requires attention to the
31683file system's log state and uuid. On the snapshot LV, the xfs log will
31684contain a dummy transaction, and the xfs uuid will match the uuid from the
31685file system on the origin LV.
31686
31687If the snapshot LV is writable, mounting will recover the log to clear the
31688dummy transaction, but will require skipping the uuid check:
31689
31690mount /dev/VG/SnapLV /mnt \-o nouuid
31691
31692Or, the uuid can be changed on disk before mounting:
31693
31694xfs_admin \-U generate /dev/VG/SnapLV
31695.br
31696mount /dev/VG/SnapLV /mnt
31697
31698If the snapshot LV is readonly, the log recovery and uuid check need to be
31699skipped while mounting readonly:
31700
31701mount /dev/VG/SnapLV /mnt \-o ro,nouuid,norecovery
31702
31703.SH SEE ALSO
31704.BR lvm (8),
31705.BR lvm.conf (5),
31706.BR lvmconfig (8),
31707.BR lvcreate (8),
31708.BR lvconvert (8),
31709.BR lvchange (8),
31710.BR lvextend (8),
31711.BR lvremove (8),
31712.BR lvs (8),
31713.BR thin_dump (8),
31714.BR thin_repair (8)
31715.BR thin_restore (8)
31716
31717\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvremove.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005542\013062740170\0020165\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVREMOVE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
31718.SH NAME
31719lvremove \(em remove a logical volume
31720.SH SYNOPSIS
31721.B lvremove
31722.RB [ \-A | \-\-autobackup
31723.RI { y | n }]
31724.RB [ \-\-commandprofile
31725.IR ProfileName ]
31726.RB [ \-d | \-\-debug ]
31727.RB [ \-h | \-\-help ]
31728.RB [ \-\-nohistory ]
31729.RB [ \-\-reportformat
31730.RB { basic | json }]
31731.RB [ \-S | \-\-select
31732.IR Selection ]
31733.RB [ \-t | \-\-test ]
31734.RB [ \-v | \-\-verbose ]
31735.RB [ \-\-version ]
31736.RB [ \-f | \-\-force ]
31737.RB [ \-\-noudevsync ]
31738.RI [ LogicalVolume { Name | Path }...]
31739.SH DESCRIPTION
31740lvremove removes one or more logical volumes.
31741Confirmation will be requested before deactivating any active logical
31742volume prior to removal. Logical volumes cannot be deactivated
31743or removed while they are open (e.g. if they contain a mounted filesystem).
31744Removing an origin logical volume will also remove all dependent snapshots.
31745.sp
31746If the logical volume is clustered then it must be deactivated on all
31747nodes in the cluster before it can be removed. A single lvchange command
31748issued from one node can do this.
31749.sp
31750If the configuration setting \fBmetadata/record_lvs_history\fP is enabled
31751and the logical volume being removed forms part of the history of at least
31752one logical volume that is still present then a simplified representation of
31753the logical volume will be retained. This includes the time of removal
31754(\fBlv_time_removed\fP reporting field), creation time (\fBlv_time\fP), name
31755(\fBlv_name\fP), LV uuid (\fBlv_uuid\fP) and VG name (\fBvg_name\fP) and
31756allows you to see the ancestry chain of thin snapshot volumes even after
31757some intermediate logical volumes have been removed.
31758The names of such historical logical volumes acquire a hyphen as a prefix
31759(e.g. '-lvol1') and cannot be reactivated. Use lvremove a second time,
31760with the hyphen, to remove the record of the former logical volume completely.
31761.SH OPTIONS
31762See \fBlvm\fP(8) for common options.
31763.TP
31764.BR \-f ", " \-\-force
31765Remove active logical volumes without confirmation.
31766Tool will try to deactivate \fIunused\fP volume.
31767To proceed with damaged pools use \-ff
31768.TP
31769.B \-\-nohistory
31770Disable the recording of history of logical volumes which are being removed.
31771(This has no effect unless the configuration setting
31772\fBmetadata/record_lvs_history\fP is enabled.)
31773.TP
31774.B \-\-noudevsync
31775Disable udev synchronisation. The
31776process will not wait for notification from udev.
31777It will continue irrespective of any possible udev processing
31778in the background. You should only use this if udev is not running
31779or has rules that ignore the devices LVM2 creates.
31780.SH Examples
31781Remove the active logical volume lvol1 in volume group vg00
31782without asking for confirmation:
31783.sp
31784.B lvremove \-f vg00/lvol1
31785.sp
31786Remove all logical volumes in volume group vg00:
31787.sp
31788.B lvremove vg00
31789.SH SEE ALSO
31790.BR lvcreate (8),
31791.BR lvdisplay (8),
31792.BR lvchange (8),
31793.BR lvm (8),
31794.BR lvs (8),
31795.BR lvscan (8),
31796.BR vgremove (8)
31797\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgcreate.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000016610\013062740170\0020124\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCREATE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
31798.SH NAME
31799vgcreate \(em create a volume group
31800.SH SYNOPSIS
31801.B vgcreate
31802.RB [ \-\-addtag
31803.IR Tag ]
31804.RB [ \-\-alloc
31805.IR AllocationPolicy ]
31806.RB [ \-A | \-\-autobackup
31807.RI { y | n }]
31808.RB [ \-c | \-\-clustered
31809.RI { y | n }]
31810.RB [ \-\-commandprofile
31811.IR ProfileName ]
31812.RB [ \-d | \-\-debug ]
31813.RB [ \-h | \-\-help ]
31814.RB [ \-l | \-\-maxlogicalvolumes
31815.IR MaxLogicalVolumes ]
31816.RB [ \-M | \-\-metadatatype
31817.IR type ]
31818.RB [ \-\-metadataprofile
31819.IR ProfileName ]
31820.RB [ \-p | \-\-maxphysicalvolumes
31821.IR MaxPhysicalVolumes ]
31822.RB [ \-\- [ vg ] metadatacopies
31823.IR NumberOfCopies | unmanaged | all ]
31824.RB [ \-s | \-\-physicalextentsize
31825.IR PhysicalExtentSize [ bBsSkKmMgGtTpPeE ]]
31826.RB [ \-\-reportformat
31827.RB { basic | json }]
31828.RB [ \-\-shared ]
31829.RB [ \-\-systemid
31830.IR SystemID ]
31831.RB [ \-t | \-\-test ]
31832.RB [ \-v | \-\-verbose ]
31833.RB [ \-\-version ]
31834.RB [ "PHYSICAL DEVICE OPTIONS" ]
31835.I VolumeGroupName PhysicalDevicePath
31836.RI [ PhysicalDevicePath ...]
31837.SH DESCRIPTION
31838vgcreate creates a new volume group called
31839.I VolumeGroupName
31840using the block special device \fIPhysicalDevicePath\fP.
31841.sp
31842If \fIPhysicalDevicePath\fP was not previously configured for LVM with
31843\fBpvcreate\fP(8), the device will be initialized with the same
31844default values used with \fBpvcreate\fP(8). If non-default
31845\fPpvcreate\fP values are desired, they may be given on the
31846commandline with the same options as \fBpvcreate\fP(8). See
31847.B PHYSICAL DEVICE OPTIONS
31848for available options. Note that the restore-related options such as
31849.BR \-\-restorefile ", " \-\-uuid " and " \-\-physicalvolumesize
31850are not available. If a restore operation is needed, use
31851\fBpvcreate\fP(8) and \fBvgcfgrestore\fP(8).
31852.SH OPTIONS
31853See \fBlvm\fP(8) for common options.
31854.TP
31855.BR \-c ", " \-\-clustered " {" \fIy | \fIn }
31856If clustered locking is enabled, this defaults to \fBy\fP indicating that
31857this Volume Group is shared with other nodes in the cluster.
31858
31859If the new Volume Group contains only local disks that are not visible
31860on the other nodes, you must specify \fB\-\-clustered\ n\fP.
31861If the cluster infrastructure is unavailable on a particular node at a
31862particular time, you may still be able to use such Volume Groups.
31863.TP
31864.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes
31865Sets the maximum number of logical volumes allowed in this
31866volume group.
31867The setting can be changed with \fBvgchange\fP(8).
31868For volume groups with metadata in lvm1 format, the limit
31869and default value is 255.
31870If the metadata uses lvm2 format, the default value is 0
31871which removes this restriction: there is then no limit.
31872.TP
31873.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes
31874Sets the maximum number of physical volumes that can belong
31875to this volume group.
31876The setting can be changed with \fBvgchange\fP.
31877For volume groups with metadata in lvm1 format, the limit
31878and default value is 255.
31879If the metadata uses lvm2 format, the value 0 removes this restriction:
31880there is then no limit. If you have a large number of physical volumes in
31881a volume group with metadata in lvm2 format, for tool performance reasons,
31882you should consider some use of \fB\-\-pvmetadatacopies 0\fP as described in
31883\fBpvcreate\fP(8), and/or use \fB\-\-vgmetadatacopies\fP.
31884.TP
31885.BR \-\- [ vg ] metadatacopies " " \fINumberOfCopies | \fIunmanaged | \fIall
31886Sets the desired number of metadata copies in the volume group. If set to
31887a non-zero value, LVM will automatically manage the 'metadataignore'
31888flags on the physical volumes (see \fBpvcreate\fP(8) or
31889\fBpvchange \-\-metadataignore\fP) in order
31890to achieve \fINumberOfCopies\fP copies of metadata. If set to \fIunmanaged\fP,
31891LVM will not automatically manage the 'metadataignore' flags. If set to
31892\fIall\fP, LVM will first clear all of the 'metadataignore' flags on all
31893metadata areas in the volume group, then set the value to \fIunmanaged\fP.
31894The \fBvgmetadatacopies\fP option is useful for volume groups containing
31895large numbers of physical volumes with metadata as it may be used to
31896minimize metadata read and write overhead.
31897The default value is \fIunmanaged\fP.
31898.TP
31899.BR \-\-metadataprofile " " \fIProfileName
31900Uses and attaches the ProfileName configuration profile to the volume group
31901metadata. Whenever the volume group is processed next time, the profile is
31902automatically applied. The profile is inherited by all logical volumes in
31903the volume group unless the logical volume itself has its own profile attached.
31904See \fBlvm.conf\fP(5) for more information about \fBmetadata profiles\fP.
31905.TP
31906.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize [ \fIbBsSkKmMgGtTpPeE ]
31907Sets the physical extent size on physical volumes of this volume group.
31908A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
31909is the default if no suffix is present. For LVM2 format, the value must be a
31910power of 2 of at least 1 sector (where the sector size is the largest sector
31911size of the PVs currently used in the VG) or, if not a power of 2, at least
31912128KiB. For the older LVM1 format, it must be a power of 2 of at least 8KiB.
31913The default is 4 MiB.
31914Once this value has been set, it is difficult to change it without recreating
31915the volume group which would involve backing up and restoring data on any
31916logical volumes. However, if no extents need moving for the new
31917value to apply, it can be altered using \fBvgchange \-s\fP.
31918
31919If the volume group metadata uses lvm1 format, extents can vary in size from
319208KiB to 16GiB and there is a limit of 65534 extents in each logical volume. The
31921default of 4 MiB leads to a maximum logical volume size of around 256GiB.
31922
31923If the volume group metadata uses lvm2 format those restrictions do not apply,
31924but having a large number of extents will slow down the tools but have no
31925impact on I/O performance to the logical volume. The smallest PE is 1KiB
31926
31927The 2.4 kernel has a limitation of 2TiB per block device.
31928
31929.TP
31930.B \-\-shared
31931Create a shared VG using lvmlockd if LVM is compiled with lockd support.
31932 lvmlockd will select lock type sanlock or dlm depending on which lock
31933manager is running. This allows multiple hosts to share a VG on shared
31934devices. lvmlockd and a lock manager must be configured and running. See
31935.BR lvmlockd (8).
31936
31937.TP
31938.BR \-\-systemid " " \fISystemID
31939Specifies the system ID that will be given to the new VG, overriding the
31940system ID of the host running the command. A VG is normally created
31941without this option, in which case the new VG is given the system ID of
31942the host creating it. Using this option requires caution because the
31943system ID of the new VG may not match the system ID of the host running
31944the command, leaving the VG inaccessible to the host. See
31945.BR lvmsystemid (7).
31946
31947.SH PHYSICAL DEVICE OPTIONS
31948The following options are available for initializing physical devices in the
31949volume group. These options are further described in the \fBpvcreate\fP(8)
31950man page.
31951.TP
31952.BR \-f ", " \-\-force
31953.TP
31954.BR \-y ", " \-\-yes
31955.TP
31956.BR \-Z ", " \-\-zero " {" \fIy | \fIn }
31957.TP
31958.B \-\-labelsector \fIsector
31959.TP
31960.B \-\-metadatasize \fIsize
31961.TP
31962.B \-\-pvmetadatacopies \fIcopies
31963.TP
31964.B \-\-dataalignment \fIalignment
31965.TP
31966.B \-\-dataalignmentoffset \fIalignment_offset
31967.SH Examples
31968Creates a volume group named "test_vg" using physical volumes "/dev/sdk1"
31969and "/dev/sdl1" with default physical extent size of 4MiB:
31970.sp
31971.B vgcreate test_vg /dev/sdk1 /dev/sdl1
31972
31973.SH SEE ALSO
31974.BR lvm (8),
31975.BR pvdisplay (8),
31976.BR pvcreate (8),
31977.BR vgdisplay (8),
31978.BR vgextend (8),
31979.BR vgreduce (8),
31980.BR lvcreate (8),
31981.BR lvdisplay (8),
31982.BR lvextend (8),
31983.BR lvreduce (8)
31984\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmconfig.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000021226\013062740170\0020307\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMCONFIG" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
31985.SH "NAME"
31986lvmconfig, lvm dumpconfig, lvm config \(em Display LVM configuration
31987.SH SYNOPSIS
31988.
31989.ad l
31990.B lvmconfig
31991.RB [ \-f | \-\-file
31992.IR Filename ]
31993.RB [ \-\-type
31994.RB { current | default | diff | full |\: list | missing | new \c
31995.RB | profilable | profilable-command | profilable-metadata }]
31996.RB [ \-\-atversion
31997.IR Version ]
31998.RB [ \-\-sinceversion
31999.IR Version ]
32000.RB [ \-\-ignoreadvanced ]
32001.RB [ \-\-ignoreunsupported ]
32002.RB [ \-\-ignorelocal ]
32003.RB [ \-l | \-\-list ]
32004.RB [ \-\-config
32005.IR ConfigurationString ]
32006.RB [ \-\-commandprofile
32007.IR ProfileName ]
32008.RB [ \-\-profile
32009.IR ProfileName ]
32010.RB [ \-\-metadataprofile
32011.IR ProfileName ]
32012.RB [ \-\-mergedconfig ]
32013.RB [ \-\-showdeprecated ]
32014.RB [ \-\-showunsupported ]
32015.RB [ \-\-validate ]
32016.RB [ \-\-withsummary ]
32017.RB [ \-\-withcomments ]
32018.RB [ \-\-withspaces ]
32019.RB [ \-\-withversions ]
32020.RB [ ConfigurationNode... ]
32021.ad b
32022.
32023.SH DESCRIPTION
32024lvmconfig produces formatted output from the LVM configuration tree.
32025The command was added in release 2.02.119 and has an identical longer form
32026\fBlvm dumpconfig\fP.
32027
32028.SH OPTIONS
32029.TP
32030.BR \-f ", " \-\-file " \fIFilename"
32031Send output to a file named 'filename'.
32032
32033.TP
32034.BR \-l ", " \-\-list
32035List configuration settings with summarizing comment. This is the same as using
32036\fBlvmconfig --type list --withsummary\fP.
32037
32038.TP
32039.BR \-\-type " {" current | default | diff | full | missing | new | profilable |\: profilable-command | profilable-metadata }
32040Select the type of configuration to display. The configuration settings
32041displayed have either default values or currently-used values assigned based on
32042the type selected. If no type is selected, \fB\-\-type current\fP is used
32043by default. Whenever a configuration setting with a default value is
32044commented out, it means the setting does not have any concrete default
32045value defined. Output can be saved and used as a proper \fBlvm.conf\fP(5)
32046file.
32047.RS
32048.IP \fBcurrent\fP 3
32049Display the current \fBlvm.conf\fP configuration merged with any \fBtag
32050config\fP if used. See also \fBlvm.conf\fP(5) for more info about LVM
32051configuration methods.
32052.IP \fBdefault\fP 3
32053Display all possible configuration settings with default values assigned.
32054.IP \fBdiff\fP 3
32055Display all configuration settings for which the values used differ from defaults.
32056The value assigned for each configuration setting is the value currently used.
32057Using this type also implies the use of \fB\-\-mergedconfig\fP option.
32058This is actually minimal LVM configuration which can be used without
32059a change to current configured behaviour.
32060.IP \fBfull\fP 3
32061Display full configuration tree - a combination of current configuration tree
32062(\fB\-\-type current\fP) and tree of settings for which default values are
32063used (\fB\-\-type missing\fP). This is exactly the configuration tree that
32064LVM2 uses during command execution. Using this type also implies
32065the use of \fB\-\-mergedconfig\fP option. If comments are displayed
32066(see \fB\-\-withcomments\fP and \fB\-\-withsummary\fP options), then
32067for each setting found in existing configuration and for which defaults
32068are not used, there's an extra comment line printed to denote this.
32069.IP \fBlist\fP 3
32070Display plain list of configuration settings.
32071.IP \fBmissing\fP 3
32072Display all configuration settings with default values assigned which are
32073missing in the configuration currently used and for which LVM automatically
32074fallbacks to using these default values.
32075.IP \fBnew\fP 3
32076Display all new configuration settings introduced in current LVM version
32077or specific version as defined by \fB\-\-atversion\fP option.
32078.IP \fBprofilable\fP 3
32079Display all profilable configuration settings with default values assigned.
32080See \fBlvm.conf\fP(5) for more info about \fBprofile config\fP method.
32081.IP \fBprofilable-command\fP 3
32082Display all profilable configuration settings with default values assigned
32083that can be used in command profile. This is a subset of settings displayed
32084by \fB\-\-type profilable\fP.
32085.IP \fBprofilable-metadata\fP 3
32086Display all profilable configuration settings with default values assigned
32087that can be used in metadata profile. This is a subset of settings displayed
32088by \fB\-\-type profilable\fP.
32089.RE
32090
32091.TP
32092.BI \-\-atversion " Version"
32093Specify an LVM version in x.y.z format where x is the major version,
32094the y is the minor version and z is the patchlevel (e.g. 2.2.106).
32095When configuration is displayed, the configuration settings recognized
32096at this LVM version will be considered only. This can be used
32097to display a configuration that a certain LVM version understands and
32098which does not contain any newer settings for which LVM would
32099issue a warning message when checking the configuration.
32100
32101.TP
32102.BI \-\-sinceversion " Version"
32103Specify an LVM version in x.y.z format where x is the major version,
32104the y is the minor version and z is the patchlevel (e.g. 2.2.106).
32105This option is currently applicable only with \fB\-\-type new\fP
32106to display all configuration settings introduced since given version.
32107
32108.TP
32109.B \-\-ignoreadvanced
32110Exclude advanced configuration settings from the output.
32111
32112.TP
32113.B \-\-ignoreunsupported
32114Exclude unsupported configuration settings from the output. These settings are
32115either used for debugging and development purposes only or their support is not
32116yet complete and they are not meant to be used in production. The \fBcurrent\fP
32117and \fBdiff\fP types include unsupported settings in their output by default,
32118all the other types ignore unsupported settings.
32119
32120.TP
32121.B \-\-ignorelocal
32122Ignore local section.
32123
32124.TP
32125.BI \-\-config " ConfigurationString"
32126Use \fIConfigurationString\fP to override existing configuration.
32127This configuration is then applied for the lvmconfig command itself.
32128See also \fBlvm.conf\fP(5) for more info about \fBconfig cascade\fP.
32129
32130.TP
32131.BI \-\-commandprofile " ProfileName"
32132Use \fIProfileName\fP to override existing configuration.
32133This configuration is then applied for the lvmconfig command itself.
32134See also \fB\-\-mergedconfig\fP option and \fBlvm.conf\fP(5) for
32135more info about \fBconfig cascade\fP.
32136
32137.TP
32138.BI \-\-profile " ProfileName"
32139The same as using \fB\-\-commandprofile\fP but the configuration is not
32140applied for the lvmconfig command itself.
32141
32142.TP
32143.BI \-\-metadataprofile " ProfileName"
32144Use \fIProfileName\fP to override existing configuration.
32145The configuration defined in metadata profile has no effect for
32146the lvmconfig command itself. lvmconfig displays the configuration only.
32147See also \fB\-\-mergedconfig\fP option and \fBlvm.conf\fP(5) for more
32148info about \fBconfig cascade\fP.
32149
32150.TP
32151.B \-\-mergedconfig
32152When the lvmconfig command is run with the \fB\-\-config\fP option
32153and/or \fB\-\-commandprofile\fP (or using \fBLVM_COMMAND_PROFILE\fP
32154environment variable), \fB\-\-profile\fP, \fB\-\-metadataprofile\fP
32155option, merge all the contents of the \fBconfig cascade\fP before displaying it.
32156Without the \fB\-\-mergeconfig\fP option used, only the configuration at
32157the front of the cascade is displayed. See also \fBlvm.conf\fP(5) for more
32158info about \fBconfig cascade\fP.
32159
32160.TP
32161.B \-\-showdeprecated
32162Include deprecated configuration settings in the output. These settings
32163are always deprecated since certain version. If concrete version is specified
32164with \fB--atversion\fP option, deprecated settings are automatically included
32165if specified version is lower that the version in which the settings were
32166deprecated. The \fBcurrent\fP and \fBdiff\fP types include deprecated settings
32167int their output by default, all the other types ignore deprecated settings.
32168
32169.TP
32170.B \-\-showunsupported
32171Include unsupported configuration settings in the output. These settings
32172are either used for debugging or development purposes only or their support
32173is not yet complete and they are not meant to be used in production. The
32174\fBcurrent\fP and \fBdiff\fP types include unsupported settings in their
32175output by default, all the other types ignore unsupported settings.
32176
32177.TP
32178.B \-\-validate
32179Validate current configuration used and exit with appropriate
32180return code. The validation is done only for the configuration
32181at the front of the \fBconfig cascade\fP. To validate the whole
32182merged configuration tree, use also the \fB\-\-mergedconfig\fP option.
32183The validation is done even if \fBconfig/checks\fP \fBlvm.conf\fP(5)
32184option is disabled.
32185
32186.TP
32187.B \-\-withsummary
32188Display a one line comment for each configuration node.
32189
32190.TP
32191.B \-\-withcomments
32192Display a full comment for each configuration node. For deprecated
32193settings, also display comments about deprecation in addition.
32194
32195.TP
32196.B \-\-withspaces
32197Where appropriate, add more spaces in output for better readability.
32198
32199.TP
32200.B \-\-withversions
32201Also display a comment containing the version of introduction for
32202each configuration node. If the setting is deprecated, also display
32203the version since which it is deprecated.
32204
32205.SH SEE ALSO
32206.BR lvm (8)
32207.BR lvmconf (8)
32208.BR lvm.conf (5)
32209\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm-config.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000025\013062740170\0020356\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.so man8/lvmconfig.8
32210\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgreduce.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003157\013062740170\0020132\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGREDUCE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
32211.SH NAME
32212vgreduce \(em reduce a volume group
32213.SH SYNOPSIS
32214.B vgreduce
32215.RB [ \-a | \-\-all ]
32216.RB [ \-A | \-\-autobackup
32217.RI { y | n }]
32218.RB [ \-\-commandprofile
32219.IR ProfileName ]
32220.RB [ \-d | \-\-debug ]
32221.RB [ \-h | \-? | \-\-help ]
32222.RB [ \-\-removemissing ]
32223.RB [ \-\-reportformat
32224.RB { basic | json }]
32225.RB [ \-t | \-\-test ]
32226.RB [ \-v | \-\-verbose ]
32227.I VolumeGroupName
32228.RI [ PhysicalVolumePath ...]
32229.SH DESCRIPTION
32230vgreduce allows you to remove one or more unused physical volumes
32231from a volume group.
32232.SH OPTIONS
32233See \fBlvm\fP(8) for common options.
32234.TP
32235.BR \-a ", " \-\-all
32236Removes all empty physical volumes if none are given on command line.
32237.TP
32238.B \-\-removemissing
32239Removes all missing physical volumes from the volume group, if there are no
32240logical volumes allocated on those. This resumes normal operation of the volume
32241group (new logical volumes may again be created, changed and so on).
32242
32243If this is not possible (there are logical volumes referencing the missing
32244physical volumes) and you cannot or do not want to remove them manually, you
32245can run this option with \fB\-\-force\fP to have \fBvgreduce\fP
32246remove any partial LVs.
32247
32248Any logical volumes and dependent snapshots that were partly on the
32249missing disks get removed completely. This includes those parts
32250that lie on disks that are still present.
32251
32252If your logical volumes spanned several disks including the ones that are
32253lost, you might want to try to salvage data first by activating your
32254logical volumes with \fB\-\-partial\fP as described in \fBlvm\fP(8).
32255
32256.SH SEE ALSO
32257.BR lvm (8),
32258.BR vgextend (8)
32259\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvscan.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003751\013062740170\0017614\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
32260.SH NAME
32261lvscan \(em scan (all disks) for Logical Volumes
32262.SH SYNOPSIS
32263.B lvscan
32264.RB [ \-a | \-\-all]
32265.RB [ \-b | \-\-blockdevice ]
32266.RB [ \-\-commandprofile
32267.IR ProfileName ]
32268.RB [ \-d | \-\-debug ]
32269.RB [ \-h | \-\-help ]
32270.RB [ \-\-ignorelockingfailure ]
32271.RB [ \-P | \-\-partial ]
32272.RB [ \-\-reportformat
32273.RB { basic | json }]
32274.RB [ \-v | \-\-verbose ]
32275.SH DESCRIPTION
32276lvscan scans all known volume groups or all supported LVM block devices
32277in the system for defined Logical Volumes. The output consists
32278of one line for each Logical Volume indicating whether or not it is active,
32279a snapshot or origin, the size of the device and its allocation policy.
32280Use \fBlvs\fP(8) or \fBlvdisplay\fP(8) to obtain more-comprehensive
32281information about the Logical Volumes.
32282.SH OPTIONS
32283See \fBlvm\fP(8) for common options.
32284.TP
32285.BR \-\-all
32286Include information in the output about internal Logical Volumes that
32287are components of normally-accessible Logical Volumes, such as mirrors,
32288but which are not independently accessible (e.g. not mountable).
32289For example, after creating a mirror using
32290.B lvcreate \-m1 \-\-mirrorlog disk\fR,
32291this option will reveal three internal Logical Volumes, with suffixes
32292mimage_0, mimage_1, and mlog.
32293.TP
32294.BR \-b ", " \-\-blockdevice
32295This option is now ignored. Instead, use \fBlvs\fP(8) or
32296\fBlvdisplay\fP(8) to obtain the device number.
32297.TP
32298.IR \fB\-\-cache " " LogicalVolume
32299Applicable only when \fBlvmetad\fP(8) is in use (see also \fBlvm.conf\fP(5),
32300global/use_lvmetad). This command issues a rescan of physical volume labels and
32301metadata areas of all PVs that the logical volume uses. In particular, this can
32302be used when a RAID logical volume becomes degraded, to update information
32303about physical volume availability. This is only necessary if the logical
32304volume is \fBnot\fP being monitored by dmeventd (see \fBlvchange\fP(8), option
32305\fB\-\-monitor\fP).
32306.SH SEE ALSO
32307.BR lvm (8),
32308.BR lvcreate (8),
32309.BR lvdisplay (8)
32310.BR lvs (8)
32311\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmsar.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000347\013062740170\0017630\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMSAR" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
32312
32313.SH "NAME"
32314lvmsar \(em LVM system activity reporter
32315
32316.SH "SYNOPSIS"
32317.B lvmsar
32318
32319.SH "DESCRIPTION"
32320lvmsar is not currently supported under LVM2.
32321
32322.SH "SEE ALSO"
32323.BR lvm (8)
32324\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/blkdeactivate.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006477\013062740170\0021140\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "BLKDEACTIVATE" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
32325.SH "NAME"
32326blkdeactivate \(em utility to deactivate block devices
32327.SH SYNOPSIS
32328.B blkdeactivate
32329.RB [ \-d \ \fIdm_options\fP ]
32330.RB [ \-e ]
32331.RB [ \-h ]
32332.RB [ \-l \ \fIlvm_options\fP ]
32333.RB [ \-m \ \fImpath_options\fP ]
32334.RB [ \-u ]
32335.RB [ \-v ]
32336.RI [ device ]
32337.SH DESCRIPTION
32338blkdeactivate utility deactivates block devices. If a device
32339is mounted, the utility can unmount it automatically before
32340trying to deactivate. The utility currently supports
32341device-mapper devices (DM), including LVM volumes and
32342software RAID MD devices. LVM volumes are handled directly
32343using the \fBlvm\fP(8) command, the rest of device-mapper
32344based devices are handled using the \fBdmsetup\fP(8) command.
32345MD devices are handled using the \fBmdadm\fP(8) command.
32346.SH OPTIONS
32347.TP
32348.BR \-d ", " \-\-dmoption \ \fIdm_options\fP
32349Comma separated list of device-mapper specific options.
32350Accepted \fBdmsetup\fP(8) options are:
32351.RS
32352.IP \fIretry\fP
32353Retry removal several times in case of failure.
32354.IP \fIforce\fP
32355Force device removal.
32356.RE
32357.TP
32358.BR \-e ", " \-\-errors
32359Show errors reported from tools called by \fBblkdeactivate\fP. Without this
32360option, any error messages from these external tools are suppressed and the
32361\fBblkdeactivate\fP itself provides only a summary message about device being
32362skipped or not.
32363.TP
32364.BR \-h ", " \-\-help
32365Display the help text.
32366.TP
32367.BR \-l ", " \-\-lvmoption \ \fIlvm_options\fP
32368Comma separated list of LVM specific options:
32369.RS
32370.IP \fIretry\fP
32371Retry removal several times in case of failure.
32372.IP \fIwholevg\fP
32373Deactivate the whole LVM Volume Group when processing a Logical Volume.
32374Deactivating Volume Group as a whole takes less time than deactivating each
32375Logical Volume separately.
32376.RE
32377.TP
32378.BR \-m ", " \-\-mpathoption \ \fImpath_options\fP
32379Comma separated list of device-mapper multipath specific options:
32380.RS
32381.IP \fIdisablequeueing\fP
32382Disable queueing on all multipath devices first before deactivation.
32383This avoids a situation where blkdeactivate may end up waiting if
32384all paths are unavailable for any underlying device-mapper multipath
32385device.
32386.RE
32387.TP
32388.BR \-u ", " \-\-umount
32389Unmount a mounted device before trying to deactivate it.
32390Without this option used, a device that is mounted is not deactivated.
32391.TP
32392.BR \-v ", " \-\-verbose
32393Run in verbose mode. Use \-\-vv for even more verbose mode.
32394.SH EXAMPLES
32395.sp
32396Deactivate all supported block devices found in the system. If a device
32397is mounted, skip its deactivation.
32398.sp
32399.B blkdeactivate
32400
32401Deactivate all supported block devices found in the system. If a device
32402is mounted, unmount it first if possible.
32403.sp
32404.B blkdeactivate \-u
32405
32406Deactivate supplied device together with all its holders. If any of the
32407devices processed is mounted, unmount it first if possible.
32408.sp
32409.B blkdeactivate \-u /dev/vg/lvol0
32410
32411Deactivate all supported block devices found in the system. Retry deactivation
32412of device-mapper devices in case the deactivation fails. Deactivate the whole
32413Volume Group at once when processing an LVM Logical Volume.
32414.sp
32415.B blkdeactivate \-u \-d retry \-l wholevg
32416
32417Deactivate all supported block devices found in the system. Retry deactivation
32418of device-mapper devices in case the deactivation fails and force removal.
32419.sp
32420.B blkdeactivate \-d force,retry
32421
32422.SH SEE ALSO
32423.BR dmsetup (8),
32424.BR lsblk (8),
32425.BR lvm (8),
32426.BR mdadm (8),
32427.BR multipathd (8),
32428.BR umount (8)
32429\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvs.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012656\013062740170\0017142\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
32430.SH NAME
32431pvs \(em report information about physical volumes
32432.SH SYNOPSIS
32433.B pvs
32434.RB [ \-a | \-\-all ]
32435.RB [ \-\-aligned ]
32436.RB [ \-\-binary ]
32437.RB [ \-\-commandprofile
32438.IR ProfileName ]
32439.RB [[ \-\-configreport
32440.IR ReportName ]
32441.RB [ \-o | \-\-options
32442.RI [ + | \- | # ] Field1 [, Field2 ...]
32443.RB [ \-O | \-\-sort
32444.RI [ + | \- ] Key1 [, Key2 ...]]
32445.RB [ \-S | \-\-select
32446.IR Selection ]
32447.RB ...]
32448.RB [ \-d | \-\-debug ]
32449.RB [ \-h | \-? | \-\-help ]
32450.RB [ \-\-ignorelockingfailure ]
32451.RB [ \-\-ignoreskippedcluster ]
32452.RB [ \-\-logonly ]
32453.RB [ \-\-nameprefixes ]
32454.RB [ \-\-noheadings ]
32455.RB [ \-\-nosuffix ]
32456.RB [ \-P | \-\-partial ]
32457.RB [ \-\-reportformat
32458.RB { basic | json }]
32459.RB [ \-\-rows ]
32460.RB [ \-\-segments ]
32461.RB [ \-\-separator
32462.IR Separator ]
32463.RB [ \-\-unbuffered ]
32464.RB [ \-\-units
32465.IR hHbBsSkKmMgGtTpPeE ]
32466.RB [ \-\-unquoted ]
32467.RB [ \-v|\-\-verbose ]
32468.RB [ \-\-version]
32469.RI [ PhysicalVolume
32470.RI [ PhysicalVolume ...]]
32471.SH DESCRIPTION
32472pvs produces formatted output about physical volumes.
32473.SH OPTIONS
32474See \fBlvm\fP(8) for common options.
32475.TP
32476.B \-\-all
32477Include information in the output about devices that have not been
32478initialized with \fBpvcreate\fP(8).
32479.TP
32480.B \-\-aligned
32481Use with \fB\-\-separator\fP to align the output columns.
32482.TP
32483.B \-\-binary
32484Use binary values "0" or "1" instead of descriptive literal values
32485for columns that have exactly two valid values to report (not counting
32486the "unknown" value which denotes that the value could not be determined).
32487.TP
32488.B \-\-configreport \fI ReportName
32489Make any subsequent \fB\-o, \-\-options\fP, \fB\-O, \-\-sort\fP or
32490\fB\-S, \-\-select\fP to apply for \fIReportName\fP where \fIReportName\fP
32491is either 'pv' for command's main report or 'log' for log report.
32492If \fB\-\-configreport\fP option is not used to identify a report, then
32493command's main report is assumed. The log report is available only if
32494enabled by \fBlog/report_command_log\fP \fBlvm.conf\fP(5) setting or
32495if \fB\-\-logonly\fP option is used.
32496.TP
32497.B \-\-logonly
32498Suppress the pvs report itself and display only log report on output.
32499.TP
32500.B \-\-nameprefixes
32501Add an "LVM2_" prefix plus the field name to the output. Useful
32502with \fB\-\-noheadings\fP to produce a list of field=value pairs that can
32503be used to set environment variables (for example, in \fBudev\fP(7) rules).
32504.TP
32505.B \-\-noheadings
32506Suppress the headings line that is normally the first line of output.
32507Useful if grepping the output.
32508.TP
32509.B \-\-nosuffix
32510Suppress the suffix on output sizes. Use with \fB\-\-units\fP
32511(except h and H) if processing the output.
32512.TP
32513.BR \-o ", " \-\-options
32514Comma-separated ordered list of columns.
32515.IP
32516Precede the list with '\fI+\fP' to append to the current list
32517of columns, '\fI-\fP' to remove from the current list of columns
32518or '\fI#\fP' to compact given columns. The \fI\-o\fP option can
32519be repeated, providing several lists. These lists are evaluated
32520from left to right.
32521.IP
32522Use \fB-o pv_all\fP to select all physical volume columns,
32523and \fB-o pvseg_all\fP to select all Physical Volume segment columns.
32524.IP
32525Use \fB-o help\fP to view the full list of columns available.
32526.IP
32527Column names include: pv_fmt, pv_uuid, dev_size, pv_name, pv_mda_free,
32528pv_mda_size, pv_ba_start, pv_ba_size, pe_start, pv_size, pv_free, pv_used,
32529pv_attr, pv_pe_count, pv_pe_alloc_count, pv_tags, pv_mda_count,
32530pv_mda_used_count, pvseg_start, and pvseg_size
32531.IP
32532With \fB\-\-segments\fP, any "pvseg_" prefixes are optional; otherwise any
32533"pv_" prefixes are optional. Columns mentioned in \fBvgs\fP(8) can also
32534be chosen. The pv_attr bits are: (a)llocatable, e(x)ported, (m)issing,
32535(u)sed (but not allocatable), (d)uplicate.
32536.TP
32537.B \-\-segments
32538Produces one line of output for each contiguous allocation of space on each
32539Physical Volume, showing the start (pvseg_start) and length (pvseg_size) in
32540units of physical extents.
32541.TP
32542.BR \-S ", " \-\-select " " \fISelection
32543Display only rows that match Selection criteria. All rows are displayed with
32544the additional "selected" column (\fB-o selected\fP) showing 1 if the row
32545matches the Selection and 0 otherwise. The Selection criteria are defined
32546by specifying column names and their valid values (that can include reserved
32547values) while making use of supported comparison operators. See \fBlvm\fP(8)
32548and \fB\-S\fP, \fB\-\-select\fP description for more detailed information
32549about constructing the Selection criteria. As a quick help and to see full
32550list of column names that can be used in Selection including the list of
32551reserved values and the set of supported selection operators, check the
32552output of \fBpvs -S help\fP command.
32553.TP
32554.BR \-O ", " \-\-sort
32555Comma-separated ordered list of columns to sort by. Replaces the default
32556selection. Precede any column with '\fI\-\fP' for a reverse sort on that
32557column.
32558.TP
32559.B \-\-rows
32560Output columns as rows.
32561.TP
32562.B \-\-separator \fISeparator
32563String to use to separate each column. Useful if grepping the output.
32564.TP
32565.B \-\-unbuffered
32566Produce output immediately without sorting or aligning the columns properly.
32567.TP
32568.B \-\-units \fIhHbBsSkKmMgGtTpPeE
32569All sizes are output in these units: (h)uman-readable, (b)ytes, (s)ectors,
32570(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
32571Capitalise to use multiples of 1000 (S.I.) instead of 1024. Can also specify
32572custom units e.g. \-\-units 3M
32573.TP
32574.B \-\-unquoted
32575When used with \fB\-\-nameprefixes\fP, output values in the field=value
32576pairs are not quoted.
32577.SH SEE ALSO
32578.BR lvm (8),
32579.BR pvdisplay (8),
32580.BR lvs (8),
32581.BR vgs (8)
32582\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm.conf.5.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000017276\013062740170\0020054\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVM.CONF 5 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
32583.SH NAME
32584lvm.conf \(em Configuration file for LVM2
32585.SH SYNOPSIS
32586.B #DEFAULT_SYS_DIR#/lvm.conf
32587.SH DESCRIPTION
32588\fBlvm.conf\fP is loaded during the initialisation phase of
32589\fBlvm\fP(8). This file can in turn lead to other files
32590being loaded - settings read in later override earlier
32591settings. File timestamps are checked between commands and if
32592any have changed, all the files are reloaded.
32593
32594The settings defined in lvm.conf can be overridden by any
32595of these extended configuration methods:
32596.TP
32597.B direct config override on command line
32598The \fB\-\-config ConfigurationString\fP command line option takes the
32599ConfigurationString as direct string representation of the configuration
32600to override the existing configuration. The ConfigurationString is of
32601exactly the same format as used in any LVM configuration file.
32602
32603.TP
32604.B profile config
32605.br
32606A profile is a set of selected customizable configuration settings
32607that are aimed to achieve a certain characteristics in various
32608environments or uses. It's used to override existing configuration.
32609Normally, the name of the profile should reflect that environment or use.
32610
32611There are two groups of profiles recognised: \fBcommand profiles\fP and
32612\fBmetadata profiles\fP.
32613
32614The \fBcommand profile\fP is used to override selected configuration
32615settings at global LVM command level - it is applied at the very beginning
32616of LVM command execution and it is used throughout the whole time of LVM
32617command execution. The command profile is applied by using the
32618\fB\-\-commandprofile ProfileName\fP command line option that is recognised by
32619all LVM2 commands.
32620
32621The \fBmetadata profile\fP is used to override selected configuration
32622settings at Volume Group/Logical Volume level - it is applied independently
32623for each Volume Group/Logical Volume that is being processed. As such,
32624each Volume Group/Logical Volume can store the profile name used
32625in its metadata so next time the Volume Group/Logical Volume is
32626processed, the profile is applied automatically. If Volume Group and
32627any of its Logical Volumes have different profiles defined, the profile
32628defined for the Logical Volume is preferred. The metadata profile can be
32629attached/detached by using the \fBlvchange\fP and \fBvgchange\fP commands
32630and their \fB\-\-metadataprofile ProfileName\fP and
32631\fB\-\-detachprofile\fP options or the \fB\-\-metadataprofile\fP
32632option during creation when using \fBvgcreate\fP or \fBlvcreate\fP command.
32633The \fBvgs\fP and \fBlvs\fP reporting commands provide \fB-o vg_profile\fP
32634and \fB-o lv_profile\fP output options to show the metadata profile
32635currently attached to a Volume Group or a Logical Volume.
32636
32637The set of options allowed for command profiles is mutually exclusive
32638when compared to the set of options allowed for metadata profiles. The
32639settings that belong to either of these two sets can't be mixed together
32640and LVM tools will reject such profiles.
32641
32642LVM itself provides a few predefined configuration profiles.
32643Users are allowed to add more profiles with different values if needed.
32644For this purpose, there's the \fBcommand_profile_template.profile\fP
32645(for command profiles) and \fBmetadata_profile_template.profile\fP
32646(for metadata profiles) which contain all settings that are customizable
32647by profiles of certain type. Users are encouraged to copy these template
32648profiles and edit them as needed. Alternatively, the
32649\fBlvmconfig \-\-file <ProfileName.profile> \-\-type profilable-command <section>\fP
32650or \fBlvmconfig \-\-file <ProfileName.profile> \-\-type profilable-metadata <section>\fP
32651can be used to generate a configuration with profilable settings in either
32652of the type for given section and save it to new ProfileName.profile
32653(if the section is not specified, all profilable settings are reported).
32654
32655The profiles are stored in #DEFAULT_PROFILE_DIR# directory by default.
32656This location can be changed by using the \fBconfig/profile_dir\fP setting.
32657Each profile configuration is stored in \fBProfileName.profile\fP file
32658in the profile directory. When referencing the profile, the \fB.profile\fP
32659suffix is left out.
32660
32661.TP
32662.B tag config
32663.br
32664See \fBtags\fP configuration setting description below.
32665
32666.LP
32667When several configuration methods are used at the same time
32668and when LVM looks for the value of a particular setting, it traverses
32669this \fBconfig cascade\fP from left to right:
32670
32671\fBdirect config override on command line\fP -> \fBcommand profile config\fP -> \fBmetadata profile config\fP -> \fBtag config\fP -> \fBlvmlocal.conf\fB -> \fBlvm.conf\fP
32672
32673No part of this cascade is compulsory. If there's no setting value found at
32674the end of the cascade, a default value is used for that setting.
32675Use \fBlvmconfig\fP to check what settings are in use and what
32676the default values are.
32677.SH SYNTAX
32678.LP
32679This section describes the configuration file syntax.
32680.LP
32681Whitespace is not significant unless it is within quotes.
32682This provides a wide choice of acceptable indentation styles.
32683Comments begin with # and continue to the end of the line.
32684They are treated as whitespace.
32685.LP
32686Here is an informal grammar:
32687.TP
32688.BR file " = " value *
32689.br
32690A configuration file consists of a set of values.
32691.TP
32692.BR value " = " section " | " assignment
32693.br
32694A value can either be a new section, or an assignment.
32695.TP
32696.BR section " = " identifier " '" { "' " value "* '" } '
32697.br
32698A section groups associated values together. If the same section is
32699encountered multiple times, the contents of all instances are concatenated
32700together in the order of appearance.
32701.br
32702It is denoted by a name and delimited by curly brackets.
32703.br
32704e.g. backup {
32705.br
32706 ...
32707.br
32708 }
32709.TP
32710.BR assignment " = " identifier " '" = "' ( " array " | " type " )"
32711.br
32712An assignment associates a type with an identifier. If the identifier contains
32713forward slashes, those are interpreted as path delimiters. The statement
32714\fBsection/key = value\fP is equivalent to \fBsection { key = value }\fP. If
32715multiple instances of the same key are encountered, only the last value is used
32716(and a warning is issued).
32717.br
32718e.g. \fBlevel = 7\fP
32719.br
32720.TP
32721.BR array " = '" [ "' ( " type " '" , "')* " type " '" ] "' | '" [ "' '" ] '
32722.br
32723Inhomogeneous arrays are supported.
32724.br
32725Elements must be separated by commas.
32726.br
32727An empty array is acceptable.
32728.TP
32729.BR type " = " integer " | " float " | " string
32730.BR integer " = [0-9]*"
32731.br
32732.BR float " = [0-9]*'" . '[0-9]*
32733.br
32734.B string \fR= '\fB"\fR'.*'\fB"\fR'
32735.IP
32736Strings with spaces must be enclosed in double quotes, single words that start
32737with a letter can be left unquoted.
32738
32739.SH SETTINGS
32740
32741The
32742.B lvmconfig
32743command prints the LVM configuration settings in various ways.
32744See the man page
32745.BR lvmconfig (8).
32746
32747Command to print a list of all possible config settings, with their
32748default values:
32749.br
32750.B lvmconfig \-\-type default
32751
32752Command to print a list of all possible config settings, with their
32753default values, and a full description of each as a comment:
32754.br
32755.B lvmconfig \-\-type default --withcomments
32756
32757Command to print a list of all possible config settings, with their
32758current values (configured, non-default values are shown):
32759.br
32760.B lvmconfig \-\-type current
32761
32762Command to print all config settings that have been configured with a
32763different value than the default (configured, non-default values are
32764shown):
32765.br
32766.B lvmconfig \-\-type diff
32767
32768Command to print a single config setting, with its default value,
32769and a full description, where "Section" refers to the config section,
32770e.g. global, and "Setting" refers to the name of the specific setting,
32771e.g. umask:
32772.br
32773.B lvmconfig \-\-type default --withcomments Section/Setting
32774
32775
32776.SH FILES
32777.I #DEFAULT_SYS_DIR#/lvm.conf
32778.br
32779.I #DEFAULT_SYS_DIR#/lvmlocal.conf
32780.br
32781.I #DEFAULT_ARCHIVE_DIR#
32782.br
32783.I #DEFAULT_BACKUP_DIR#
32784.br
32785.I #DEFAULT_CACHE_DIR#/.cache
32786.br
32787.I #DEFAULT_LOCK_DIR#
32788.br
32789.I #DEFAULT_PROFILE_DIR#
32790
32791.SH SEE ALSO
32792.BR lvm (8)
32793.BR lvmconfig (8)
32794
32795\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvscan.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012454\013062740170\0017620\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
32796.SH NAME
32797pvscan \(em scan all disks for physical volumes
32798
32799.SH SYNOPSIS
32800.B pvscan
32801.RB [ \-\-commandprofile
32802.IR ProfileName ]
32803.RB [ \-d | \-\-debug ]
32804.RB [ \-h | \-\-help ]
32805.RB [ \-v | \-\-verbose ]
32806.RB [ \-\-version ]
32807.RB [ \-\-ignorelockingfailure ]
32808.RB [ \-e | \-\-exported ]
32809.RB [ \-n | \-\-novolumegroup ]
32810.RB [ \-\-reportformat
32811.RB { basic | json }]
32812.RB [ \-s | \-\-short ]
32813.RB [ \-u | \-\-uuid ]
32814.BR
32815
32816.B pvscan
32817.RB [ \-d | \-\-debug ]
32818.RB [ \-h | \-\-help ]
32819.B \-\-cache
32820.RB [ \-a | \-\-activate " " \fIay ]
32821.RB [ \-b | \-\-background ]
32822.RB [ \-\-reportformat
32823.RB { basic | json }]
32824.RB [ \-\-major
32825.I major
32826.B \-\-minor
32827.I minor
32828|
32829.IR DevicePath
32830|
32831.IR major:minor ]...
32832
32833.SH DESCRIPTION
32834pvscan scans all supported LVM block devices in the system for physical
32835volumes.
32836
32837.SS Scanning with lvmetad
32838
32839pvscan operates differently when used with the
32840.BR lvmetad (8)
32841daemon.
32842
32843Scanning disks is required to read LVM metadata and identify LVM PVs.
32844Once read, lvmetad caches the metadata so that LVM commands can read it
32845without repeatedly scanning disks. This is helpful because scanning disks
32846is time consuming, and frequent scanning may interfere with the normal
32847work of the system and disks.
32848
32849When lvmetad is not used, LVM commands revert to scanning disks to read
32850metadata. Any LVM command that needs metadata will scan disks for it;
32851running the pvscan command is not necessary for the sake of other LVM
32852commands.
32853
32854When lvmetad is used, LVM commands avoid scanning disks by reading
32855metadata from lvmetad. When new disks appear, they must be scanned so
32856their metadata can be cached in lvmetad. This is done by the command
32857pvscan \-\-cache, which scans disks and passes the metadata to lvmetad.
32858
32859The pvscan \-\-cache command is typically run automatically by system
32860services when a new device appears. Users do not generally need to run
32861this command if the system and lvmetad are running properly.
32862
32863Many scripts contain unnecessary pvscan (or vgscan) commands for
32864historical reasons. To avoid disrupting the system with extraneous disk
32865scanning, an ordinary pvscan (without \-\-cache) will simply read metadata
32866from lvmetad like other LVM commands. It does not do anything beyond
32867displaying the current state of the cache.
32868
32869.I Notes
32870
32871.IP \[bu] 2
32872When given specific device name arguments, pvscan \-\-cache will only
32873read the named devices.
32874
32875.IP \[bu] 2
32876LVM udev rules and systemd services are used to initiate automatic device
32877scanning.
32878
32879.IP \[bu] 2
32880To prevent devices from being scanned by pvscan --cache, add them
32881to
32882.BR lvm.conf (5)
32883.B devices/global_filter.
32884The devices/filter setting does not
32885apply to system level scanning.
32886For more information, see:
32887.br
32888.B lvmconfig --withcomments devices/global_filter
32889
32890.IP \[bu] 2
32891If lvmetad is started or restarted after devices are visible, or
32892if the global_filter has changed, then all devices must be rescanned
32893for metadata with the command pvscan \-\-cache.
32894
32895.IP \[bu] 2
32896lvmetad does not cache older metadata formats, e.g. lvm1, and will
32897be temporarily disabled if they are seen.
32898
32899.IP \[bu] 2
32900To notify lvmetad about a device that is no longer present, the major and
32901minor numbers must be given, not the path.
32902
32903.SS Automatic activation
32904
32905When event-driven system services detect a new LVM device, the first step
32906is to automatically scan and cache the metadata from the device. This is
32907done by pvscan \-\-cache. A second step is to automatically activate LVs
32908that are present on the new device. This auto-activation is done by the
32909same pvscan \-\-cache command when the option '\-a|\-\-activate ay' is
32910included.
32911
32912Auto-activation of VGs or LVs can be enabled/disabled using:
32913.br
32914.BR lvm.conf (5)
32915.B activation/auto_activation_volume_list
32916
32917For more information, see:
32918.br
32919.B lvmconfig --withcomments activation/auto_activation_volume_list
32920
32921When this setting is undefined, all LVs are auto-activated (when lvm is
32922fully integrated with the event-driven system services.)
32923
32924When a VG or LV is not auto-activated, traditional activation using
32925vgchange or lvchange -a|--activate is needed.
32926
32927.I Notes
32928
32929.IP \[bu] 2
32930pvscan auto-activation can be only done in combination with \-\-cache.
32931
32932.IP \[bu] 2
32933Auto-activation is designated by the "a" argument in '-a|--activate ay'.
32934This is meant to distinguish system generated commands from explicit user
32935commands, although it can be used in any activation command. Whenever it
32936is used, the auto_activation_volume_list is applied.
32937
32938.IP \[bu] 2
32939Auto-activation is not yet supported for LVs that are part of partial or
32940clustered volume groups.
32941
32942.P
32943
32944.SH OPTIONS
32945See \fBlvm\fP(8) for common options.
32946.TP
32947.BR \-e ", " \-\-exported
32948Only show physical volumes belonging to exported volume groups.
32949.TP
32950.BR \-n ", " \-\-novolumegroup
32951Only show physical volumes not belonging to any volume group.
32952.TP
32953.BR \-s ", " \-\-short
32954Short listing format.
32955.TP
32956.BR \-u ", " \-\-uuid
32957Show UUIDs in addition to device names.
32958.TP
32959.BR \-a ", " \-\-activate " " \fIay
32960Automatically activate any logical volumes that are possible to activate
32961with the addition of the new devices.
32962.TP
32963.BR \-b ", " \-\-background
32964Run the command in the background.
32965.TP
32966.BR \-\-cache " [" \-\-major " " \fImajor " " \-\-minor " " \fIminor " | " \fIDevicePath " | " \fImajor:minor " ]..."
32967Scan one or more devices and send the metadata to lvmetad.
32968
32969.SH SEE ALSO
32970.BR lvm (8),
32971.BR lvmconfig (8),
32972.BR lvmetad (8)
32973\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm2-activation-generator.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004417\013062740170\0023331\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVM2-ACTIVATION-GENERATOR" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
32974.SH "NAME"
32975lvm2-activation-generator \- generator for systemd units to activate LVM2 volumes on boot
32976.SH SYNOPSIS
32977.B #SYSTEMD_GENERATOR_DIR#/lvm2-activation-generator
32978.sp
32979.SH DESCRIPTION
32980The lvm2-activation-generator is called by \fBsystemd\fP(1) on boot
32981to generate systemd units at runtime to activate LVM2 volumes if
32982\fBlvmetad\fP(8) is disabled (global/use_lvmetad=0 \fBlvm.conf\fP(5)
32983option is used). Otherwise, if \fBlvmetad\fP(8) is enabled,
32984the lvm2-activation-generator exits immediately without generating
32985any systemd units and LVM2 fully relies on event-based activation
32986to activate the LVM2 volumes instead using the \fBpvscan\fP(8)
32987(pvscan \-\-cache -aay) call that is a part of \fBudev\fP(8) rules.
32988
32989These systemd units are generated by lvm2-activation-generator:
32990.sp
32991\fIlvm2-activation-early.service\fP
32992used for activation of LVM2 volumes that is ordered before systemd's
32993special \fBcryptsetup.target\fP to support LVM2 volumes which are not
32994layered on top of encrypted devices.
32995
32996\fIlvm2-activation.service\fP
32997used for activation of LVM2 volumes that is ordered after systemd's
32998special \fBcryptsetup.target\fP to support LVM2 volumes which are
32999layered on top of encrypted devices.
33000
33001\fIlvm2-activation-net.service\fP
33002used for activation of LVM2 volumes that is ordered after systemd's
33003special \fBremote-fs-pre.target\fP to support LVM2 volumes which are
33004layered on attached remote devices.
33005
33006Note that all the underlying devices (Physical Volumes) need to be present
33007when the service is run. If the there are any devices presented in the system
33008anytime later, any LVM2 volumes on top of such devices need to be activated
33009directly by \fBlvchange\fP(8) or \fBvgchange\fP(8). This limitation does
33010not exist when using \fBlvmetad\fP(8) and accompanying event-based activation
33011since such LVM volumes are activated automatically as soon as the Volume Group
33012is ready (all the Physical Volumes making up the Volume Group are present
33013in the system).
33014
33015The lvm2-activation-generator implements the \fBGenerators Specification\fP
33016as referenced in \fBsystemd\fP(1).
33017.sp
33018.SH SEE ALSO
33019.BR lvm.conf (5)
33020.BR vgchange (8)
33021.BR lvchange (8)
33022.BR lvmetad (8)
33023.BR pvscan (8)
33024.BR udev (7)
33025.BR systemd (1)
33026.BR systemd.target (5)
33027.BR systemd.special (7)
33028\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/dmsetup.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000056230\013062740170\0020007\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH DMSETUP 8 "Apr 06 2006" "Linux" "MAINTENANCE COMMANDS"
33029.
33030.SH NAME
33031.
33032dmsetup \(em low level logical volume management
33033.
33034.SH SYNOPSIS
33035.
33036.\".nh
33037.ad l
33038.PD 0
33039.HP 9
33040.B dmsetup
33041.de CMD_CLEAR
33042. BR clear
33043. IR device_name
33044..
33045.CMD_CLEAR
33046.
33047.HP
33048.B dmsetup
33049.de CMD_CREATE
33050. ad l
33051. BR create
33052. IR device_name
33053. RB [ -u | \-\-uuid
33054. IR uuid ]
33055. RB \%[ \-\-addnodeoncreate | \-\-addnodeonresume ]
33056. RB \%[ \-n | \-\-notable | \-\-table
33057. RI \%{ table | table_file }]
33058. RB [ \-\-readahead
33059. RB \%{[ + ] \fIsectors | auto | none }]
33060. ad b
33061..
33062.CMD_CREATE
33063.
33064.HP
33065.B dmsetup
33066.de CMD_DEPS
33067. ad l
33068. BR deps
33069. RB [ \-o
33070. IR options ]
33071. RI [ device_name ]
33072. ad b
33073..
33074.CMD_DEPS
33075.
33076.HP
33077.B dmsetup
33078.de CMD_HELP
33079. BR help
33080. RB [ \-c | \-C | \-\-columns ]
33081..
33082.CMD_HELP
33083.
33084.HP
33085.B dmsetup
33086.de CMD_INFO
33087. BR info
33088. RI [ device_name ]
33089..
33090.CMD_INFO
33091.
33092.HP
33093.B dmsetup
33094.de CMD_INFOLONG
33095. ad l
33096. BR info
33097. BR \-c | \-C | \-\-columns
33098. RB [ \-\-count
33099. IR count ]
33100. RB [ \-\-interval
33101. IR seconds ]
33102. RB \%[ \-\-nameprefixes ]
33103. RB \%[ \-\-noheadings ]
33104. RB [ \-o
33105. IR fields ]
33106. RB [ \-O | \-\-sort
33107. IR sort_fields ]
33108. RB [ \-\-separator
33109. IR separator ]
33110. RI [ device_name ]
33111. ad b
33112..
33113.CMD_INFOLONG
33114.
33115.HP
33116.B dmsetup
33117.de CMD_LOAD
33118. ad l
33119. BR load
33120. IR device_name
33121. RB [ \-\-table
33122. RI { table | table_file }]
33123. ad b
33124..
33125.CMD_LOAD
33126.
33127.HP
33128.B dmsetup
33129.de CMD_LS
33130. ad l
33131. BR ls
33132. RB [ \-\-target
33133. IR target_type ]
33134. RB [ \-\-exec
33135. IR command ]
33136. RB [ \-\-tree ]
33137. RB [ \-o
33138. IR options ]
33139. ad b
33140..
33141.CMD_LS
33142.
33143.HP
33144.B dmsetup
33145.de CMD_MANGLE
33146. BR mangle
33147. RI [ device_name ]
33148..
33149.CMD_MANGLE
33150.
33151.HP
33152.B dmsetup
33153.de CMD_MESSAGE
33154. BR message
33155. IR device_name
33156. IR sector
33157. IR message
33158..
33159.CMD_MESSAGE
33160.
33161.HP
33162.B dmsetup
33163.de CMD_MKNODES
33164. BR mknodes
33165. RI [ device_name ]
33166..
33167.CMD_MKNODES
33168.
33169.HP
33170.B dmsetup
33171.de CMD_RELOAD
33172. ad l
33173. BR reload
33174. IR device_name
33175. RB [ \-\-table
33176. RI { table | table_file }]
33177. ad b
33178..
33179.CMD_RELOAD
33180.
33181.HP
33182.B dmsetup
33183.de CMD_REMOVE
33184. ad l
33185. BR remove
33186. RB [ \-f | \-\-force ]
33187. RB [ \-\-retry ]
33188. RB [ \-\-deferred ]
33189. IR device_name
33190. ad b
33191..
33192.CMD_REMOVE
33193.
33194.HP
33195.B dmsetup
33196.de CMD_REMOVE_ALL
33197. BR remove_all
33198. RB [ \-f | \-\-force ]
33199. RB [ \-\-deferred ]
33200..
33201.CMD_REMOVE_ALL
33202.
33203.HP
33204.B dmsetup
33205.de CMD_RENAME
33206. BR rename
33207. IR device_name
33208. IR new_name
33209..
33210.CMD_RENAME
33211.
33212.HP
33213.B dmsetup
33214.de CMD_RENAME_UUID
33215. BR rename
33216. IR device_name
33217. BR \-\-setuuid
33218. IR uuid
33219..
33220.CMD_RENAME_UUID
33221.
33222.HP
33223.B dmsetup
33224.de CMD_RESUME
33225. ad l
33226. BR resume
33227. IR device_name
33228. RB [ \-\-addnodeoncreate | \-\-addnodeonresume ]
33229. RB [ \-\-noflush ]
33230. RB [ \-\-nolockfs ]
33231. RB \%[ \-\-readahead
33232. RB \%{[ + ] \fIsectors | auto | none }]
33233. ad b
33234..
33235.CMD_RESUME
33236.
33237.HP
33238.B dmsetup
33239.de CMD_SETGEOMETRY
33240. ad l
33241. BR setgeometry
33242. IR device_name
33243. IR cyl
33244. IR head
33245. IR sect
33246. IR start
33247. ad b
33248..
33249.CMD_SETGEOMETRY
33250.
33251.HP
33252.B dmsetup
33253.de CMD_SPLITNAME
33254. BR splitname
33255. IR device_name
33256. RI [ subsystem ]
33257..
33258.CMD_SPLITNAME
33259.
33260.HP
33261.B dmsetup
33262.de CMD_STATS
33263. BR stats
33264. IR command
33265. RI [ options ]
33266..
33267.CMD_STATS
33268.
33269.HP
33270.B dmsetup
33271.de CMD_STATUS
33272. ad l
33273. BR status
33274. RB [ \-\-target
33275. IR target_type ]
33276. RB [ \-\-noflush ]
33277. RI [ device_name ]
33278. ad b
33279..
33280.CMD_STATUS
33281.
33282.HP
33283.B dmsetup
33284.de CMD_SUSPEND
33285. ad l
33286. BR suspend
33287. RB [ \-\-nolockfs ]
33288. RB [ \-\-noflush ]
33289. IR device_name
33290. ad b
33291..
33292.CMD_SUSPEND
33293.
33294.HP
33295.B dmsetup
33296.de CMD_TABLE
33297. ad l
33298. BR table
33299. RB [ \-\-target
33300. IR target_type ]
33301. RB [ \-\-showkeys ]
33302. RI [ device_name ]
33303. ad b
33304..
33305.CMD_TABLE
33306.
33307.HP
33308.B dmsetup
33309.de CMD_TARGETS
33310. BR targets
33311..
33312.CMD_TARGETS
33313.
33314.HP
33315.B dmsetup
33316.de CMD_UDEVCOMPLETE
33317. BR udevcomplete
33318. IR cookie
33319..
33320.CMD_UDEVCOMPLETE
33321.
33322.HP
33323.B dmsetup
33324.de CMD_UDEVCOMPLETE_ALL
33325. BR udevcomplete_all
33326. RI [ age_in_minutes ]
33327..
33328.CMD_UDEVCOMPLETE_ALL
33329.
33330.HP
33331.B dmsetup
33332.de CMD_UDEVCOOKIES
33333. BR udevcookie
33334..
33335.CMD_UDEVCOOKIES
33336.
33337.HP
33338.B dmsetup
33339.de CMD_UDEVCREATECOOKIE
33340. BR udevcreatecookie
33341..
33342.CMD_UDEVCREATECOOKIE
33343.
33344.HP
33345.B dmsetup
33346.de CMD_UDEVFLAGS
33347. BR udevflags
33348. IR cookie
33349..
33350.CMD_UDEVFLAGS
33351.
33352.HP
33353.B dmsetup
33354.de CMD_UDEVRELEASECOOKIE
33355. BR udevreleasecookie
33356. RI [ cookie ]
33357..
33358.CMD_UDEVRELEASECOOKIE
33359.
33360.HP
33361.B dmsetup
33362.de CMD_VERSION
33363. BR version
33364..
33365.CMD_VERSION
33366.
33367.HP
33368.B dmsetup
33369.de CMD_WAIT
33370. ad l
33371. BR wait
33372. RB [ \-\-noflush ]
33373. IR device_name
33374. RI [ event_nr ]
33375. ad b
33376..
33377.CMD_WAIT
33378.
33379.HP
33380.B dmsetup
33381.de CMD_WIPE_TABLE
33382. ad l
33383. BR wipe_table
33384. IR device_name
33385. RB [ \-f | \-\-force ]
33386. RB [ \-\-noflush ]
33387. RB [ \-\-nolockfs ]
33388. ad b
33389..
33390.CMD_WIPE_TABLE
33391.PD
33392.P
33393.HP
33394.PD 0
33395.B devmap_name \fImajor minor
33396.HP
33397.B devmap_name \fImajor:minor
33398.PD
33399.ad b
33400.
33401.SH DESCRIPTION
33402.
33403dmsetup manages logical devices that use the device-mapper driver.
33404Devices are created by loading a table that specifies a target for
33405each sector (512 bytes) in the logical device.
33406
33407The first argument to dmsetup is a command.
33408The second argument is the logical device name or uuid.
33409
33410Invoking the dmsetup tool as \fBdevmap_name\fP
33411(which is not normally distributed and is supported
33412only for historical reasons) is equivalent to
33413.BI \%dmsetup\ info\ \-c\ \-\-noheadings\ \-j \ major\ \-m \ minor \c
33414\fR.
33415.\" dot above here fixes -Thtml rendering for next HP option
33416.
33417.SH OPTIONS
33418.
33419.HP
33420.BR \-\-addnodeoncreate
33421.br
33422Ensure \fI/dev/mapper\fP node exists after \fBdmsetup create\fP.
33423.
33424.HP
33425.BR \-\-addnodeonresume
33426.br
33427Ensure \fI/dev/mapper\fP node exists after \fBdmsetup resume\fP (default with udev).
33428.
33429.HP
33430.BR \-\-checks
33431.br
33432Perform additional checks on the operations requested and report
33433potential problems. Useful when debugging scripts.
33434In some cases these checks may slow down operations noticeably.
33435.
33436.HP
33437.BR \-c | \-C | \-\-columns
33438.br
33439Display output in columns rather than as Field: Value lines.
33440.
33441.HP
33442.BR \-\-count
33443.IR count
33444.br
33445Specify the number of times to repeat a report. Set this to zero
33446continue until interrupted. The default interval is one second.
33447.
33448.HP
33449.BR \-f | \-\-force
33450.br
33451Try harder to complete operation.
33452.
33453.HP
33454.BR \-h | \-\-help
33455.br
33456Outputs a summary of the commands available, optionally including
33457the list of report fields (synonym with \fBhelp\fP command).
33458.
33459.HP
33460.BR \-\-inactive
33461.br
33462When returning any table information from the kernel report on the
33463inactive table instead of the live table.
33464Requires kernel driver version 4.16.0 or above.
33465.
33466.HP
33467.BR \-\-interval
33468.IR seconds
33469.br
33470Specify the interval in seconds between successive iterations for
33471repeating reports. If \fB\-\-interval\fP is specified but \fB\-\-count\fP
33472is not, reports will continue to repeat until interrupted.
33473The default interval is one second.
33474.
33475.HP
33476.BR \-\-manglename
33477.RB { auto | hex | none }
33478.br
33479Mangle any character not on a whitelist using mangling_mode when
33480processing device-mapper device names and UUIDs. The names and UUIDs
33481are mangled on input and unmangled on output where the mangling mode
33482is one of:
33483\fBauto\fP (only do the mangling if not mangled yet, do nothing
33484if already mangled, error on mixed),
33485\fBhex\fP (always do the mangling) and
33486\fBnone\fP (no mangling).
33487Default mode is \fB#DEFAULT_MANGLING#\fP.
33488Character whitelist: 0-9, A-Z, a-z, #+-.:=@_. This whitelist is
33489also supported by udev. Any character not on a whitelist is replaced
33490with its hex value (two digits) prefixed by \\x.
33491Mangling mode could be also set through
33492\fBDM_DEFAULT_NAME_MANGLING_MODE\fP
33493environment variable.
33494.
33495.HP
33496.BR \-j | \-\-major
33497.IR major
33498.br
33499Specify the major number.
33500.
33501.HP
33502.BR \-m | \-\-minor
33503.IR minor
33504.br
33505Specify the minor number.
33506.
33507.HP
33508.BR \-n | \-\-notable
33509.br
33510When creating a device, don't load any table.
33511.
33512.HP
33513.BR \-\-nameprefixes
33514.br
33515Add a "DM_" prefix plus the field name to the output. Useful with
33516\fB\-\-noheadings\fP to produce a list of
33517field=value pairs that can be used to set environment variables
33518(for example, in
33519.BR udev (7)
33520rules).
33521.
33522.HP
33523.BR \-\-noheadings
33524Suppress the headings line when using columnar output.
33525.
33526.HP
33527.BR \-\-noflush
33528Do not flush outstading I/O when suspending a device, or do not
33529commit thin-pool metadata when obtaining thin-pool status.
33530.
33531.HP
33532.BR \-\-nolockfs
33533.br
33534Do not attempt to synchronize filesystem eg, when suspending a device.
33535.
33536.HP
33537.BR \-\-noopencount
33538.br
33539Tell the kernel not to supply the open reference count for the device.
33540.
33541.HP
33542.BR \-\-noudevrules
33543.br
33544Do not allow udev to manage nodes for devices in device-mapper directory.
33545.
33546.HP
33547.BR \-\-noudevsync
33548.br
33549Do not synchronise with udev when creating, renaming or removing devices.
33550.
33551.HP
33552.BR \-o | \-\-options
33553.IR options
33554.br
33555Specify which fields to display.
33556.
33557.HP
33558.BR \-\-readahead
33559.RB {[ + ] \fIsectors | auto | none }
33560.br
33561Specify read ahead size in units of sectors.
33562The default value is \fBauto\fP which allows the kernel to choose
33563a suitable value automatically. The \fB+\fP prefix lets you
33564specify a minimum value which will not be used if it is
33565smaller than the value chosen by the kernel.
33566The value \fBnone\fP is equivalent to specifying zero.
33567.
33568.HP
33569.BR \-r | \-\-readonly
33570.br
33571Set the table being loaded read-only.
33572.
33573.HP
33574.BR \-S | \-\-select
33575.IR selection
33576.br
33577Display only rows that match \fIselection\fP criteria. All rows are displayed
33578with the additional "selected" column (\fB-o selected\fP) showing 1 if the row
33579matches the \fIselection\fP and 0 otherwise. The selection criteria are defined
33580by specifying column names and their valid values while making use of
33581supported comparison operators. As a quick help and to see full list of
33582column names that can be used in selection and the set of supported
33583selection operators, check the output of \fBdmsetup\ info\ -c\ -S\ help\fP
33584command.
33585.
33586.HP
33587.BR \-\-table
33588.IR table
33589.br
33590Specify a one-line table directly on the command line.
33591See below for more information on the table format.
33592.
33593.HP
33594.BR \-\-udevcookie
33595.IR cookie
33596.br
33597Use cookie for udev synchronisation.
33598Note: Same cookie should be used for same type of operations i.e. creation of
33599multiple different devices. It's not adviced to combine different
33600operations on the single device.
33601.
33602.HP
33603.BR \-u | \-\-uuid
33604.br
33605Specify the \fIuuid\fP.
33606.
33607.HP
33608.BR \-y | \-\-yes
33609.br
33610Answer yes to all prompts automatically.
33611.
33612.HP
33613.BR \-v | \-\-verbose
33614.RB [ \-v | \-\-verbose ]
33615.br
33616Produce additional output.
33617.
33618.HP
33619.BR \-\-verifyudev
33620.br
33621If udev synchronisation is enabled, verify that udev operations get performed
33622correctly and try to fix up the device nodes afterwards if not.
33623.
33624.HP
33625.BR \-\-version
33626.br
33627Display the library and kernel driver version.
33628.br
33629.
33630.SH COMMANDS
33631.
33632.HP
33633.CMD_CLEAR
33634.br
33635Destroys the table in the inactive table slot for device_name.
33636.
33637.HP
33638.CMD_CREATE
33639.br
33640Creates a device with the given name.
33641If \fItable\fP or \fItable_file\fP is supplied, the table is loaded and made live.
33642Otherwise a table is read from standard input unless \fB\-\-notable\fP is used.
33643The optional \fIuuid\fP can be used in place of
33644device_name in subsequent dmsetup commands.
33645If successful the device will appear in table and for live
33646device the node \fI/dev/mapper/device_name\fP is created.
33647See below for more information on the table format.
33648.
33649.HP
33650.CMD_DEPS
33651.br
33652Outputs a list of devices referenced by the live table for the specified
33653device. Device names on output can be customised by following \fIoptions\fP:
33654\fBdevno\fP (major and minor pair, used by default),
33655\fBblkdevname\fP (block device name),
33656\fBdevname\fP (map name for device-mapper devices, equal to blkdevname otherwise).
33657.
33658.HP
33659.CMD_HELP
33660.br
33661Outputs a summary of the commands available, optionally including
33662the list of report fields.
33663.
33664.HP
33665.CMD_INFO
33666.br
33667Outputs some brief information about the device in the form:
33668.RS
33669.RS
33670 State: SUSPENDED|ACTIVE, READ-ONLY
33671 Tables present: LIVE and/or INACTIVE
33672 Open reference count
33673 Last event sequence number (used by \fBwait\fP)
33674 Major and minor device number
33675 Number of targets in the live table
33676 UUID
33677.RE
33678.RE
33679.HP
33680.CMD_INFOLONG
33681.br
33682Output you can customise.
33683Fields are comma-separated and chosen from the following list:
33684.BR name ,
33685.BR major ,
33686.BR minor ,
33687.BR attr ,
33688.BR open ,
33689.BR segments ,
33690.BR events ,
33691.BR uuid .
33692Attributes are:
33693.RI ( L )ive,
33694.RI ( I )nactive,
33695.RI ( s )uspended,
33696.RI ( r )ead-only,
33697.RI read-( w )rite.
33698Precede the list with '\fB+\fP' to append
33699to the default selection of columns instead of replacing it.
33700Precede any sort field with '\fB-\fP' for a reverse sort on that column.
33701.
33702.HP
33703.CMD_LS
33704.br
33705List device names. Optionally only list devices that have at least
33706one target of the specified type. Optionally execute a command for
33707each device. The device name is appended to the supplied command.
33708Device names on output can be customised by following options:
33709\fBdevno\fP (major and minor pair, used by default),
33710\fBblkdevname\fP (block device name),
33711\fBdevname\fP (map name for device-mapper devices, equal to blkdevname otherwise).
33712\fB\-\-tree\fP displays dependencies between devices as a tree.
33713It accepts a comma-separate list of \fIoptions\fP.
33714Some specify the information displayed against each node:
33715.BR device / nodevice ;
33716.BR blkdevname ;
33717.BR active ", " open ", " rw ", " uuid .
33718Others specify how the tree is displayed:
33719.BR ascii ", " utf ", " vt100 ;
33720.BR compact ", " inverted ", " notrunc .
33721.
33722.HP
33723.BR load | \c
33724.CMD_RELOAD
33725.br
33726Loads \fItable\fP or \fItable_file\fP into the inactive table slot for device_name.
33727If neither is supplied, reads a table from standard input.
33728.
33729.HP
33730.CMD_MANGLE
33731.br
33732Ensure existing device-mapper \fIdevice_name\fP and UUID is in the correct mangled
33733form containing only whitelisted characters (supported by udev) and do
33734a rename if necessary. Any character not on the whitelist will be mangled
33735based on the \fB\-\-manglename\fP setting. Automatic rename works only for device
33736names and not for device UUIDs because the kernel does not allow changing
33737the UUID of active devices. Any incorrect UUIDs are reported only and they
33738must be manually corrected by deactivating the device first and then
33739reactivating it with proper mangling mode used (see also \fB\-\-manglename\fP).
33740.
33741.HP
33742.CMD_MESSAGE
33743.br
33744Send message to target. If sector not needed use 0.
33745.
33746.HP
33747.CMD_MKNODES
33748.br
33749Ensure that the node in \fI/dev/mapper\fP for \fIdevice_name\fP is correct.
33750If no device_name is supplied, ensure that all nodes in \fI/dev/mapper\fP
33751correspond to mapped devices currently loaded by the device-mapper kernel
33752driver, adding, changing or removing nodes as necessary.
33753.
33754.HP
33755.CMD_REMOVE
33756.br
33757Removes a device. It will no longer be visible to dmsetup. Open devices
33758cannot be removed, but adding \fB\-\-force\fP will replace the table with one
33759that fails all I/O. \fB\-\-deferred\fP will enable deferred removal of open
33760devices - the device will be removed when the last user closes it. The deferred
33761removal feature is supported since version 4.27.0 of the device-mapper
33762driver available in upstream kernel version 3.13. (Use \fBdmsetup version\fP
33763to check this.) If an attempt to remove a device fails, perhaps because a process run
33764from a quick udev rule temporarily opened the device, the \fB\-\-retry\fP
33765option will cause the operation to be retried for a few seconds before failing.
33766Do NOT combine
33767\fB\-\-force\fP and \fB\-\-udevcookie\fP, as udev may start to process udev
33768rules in the middle of error target replacement and result in nondeterministic
33769result.
33770.
33771.HP
33772.CMD_REMOVE_ALL
33773.br
33774Attempts to remove all device definitions i.e. reset the driver. This also runs
33775\fBmknodes\fP afterwards. Use with care! Open devices cannot be removed, but
33776adding \fB\-\-force\fP will replace the table with one that fails all I/O.
33777\fB\-\-deferred\fP will enable deferred removal of open devices - the device
33778will be removed when the last user closes it. The deferred removal feature is
33779supported since version 4.27.0 of the device-mapper driver available in
33780upstream kernel version 3.13.
33781.
33782.HP
33783.CMD_RENAME
33784.br
33785Renames a device.
33786.
33787.HP
33788.CMD_RENAME_UUID
33789.br
33790Sets the uuid of a device that was created without a uuid.
33791After a uuid has been set it cannot be changed.
33792.
33793.HP
33794.CMD_RESUME
33795.br
33796Un-suspends a device.
33797If an inactive table has been loaded, it becomes live.
33798Postponed I/O then gets re-queued for processing.
33799.
33800.HP
33801.CMD_SETGEOMETRY
33802.br
33803Sets the device geometry to C/H/S.
33804.
33805.HP
33806.CMD_SPLITNAME
33807.br
33808Splits given \fIdevice name\fP into \fIsubsystem\fP constituents.
33809The default subsystem is LVM.
33810LVM currently generates device names by concatenating the names of the Volume
33811Group, Logical Volume and any internal Layer with a hyphen as separator.
33812Any hyphens within the names are doubled to escape them.
33813The precise encoding might change without notice in any future
33814release, so we recommend you always decode using the current version of
33815this command.
33816.HP
33817.CMD_STATS
33818.br
33819Manages IO statistics regions for devices.
33820See
33821.BR dmstats (8)
33822for more details.
33823.HP
33824.CMD_STATUS
33825.br
33826Outputs status information for each of the device's targets.
33827With \fB\-\-target\fP, only information relating to the specified target type
33828any is displayed. With \fB\-\-noflush\fP, the thin target (from version 1.3.0)
33829doesn't commit any outstanding changes to disk before reporting its statistics.
33830
33831.HP
33832.CMD_SUSPEND
33833.br
33834Suspends a device. Any I/O that has already been mapped by the device
33835but has not yet completed will be flushed. Any further I/O to that
33836device will be postponed for as long as the device is suspended.
33837If there's a filesystem on the device which supports the operation,
33838an attempt will be made to sync it first unless \fB\-\-nolockfs\fP is specified.
33839Some targets such as recent (October 2006) versions of multipath may support
33840the \fB\-\-noflush\fP option. This lets outstanding I/O that has not yet reached the
33841device to remain unflushed.
33842.
33843.HP
33844.CMD_TABLE
33845.br
33846Outputs the current table for the device in a format that can be fed
33847back in using the create or load commands.
33848With \fB\-\-target\fP, only information relating to the specified target type
33849is displayed.
33850Encryption keys are suppressed in the table output for the crypt
33851target unless the \fB\-\-showkeys\fP parameter is supplied.
33852.
33853.HP
33854.CMD_TARGETS
33855.br
33856Displays the names and versions of the currently-loaded targets.
33857.
33858.HP
33859.CMD_UDEVCOMPLETE
33860.br
33861Wake any processes that are waiting for udev to complete processing the specified cookie.
33862.
33863.HP
33864.CMD_UDEVCOMPLETE_ALL
33865.br
33866Remove all cookies older than the specified number of minutes.
33867Any process waiting on a cookie will be resumed immediately.
33868.
33869.HP
33870.CMD_UDEVCOOKIES
33871.br
33872List all existing cookies. Cookies are system-wide semaphores with keys
33873prefixed by two predefined bytes (0x0D4D).
33874.
33875.HP
33876.CMD_UDEVCREATECOOKIE
33877.br
33878Creates a new cookie to synchronize actions with udev processing.
33879The output is a cookie value. Normally we don't need to create cookies since
33880dmsetup creates and destroys them for each action automatically. However, we can
33881generate one explicitly to group several actions together and use only one
33882cookie instead. We can define a cookie to use for each relevant command by using
33883\fB\-\-udevcookie\fP option. Alternatively, we can export this value into the environment
33884of the dmsetup process as \fBDM_UDEV_COOKIE\fP variable and it will be used automatically
33885with all subsequent commands until it is unset.
33886Invoking this command will create system-wide semaphore that needs to be cleaned
33887up explicitly by calling udevreleasecookie command.
33888.
33889.HP
33890.CMD_UDEVFLAGS
33891.br
33892Parses given \fIcookie\fP value and extracts any udev control flags encoded.
33893The output is in environment key format that is suitable for use in udev
33894rules. If the flag has its symbolic name assigned then the output is
33895DM_UDEV_FLAG_<flag_name> = '1', DM_UDEV_FLAG<flag_position> = '1' otherwise.
33896Subsystem udev flags don't have symbolic names assigned and these ones are
33897always reported as DM_SUBSYSTEM_UDEV_FLAG<flag_position> = '1'. There are
3389816 udev flags altogether.
33899.
33900.HP
33901.CMD_UDEVRELEASECOOKIE
33902.br
33903Waits for all pending udev processing bound to given cookie value and clean up
33904the cookie with underlying semaphore. If the cookie is not given directly,
33905the command will try to use a value defined by \fBDM_UDEV_COOKIE\fP environment variable.
33906.
33907.HP
33908.CMD_VERSION
33909.br
33910Outputs version information.
33911.
33912.HP
33913.CMD_WAIT
33914.br
33915Sleeps until the event counter for device_name exceeds event_nr.
33916Use \fB\-v\fP to see the event number returned.
33917To wait until the next event is triggered, use \fBinfo\fP to find
33918the last event number.
33919With \fB\-\-noflush\fP, the thin target (from version 1.3.0) doesn't commit
33920any outstanding changes to disk before reporting its statistics.
33921.
33922.HP
33923.CMD_WIPE_TABLE
33924.br
33925Wait for any I/O in-flight through the device to complete, then
33926replace the table with a new table that fails any new I/O
33927sent to the device. If successful, this should release any devices
33928held open by the device's table(s).
33929.
33930.SH TABLE FORMAT
33931.
33932Each line of the table specifies a single target and is of the form:
33933.sp
33934.I logical_start_sector num_sectors
33935.B target_type
33936.I target_args
33937.sp
33938Simple target types and target args include:
33939.
33940.TP
33941.B linear \fIdestination_device start_sector
33942The traditional linear mapping.
33943.TP
33944.B striped \fInum_stripes chunk_size \fR[\fIdestination start_sector\fR]...
33945Creates a striped area.
33946.br
33947e.g. striped 2 32 /dev/hda1 0 /dev/hdb1 0
33948will map the first chunk (16k) as follows:
33949.RS
33950.RS
33951 LV chunk 1 -> hda1, chunk 1
33952 LV chunk 2 -> hdb1, chunk 1
33953 LV chunk 3 -> hda1, chunk 2
33954 LV chunk 4 -> hdb1, chunk 2
33955 etc.
33956.RE
33957.RE
33958.TP
33959.B error
33960Errors any I/O that goes to this area. Useful for testing or
33961for creating devices with holes in them.
33962.TP
33963.B zero
33964Returns blocks of zeroes on reads. Any data written is discarded silently.
33965This is a block-device equivalent of the \fI/dev/zero\fP
33966character-device data sink described in \fBnull\fP(4).
33967.P
33968More complex targets include:
33969.TP
33970.B cache
33971Improves performance of a block device (eg, a spindle) by dynamically
33972migrating some of its data to a faster smaller device (eg, an SSD).
33973.TP
33974.B crypt
33975Transparent encryption of block devices using the kernel crypto API.
33976.TP
33977.B delay
33978Delays reads and/or writes to different devices. Useful for testing.
33979.TP
33980.B flakey
33981Creates a similar mapping to the linear target but
33982exhibits unreliable behaviour periodically.
33983Useful for simulating failing devices when testing.
33984.TP
33985.B mirror
33986Mirrors data across two or more devices.
33987.TP
33988.B multipath
33989Mediates access through multiple paths to the same device.
33990.TP
33991.B raid
33992Offers an interface to the kernel's software raid driver, md.
33993.TP
33994.B snapshot
33995Supports snapshots of devices.
33996.TP
33997.BR thin ", " thin-pool
33998Supports thin provisioning of devices and also provides a better snapshot support.
33999.P
34000To find out more about the various targets and their table formats and status
34001lines, please read the files in the Documentation/device-mapper directory in
34002the kernel source tree.
34003(Your distribution might include a copy of this information in the
34004documentation directory for the device-mapper package.)
34005.
34006.SH EXAMPLES
34007.
34008# A table to join two disks together
34009.br
340100 1028160 linear /dev/hda 0
34011.br
340121028160 3903762 linear /dev/hdb 0
34013.br
34014# A table to stripe across the two disks,
34015.br
34016# and add the spare space from
34017.br
34018# hdb to the back of the volume
34019.br
340200 2056320 striped 2 32 /dev/hda 0 /dev/hdb 0
34021.br
340222056320 2875602 linear /dev/hdb 1028160
34023.
34024.SH ENVIRONMENT VARIABLES
34025.
34026.TP
34027.B DM_DEV_DIR
34028The device directory name.
34029Defaults to "\fI/dev\fP" and must be an absolute path.
34030.TP
34031.B DM_UDEV_COOKIE
34032A cookie to use for all relevant commands to synchronize with udev processing.
34033It is an alternative to using \fB\-\-udevcookie\fP option.
34034.TP
34035.B DM_DEFAULT_NAME_MANGLING_MODE
34036A default mangling mode. Defaults to "\fB#DEFAULT_MANGLING#\fP"
34037and it is an alternative to using \fB\-\-manglename\fP option.
34038.
34039.SH AUTHORS
34040.
34041Original version: Joe Thornber <thornber@redhat.com>
34042.
34043.SH SEE ALSO
34044.
34045.BR dmstats (8),
34046.BR udev (7),
34047.BR udevadm (8)
34048.P
34049LVM2 resource page: https://www.sourceware.org/lvm2/
34050.br
34051Device-mapper resource page: http://sources.redhat.com/dm/
34052\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm-lvpoll.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005507\013062740170\0020433\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVPOLL" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" \" -*- nroff -*-
34053.SH NAME
34054lvpoll \(em Internal command used by lvmpolld to complete some Logical Volume operations.
34055
34056.SH SYNOPSIS
34057.B lvm lvpoll
34058.BR \-\-polloperation
34059.RI { pvmove | convert | merge | merge_thin }
34060.RB [ \-\-abort ]
34061.RB [ \-A | \-\-autobackup
34062.RI { y | n }]
34063.RB [ \-\-commandprofile
34064.IR ProfileName ]
34065.RB [ \-d | \-\-debug ]
34066.RB [ \-h | \-? | \-\-help ]
34067.RB [ \-\-handlemissingpvs ]
34068.RB [ \-i | \-\-interval
34069.IR Seconds ]
34070.RB [ \-t | \-\-test ]
34071.RB [ \-v | \-\-verbose ]
34072.RB [ \-\-version ]
34073.IR LogicalVolume [ Path ]
34074.SH DESCRIPTION
34075\fBlvpoll\fP is an internal command used by \fBlvmpolld\fP(8) to monitor and
34076complete \fBlvconvert\fP(8) and \fBpvmove\fP(8) operations.
34077\fBlvpoll\fP itself does not initiate these operations and
34078you should never normally need to invoke it directly.
34079
34080.I LogicalVolume
34081The Logical Volume undergoing conversion or, in the case of pvmove, the name of
34082the internal pvmove Logical Volume (see \fBEXAMPLES\fP).
34083.SH OPTIONS
34084See \fBlvm\fP(8) for common options.
34085.TP
34086.BR \-\-polloperation " {" \fIconvert | \fImerge | \fImerge_thin | \fIpvmove }
34087Mandatory option.
34088\fIpvmove\fP refers to a pvmove operation that is moving data.
34089\fIconvert\fP refers to an operation that is increasing the number of redundant copies of data maintained by a mirror.
34090\fImerge\fP indicates a merge operation that doesn't involve thin volumes.
34091\fImerge_thin\fP indicates a merge operation involving thin snapshots.
34092\fBpvmove\fP(8) and \fBlvconvert\fP(8) describe how to initiate these operations.
34093.TP
34094.B \-\-abort
34095Abort pvmove in progress. See \fBpvmove\fP(8).
34096.TP
34097.B \-\-handlemissingpvs
34098Used when the polling operation needs to handle missing PVs to be able to
34099continue. This can happen when \fBlvconvert\fP(8) is repairing a mirror
34100with one or more faulty devices.
34101.TP
34102.BR \-i ", " \-\-interval " "\fISeconds
34103Report progress at regular intervals
34104
34105.SH EXAMPLES
34106Resume polling of a pvmove operation identified by the Logical Volume vg00/pvmove0:
34107.sp
34108.B lvm lvpoll --polloperation pvmove vg00/pvmove0
34109.P
34110Abort the same pvmove operation:
34111.sp
34112.B lvm lvpoll --polloperation pvmove --abort vg00/pvmove0
34113.P
34114To find out the name of the pvmove Logical Volume resulting from an original
34115\fBpvmove /dev/sda1\fP command you may use the following \fBlvs\fP command.
34116(Remove the parentheses from the LV name.)
34117.sp
34118.B lvs -a -S move_pv=/dev/sda1
34119.P
34120Resume polling of mirror conversion vg00/lvmirror:
34121.sp
34122.B lvm lvpoll --polloperation convert vg00/lvmirror
34123.P
34124Complete mirror repair:
34125.sp
34126.B lvm lvpoll --polloperation convert vg/damaged_mirror --handlemissingpvs
34127.P
34128Process snapshot merge:
34129.sp
34130.B lvm lvpoll --polloperation merge vg/snapshot_old
34131.P
34132Finish thin snapshot merge:
34133.sp
34134.B lvm lvpoll --polloperation merge_thin vg/thin_snapshot
34135.SH SEE ALSO
34136.BR lvconvert (8),
34137.BR lvm (8),
34138.BR lvmpolld (8),
34139.BR lvs (8),
34140.BR pvmove (8)
34141\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvdisplay.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007402\013062740170\0020332\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVDISPLAY 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
34142.SH NAME
34143lvdisplay \(em display attributes of a logical volume
34144.SH SYNOPSIS
34145.B lvdisplay
34146.RB [ \-a | \-\-all ]
34147.RB [ \-c | \-\-colon ]
34148.RB [ \-\-commandprofile
34149.IR ProfileName ]
34150.RB [ \-d | \-\-debug ]
34151.RB [ \-h | \-? | \-\-help ]
34152.RB [ \-\-ignorelockingfailure ]
34153.RB [ \-\-ignoreskippedcluster ]
34154.RB [ \-\-maps ]
34155.RB [ \-\-nosuffix ]
34156.RB [ \-P | \-\-partial ]
34157.RB [ \-\-reportformat
34158.RB { basic | json }]
34159.RB [ \-S | \-\-select
34160.IR Selection ]
34161.RB [ \-\-units
34162.IR hHbBsSkKmMgGtTpPeE ]
34163.RB [ \-v | \-\-verbose ]
34164.RB [ \-\-version ]
34165.RI [ VolumeGroupName | LogicalVolume { Name | Path }\ ...]
34166.br
34167
34168.B lvdisplay
34169.BR \-C | \-\-columns
34170.RB [ \-\-aligned ]
34171.RB [ \-\-binary ]
34172.RB [ \-a | \-\-all ]
34173.RB [ \-\-commandprofile
34174.IR ProfileName ]
34175.RB [[ \-\-configreport
34176.IR ReportName ]
34177.RB [ \-o | \-\-options
34178.RI [ + | \- | # ] Field1 [, Field2 ...]
34179.RB [ \-O | \-\-sort
34180.RI [ + | \- ] Key1 [, Key2 ...]]
34181.RB [ \-S | \-\-select
34182.IR Selection ]
34183.RB ...]
34184.RB [ \-d | \-\-debug ]
34185.RB [ \-h | \-? | \-\-help ]
34186.RB [ \-\-ignorelockingfailure ]
34187.RB [ \-\-ignoreskippedcluster ]
34188.RB [ \-\-logonly ]
34189.RB [ \-\-noheadings ]
34190.RB [ \-\-nosuffix ]
34191.RB [ \-P | \-\-partial ]
34192.RB [ \-\-reportformat
34193.RB { basic | json }]
34194.RB [ \-\-segments ]
34195.RB [ \-\-separator
34196.IR Separator ]
34197.RB [ \-\-unbuffered ]
34198.RB [ \-\-units
34199.IR hHbBsSkKmMgGtTpPeE ]
34200.RB [ \-v | \-\-verbose ]
34201.RB [ \-\-version ]
34202.RI [ VolumeGroupName | LogicalVolume { Name | Path }\ ...]
34203.SH DESCRIPTION
34204lvdisplay allows you to see the attributes of a logical volume
34205like size, read/write status, snapshot information etc.
34206.P
34207\fBlvs\fP(8) is an alternative that provides the same information
34208in the style of \fBps\fP(1).
34209\fBlvs\fP(8) is recommended over \fBlvdisplay\fP.
34210
34211.SH OPTIONS
34212See \fBlvm\fP(8) for common options and \fBlvs\fP for options given with
34213\fB\-\-columns\fP.
34214.TP
34215.B \-\-all
34216Include information in the output about internal Logical Volumes that
34217are components of normally-accessible Logical Volumes, such as mirrors,
34218but which are not independently accessible (e.g. not mountable).
34219For example, after creating a mirror using
34220\fBlvcreate \-m1 \-\-mirrorlog disk\fP,
34221this option will reveal three internal Logical Volumes, with suffixes
34222mimage_0, mimage_1, and mlog.
34223.TP
34224.BR \-C ", " \-\-columns
34225Display output in columns, the equivalent of \fBlvs\fP(8).
34226Options listed are the same as options given in \fBlvs\fP(8).
34227.TP
34228.BR \-c ", " \-\-colon
34229Generate colon separated output for easier parsing in scripts or programs.
34230N.B. \fBlvs\fP(8) provides considerably more control over the output.
34231.nf
34232
34233The values are:
34234
34235\(bu logical volume name
34236\(bu volume group name
34237\(bu logical volume access
34238\(bu logical volume status
34239\(bu internal logical volume number
34240\(bu open count of logical volume
34241\(bu logical volume size in sectors
34242\(bu current logical extents associated to logical volume
34243\(bu allocated logical extents of logical volume
34244\(bu allocation policy of logical volume
34245\(bu read ahead sectors of logical volume
34246\(bu major device number of logical volume
34247\(bu minor device number of logical volume
34248
34249.fi
34250.TP
34251.BR \-m ", " \-\-maps
34252Display the mapping of logical extents to physical volumes and
34253physical extents. To map physical extents
34254to logical extents use:
34255.B pvs \-\-segments \-o+lv_name,seg_start_pe,segtype
34256.SH Examples
34257Shows attributes of that logical volume. If snapshot
34258logical volumes have been created for this original logical volume,
34259this command shows a list of all snapshot logical volumes and their
34260status (active or inactive) as well:
34261.sp
34262.B lvdisplay \-v vg00/lvol2
34263
34264Shows the attributes of this snapshot logical volume and also which
34265original logical volume it is associated with:
34266.sp
34267.B lvdisplay vg00/snapshot
34268
34269.SH SEE ALSO
34270.BR lvm (8),
34271.BR lvcreate (8),
34272.BR lvs (8),
34273.BR lvscan (8),
34274.BR pvs (8)
34275\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvextend.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011500\013062740170\0020146\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVEXTEND 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
34276.SH NAME
34277lvextend \(em extend the size of a logical volume
34278.SH SYNOPSIS
34279.B lvextend
34280.RB [ \-\-alloc
34281.IR AllocationPolicy ]
34282.RB [ \-A | \-\-autobackup
34283.RI { y | n }]
34284.RB [ \-\-commandprofile
34285.IR ProfileName ]
34286.RB [ \-d | \-\-debug ]
34287.RB [ \-h | \-? | \-\-help ]
34288.RB [ \-f | \-\-force ]
34289.RB [ \-i | \-\-stripes
34290.I Stripes
34291.RB [ \-I | \-\-stripesize
34292.IR StripeSize ]]
34293.RB { \-l | \-\-extents
34294.RI [ + ] LogicalExtentsNumber [ % { VG | LV | PVS | FREE | ORIGIN }]
34295|
34296.BR \-L | \-\-size
34297.RI [ + ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]}
34298.RB [ \-n | \-\-nofsck ]
34299.RB [ \-\-noudevsync]
34300.RB [ \-r | \-\-resizefs ]
34301.RB [ \-\-reportformat
34302.RB { basic | json }]
34303.RB [ \-\-use\-policies ]
34304.RB [ \-t | \-\-test ]
34305.RB [ \-v | \-\-verbose ]
34306.I LogicalVolumePath
34307.RI [ PhysicalVolumePath [ :PE [ \-PE ]]...]
34308.SH DESCRIPTION
34309lvextend allows you to extend the size of a logical volume.
34310Extension of snapshot logical volumes (see
34311.BR lvcreate (8)
34312for information to create snapshots) is supported as well.
34313But to change the number of copies in a mirrored logical
34314volume use
34315.BR lvconvert (8).
34316.SH OPTIONS
34317See \fBlvm\fP(8) for common options.
34318.TP
34319.BR \-f ", " \-\-force
34320Proceed with size extension without prompting.
34321.TP
34322.IR \fB\-l ", " \fB\-\-extents " [" + ] LogicalExtentsNumber [ % { VG | LV | PVS | FREE | ORIGIN }]
34323Extend or set the logical volume size in units of logical extents.
34324With the '\fI+\fP' sign the value is added to the actual size
34325of the logical volume and without it, the value is taken as an absolute one.
34326The total number of physical extents allocated will be
34327greater than this, for example, if the volume is mirrored.
34328The number can also be expressed as a percentage of the total space
34329in the Volume Group with the suffix \fI%VG\fP, relative to the existing
34330size of the Logical Volume with the suffix \fI%LV\fP, of the remaining
34331free space for the specified PhysicalVolume(s) with the suffix \fI%PVS\fP,
34332as a percentage of the remaining free space in the Volume Group
34333with the suffix \fI%FREE\fP, or (for a snapshot) as a percentage of the total
34334space in the Origin Logical Volume with the suffix \fI%ORIGIN\fP.
34335The resulting value is rounded upward.
34336N.B. In a future release, when expressed as a percentage with PVS, VG or FREE,
34337the number will be treated as an approximate upper limit for the total number
34338of physical extents to be allocated (including extents used by any mirrors, for
34339example). The code may currently allocate more space than you might otherwise
34340expect.
34341.TP
34342.IR \fB\-L ", " \fB\-\-size " [" + ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
34343Extend or set the logical volume size in units of megabytes.
34344A size suffix of M for megabytes,
34345G for gigabytes, T for terabytes, P for petabytes
34346or E for exabytes is optional.
34347With the + sign the value is added to the actual size
34348of the logical volume and without it, the value is taken as an absolute one.
34349.TP
34350.BR \-i ", " \-\-stripes " " \fIStripes
34351Gives the number of stripes for the extension.
34352Not applicable to LVs using the original metadata LVM format, which must
34353use a single value throughout.
34354.TP
34355.BR \-I ", " \-\-stripesize " " \fIStripeSize
34356Gives the number of kilobytes for the granularity of the stripes.
34357Not applicable to LVs using the original metadata LVM format, which must
34358use a single value throughout.
34359.br
34360StripeSize must be 2^n (n = 2 to 9)
34361.TP
34362.BR \-n ", " \-\-nofsck
34363Do not perform fsck before extending filesystem when filesystem
34364requires it. You may need to use \fB\-\-force\fR to proceed with
34365this option.
34366.TP
34367.B \-\-noudevsync
34368Disable udev synchronisation. The
34369process will not wait for notification from udev.
34370It will continue irrespective of any possible udev processing
34371in the background. You should only use this if udev is not running
34372or has rules that ignore the devices LVM2 creates.
34373.TP
34374.BR \-r ", " \-\-resizefs
34375Resize underlying filesystem together with the logical volume using
34376\fBfsadm\fR(8).
34377.TP
34378.B \-\-use\-policies
34379Resizes the logical volume according to configured policy. See
34380\fBlvm.conf\fR(5) for some details.
34381
34382.SH Examples
34383Extends the size of the logical volume "vg01/lvol10" by 54MiB on physical
34384volume /dev/sdk3. This is only possible if /dev/sdk3 is a member of
34385volume group vg01 and there are enough free physical extents in it:
34386.sp
34387.B lvextend \-L +54 /dev/vg01/lvol10 /dev/sdk3
34388
34389Extends the size of logical volume "vg01/lvol01" by the amount of free
34390space on physical volume /dev/sdk3. This is equivalent to specifying
34391"\-l +100%PVS" on the command line:
34392.sp
34393.B lvextend /dev/vg01/lvol01 /dev/sdk3
34394
34395Extends a logical volume "vg01/lvol01" by 16MiB using physical extents
34396/dev/sda:8\-9 and /dev/sdb:8\-9 for allocation of extents:
34397.sp
34398.B lvextend -L+16M vg01/lvol01 /dev/sda:8\-9 /dev/sdb:8\-9
34399
34400.SH SEE ALSO
34401.BR fsadm (8),
34402.BR lvm (8),
34403.BR lvm.conf (5),
34404.BR lvcreate (8),
34405.BR lvconvert (8),
34406.BR lvreduce (8),
34407.BR lvresize (8),
34408.BR lvchange (8)
34409\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmdbusd.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000765\013062740170\0020150\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMDBUSD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
34410.
34411.SH NAME
34412.
34413lvmdbusd \(em LVM D-Bus daemon
34414.
34415.SH SYNOPSIS
34416.
34417.ad l
34418.B lvmdbusd
34419.RB [ \-\-debug \]
34420.RB [ \-\-udev \]
34421.ad b
34422.
34423.SH DESCRIPTION
34424.
34425lvmdbusd is a service which provides a D-Bus API to the logical volume manager (LVM).
34426Run
34427.BR lvmdbusd (8)
34428as root.
34429.
34430.SH OPTIONS
34431.
34432.HP
34433.BR \-\-debug
34434.br
34435Enable debug statements
34436.
34437.HP
34438.BR \-\-udev
34439.br
34440Use udev events to trigger updates
34441.
34442.SH SEE ALSO
34443.
34444.nh
34445.BR dbus-send (1),
34446.BR lvm (8)
34447\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgsplit.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005511\013062740170\0020012\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGSPLIT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
34448.SH NAME
34449vgsplit \(em split a volume group into two
34450.SH SYNOPSIS
34451.B vgsplit
34452.RB [ \-\-alloc
34453.IR AllocationPolicy ]
34454.RB [ \-A | \-\-autobackup
34455.RI { y | n }]
34456.RB [ \-c | \-\-clustered
34457.RI { y | n }]
34458.RB [ \-\-commandprofile
34459.IR ProfileName ]
34460.RB [ \-d | \-\-debug ]
34461.RB [ \-h | \-\-help ]
34462.RB [ \-l | \-\-maxlogicalvolumes
34463.IR MaxLogicalVolumes ]
34464.RB [ \-M | \-\-metadatatype
34465.IR type ]
34466.RB [ \-p | \-\-maxphysicalvolumes
34467.IR MaxPhysicalVolumes ]
34468.RB [ \-\- [ vg ] metadatacopies
34469.IR NumberOfCopies | unmanaged | all ]
34470.RB [ \-n | \-\-name
34471.IR LogicalVolumeName ]
34472.RB [ \-t | \-\-test ]
34473.RB [ \-v | \-\-verbose ]
34474.I SourceVolumeGroupName DestinationVolumeGroupName
34475.RI [ PhysicalVolumePath ...]
34476.SH DESCRIPTION
34477vgsplit moves one or more physical volumes from
34478\fISourceVolumeGroupName\fP into \fIDestinationVolumeGroupName\fP.
34479The physical volumes moved can be specified either explicitly via
34480\fIPhysicalVolumePath\fP, or implicitly by \fB\-n\fP
34481\fILogicalVolumeName\fP, in which case only physical volumes
34482underlying the specified logical volume will be moved.
34483
34484If \fIDestinationVolumeGroupName\fP does not exist, a new volume
34485group will be created. The default attributes
34486for the new volume group can be specified with
34487.BR \-\-alloc ,
34488.BR \-\-clustered ,
34489.BR \-\-maxlogicalvolumes ,
34490.BR \-\-metadatatype ,
34491.B \-\-maxphysicalvolumes \fRand
34492.BR \-\- [ vg ] metadatacopies
34493(see \fBvgcreate\fP(8) for a description of these options). If any
34494of these options are not given, default attribute(s) are taken from
34495\fISourceVolumeGroupName\fP. If a non-LVM2 metadata type (e.g. lvm1) is
34496being used, you should use the \fB\-M\fP option to specify the metadata
34497type directly.
34498
34499If
34500.I DestinationVolumeGroupName
34501does exist, it will be checked for compatibility with
34502.I SourceVolumeGroupName
34503before the physical volumes are moved. Specifying any of the above default
34504volume group attributes with an existing destination volume group is an error,
34505and no split will occur.
34506
34507Logical volumes cannot be split between volume groups. \fBvgsplit\fP(8) only
34508moves complete physical volumes: To move part of a physical volume, use
34509\fBpvmove\fP(8). Each existing logical volume must be entirely on the physical
34510volumes forming either the source or the destination volume group. For this
34511reason, \fBvgsplit\fP(8) may fail with an error if a split would result in a
34512logical volume being split across volume groups.
34513
34514A vgsplit into an existing volume group retains the existing volume group's
34515value of \fPvgmetadatacopies\fP (see \fBvgcreate\fP(8) and \fBlvm.conf\fP(5) for further
34516explanation of \fPvgmetadatacopies\fP). To change the value of
34517\fBvgmetadatacopies\fP, use \fBvgchange\fP(8).
34518
34519.SH OPTIONS
34520See \fBlvm\fP(8) for common options.
34521.SH SEE ALSO
34522.BR lvm (8),
34523.BR vgcreate (8),
34524.BR vgextend (8),
34525.BR vgreduce (8),
34526.BR vgmerge (8)
34527\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmetad.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010202\013062740170\0017747\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMETAD 8 "LVM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
34528.SH NAME
34529lvmetad \(em LVM metadata cache daemon
34530
34531.SH SYNOPSIS
34532.B lvmetad
34533.RB [ \-l
34534.IR level [,level...]]
34535.RB [ \-p
34536.IR pidfile_path ]
34537.RB [ \-s
34538.IR socket_path ]
34539.RB [ \-t
34540.IR timeout_value ]
34541.RB [ \-f ]
34542.RB [ \-h ]
34543.RB [ \-V ]
34544.RB [ \-? ]
34545
34546.SH DESCRIPTION
34547
34548The lvmetad daemon caches LVM metadata so that LVM commands can read
34549metadata from the cache rather than scanning disks. This can be an
34550advantage because scanning disks is time consuming and may interfere with
34551the normal work of the system. lvmetad can be a disadvantage when disk
34552event notifications from the system are unreliable.
34553
34554lvmetad does not read metadata from disks itself. Instead, it relies on
34555an LVM command, like pvscan \-\-cache, to read metadata from disks and
34556send it to lvmetad to be cached.
34557
34558New LVM disks that appear on the system must be scanned before lvmetad
34559knows about them. If lvmetad does not know about a disk, then LVM
34560commands using lvmetad will also not know about it. When disks are added
34561or removed from the system, lvmetad must be updated.
34562
34563lvmetad is usually combined with event\-based system services that
34564automatically run pvscan \-\-cache on disks added or removed. This way,
34565the cache is automatically updated with metadata from new disks when they
34566appear. LVM udev rules and systemd services implement this automation.
34567Automatic scanning is usually combined with automatic activation. For
34568more information, see
34569.BR pvscan (8).
34570
34571If lvmetad is started or restarted after disks have been added to the
34572system, or if the global_filter has changed, the cache must be updated.
34573This can be done by running pvscan \-\-cache, or it will be done
34574automatically by the next LVM command that's run.
34575
34576When lvmetad is not used, LVM commands revert to scanning disks for LVM
34577metadata.
34578
34579In some cases, lvmetad will be temporarily disabled while it continues
34580running. In this state, LVM commands will ignore the lvmetad cache and
34581revert to scanning disks. A warning will also be printed which includes
34582the reason why lvmetad is not being used. The most common reason is the
34583existence of duplicate PVs (lvmetad cannot cache data for duplicate PVs.)
34584Once duplicates have been resolved, the lvmetad cache is can be updated
34585with pvscan \-\-cache and commands will return to using the cache.
34586
34587Use of lvmetad is enabled/disabled by:
34588.br
34589.BR lvm.conf (5)
34590.B global/use_lvmetad
34591
34592For more information on this setting, see:
34593.br
34594.B lvmconfig \-\-withcomments global/use_lvmetad
34595
34596To ignore disks from LVM at the system level, e.g. lvmetad, pvscan use:
34597.br
34598.BR lvm.conf (5)
34599.B devices/global_filter
34600
34601For more information on this setting, see
34602.br
34603.B lvmconfig \-\-withcomments devices/global_filter
34604
34605.SH OPTIONS
34606
34607To run the daemon in a test environment both the pidfile_path and the
34608socket_path should be changed from the defaults.
34609.TP
34610.B \-f
34611Don't fork, but run in the foreground.
34612.TP
34613.BR \-h ", " \-?
34614Show help information.
34615.TP
34616.B \-l \fIlevels
34617Specify the levels of log messages to generate as a comma separated list.
34618Messages are logged by syslog.
34619Additionally, when \-f is given they are also sent to standard error.
34620Possible levels are: all, fatal, error, warn, info, wire, debug.
34621.TP
34622.B \-p \fIpidfile_path
34623Path to the pidfile. This overrides both the built-in default
34624(#DEFAULT_PID_DIR#/lvmetad.pid) and the environment variable
34625\fBLVM_LVMETAD_PIDFILE\fP. This file is used to prevent more
34626than one instance of the daemon running simultaneously.
34627.TP
34628.B \-s \fIsocket_path
34629Path to the socket file. This overrides both the built-in default
34630(#DEFAULT_RUN_DIR#/lvmetad.socket) and the environment variable
34631\fBLVM_LVMETAD_SOCKET\fP. To communicate successfully with lvmetad,
34632all LVM2 processes should use the same socket path.
34633.TP
34634.B \-t \fItimeout_value
34635The daemon may shutdown after being idle for the given time (in seconds). When the
34636option is omitted or the value given is zero the daemon never shutdowns on idle.
34637.TP
34638.B \-V
34639Display the version of lvmetad daemon.
34640.SH ENVIRONMENT VARIABLES
34641.TP
34642.B LVM_LVMETAD_PIDFILE
34643Path for the pid file.
34644.TP
34645.B LVM_LVMETAD_SOCKET
34646Path for the socket file.
34647
34648.SH SEE ALSO
34649.BR lvm (8),
34650.BR lvmconfig (8),
34651.BR lvm.conf (5),
34652.BR pvscan (8)
34653\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgs.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012553\013062740170\0017125\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGS 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
34654.SH NAME
34655vgs \(em report information about volume groups
34656.SH SYNOPSIS
34657.B vgs
34658.RB [ \-a | \-\-all ]
34659.RB [ \-\-aligned ]
34660.RB [ \-\-binary ]
34661.RB [ \-\-commandprofile
34662.IR ProfileName ]
34663.RB [[ \-\-configreport
34664.IR ReportName ]
34665.RB [ \-o | \-\-options
34666.RI [ + | \- | # ] Field1 [, Field2 ...]
34667.RB [ \-O | \-\-sort
34668.RI [ + | \- ] Key1 [, Key2 ...]]
34669.RB [ \-S | \-\-select
34670.IR Selection ]
34671.RB ...]
34672.RB [ \-d | \-\-debug ]
34673.RB [ \-h | \-? | \-\-help ]
34674.RB [ \-\-ignorelockingfailure ]
34675.RB [ \-\-ignoreskippedcluster ]
34676.RB [ \-\-logonly ]
34677.RB [ \-\-nameprefixes ]
34678.RB [ \-\-noheadings ]
34679.RB [ \-\-nosuffix ]
34680.RB [ \-P | \-\-partial ]
34681.RB [ \-\-reportformat
34682.RB { basic | json }]
34683.RB [ \-\-rows ]
34684.RB [ \-\-separator
34685.IR Separator ]
34686.RB [ \-\-unbuffered ]
34687.RB [ \-\-units
34688.IR hHbBsSkKmMgGtTpPeE ]
34689.RB [ \-\-unquoted ]
34690.RB [ \-v | \-\-verbose ]
34691.RB [ \-\-version ]
34692.RI [ VolumeGroupName
34693.RI [ VolumeGroupName ...]]
34694.SH DESCRIPTION
34695vgs produces formatted output about volume groups.
34696.SH OPTIONS
34697See \fBlvm\fP(8) for common options.
34698.TP
34699.B \-\-all
34700List all volume groups. Equivalent to not specifying any volume groups.
34701.TP
34702.B \-\-aligned
34703Use with \fB\-\-separator\fP to align the output columns.
34704.TP
34705.B \-\-binary
34706Use binary values "0" or "1" instead of descriptive literal values
34707for columns that have exactly two valid values to report (not counting
34708the "unknown" value which denotes that the value could not be determined).
34709.TP
34710.B \-\-configreport \fI ReportName
34711Make any subsequent \fB\-o, \-\-options\fP, \fB\-O, \-\-sort\fP or
34712\fB\-S, \-\-select\fP to apply for \fIReportName\fP where \fIReportName\fP
34713is either 'vg' for command's main report or 'log' for log report.
34714If \fB\-\-configreport\fP option is not used to identify a report, then
34715command's main report is assumed. The log report is available only if
34716enabled by \fBlog/report_command_log\fP \fBlvm.conf\fP(5) setting or
34717if \fB\-\-logonly\fP option is used.
34718.TP
34719.B \-\-logonly
34720Suppress the vgs report itself and display only log report on output.
34721.TP
34722.B \-\-nameprefixes
34723Add an "LVM2_" prefix plus the field name to the output. Useful
34724with \fB\-\-noheadings\fP to produce a list of field=value pairs that can
34725be used to set environment variables (for example, in \fBudev\fP(7) rules).
34726.TP
34727.B \-\-noheadings
34728Suppress the headings line that is normally the first line of output.
34729Useful if grepping the output.
34730.TP
34731.B \-\-nosuffix
34732Suppress the suffix on output sizes. Use with \fB\-\-units\fP
34733(except h and H) if processing the output.
34734.TP
34735.BR \-o ", " \-\-options
34736Comma-separated ordered list of columns.
34737.IP
34738Precede the list with '\fI+\fP' to append to the current list
34739of columns, '\fI-\fP' to remove from the current list of columns
34740or '\fI#\fP' to compact given columns. The \fI\-o\fP option can
34741be repeated, providing several lists. These lists are evaluated
34742from left to right.
34743.IP
34744Use \fB\-o vg_all\fP to select all volume group columns.
34745.IP
34746Use \fB\-o help\fP to view the full list of columns available.
34747.IP
34748Column names include: vg_fmt, vg_uuid, vg_name, vg_attr, vg_size, vg_free,
34749vg_sysid, vg_extent_size, vg_extent_count, vg_free_count, vg_profile, max_lv,
34750max_pv, pv_count, lv_count, snap_count, vg_seqno, vg_tags, vg_mda_count,
34751vg_mda_free, and vg_mda_size, vg_mda_used_count.
34752.IP
34753Any "vg_" prefixes are optional. Columns mentioned in either \fBpvs\fP(8)
34754or \fBlvs\fP(8) can also be chosen, but columns cannot be taken from both
34755at the same time.
34756.IP
34757The vg_attr bits are:
34758.RS
34759.IP 1 3
34760Permissions: (w)riteable, (r)ead-only
34761.IP 2 3
34762Resi(z)eable
34763.IP 3 3
34764E(x)ported
34765.IP 4 3
34766(p)artial: one or more physical volumes belonging to the volume group
34767are missing from the system
34768.IP 5 3
34769Allocation policy: (c)ontiguous, c(l)ing, (n)ormal, (a)nywhere
34770.IP 6 3
34771(c)lustered, (s)hared
34772.RE
34773.TP
34774.BR \-O ", " \-\-sort
34775Comma-separated ordered list of columns to sort by. Replaces the default
34776selection. Precede any column with '\fI\-\fP' for a reverse sort on that
34777column.
34778.TP
34779.B \-\-rows
34780Output columns as rows.
34781.TP
34782.BR \-S ", " \-\-select " " \fISelection
34783Display only rows that match Selection criteria. All rows are displayed with
34784the additional "selected" column (\fB-o selected\fP) showing 1 if the row
34785matches the Selection and 0 otherwise. The Selection criteria are defined
34786by specifying column names and their valid values (that can include reserved
34787values) while making use of supported comparison operators. See \fBlvm\fP(8)
34788and \fB\-S\fP, \fB\-\-select\fP description for more detailed information
34789about constructing the Selection criteria. As a quick help and to see full
34790list of column names that can be used in Selection including the list of
34791reserved values and the set of supported selection operators, check the
34792output of \fBvgs -S help\fP command.
34793.TP
34794.B \-\-separator \fISeparator
34795String to use to separate each column. Useful if grepping the output.
34796.TP
34797.B \-\-unbuffered
34798Produce output immediately without sorting or aligning the columns properly.
34799.TP
34800.B \-\-units \fIhHbBsSkKmMgGtTpPeE
34801All sizes are output in these units: (h)uman-readable, (b)ytes, (s)ectors,
34802(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.
34803Capitalise to use multiples of 1000 (S.I.) instead of 1024. Can also specify
34804custom units e.g. \-\-units 3M
34805.TP
34806.B \-\-unquoted
34807When used with \fB\-\-nameprefixes\fP, output values in the field=value
34808pairs are not quoted.
34809.SH SEE ALSO
34810.BR lvm (8),
34811.BR vgdisplay (8),
34812.BR pvs (8),
34813.BR lvs (8)
34814\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvm.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000062104\013062740170\0017121\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVM 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
34815.
34816.SH NAME
34817.
34818lvm \(em LVM2 tools
34819.
34820.SH SYNOPSIS
34821.
34822.B lvm
34823.RI [ command | file ]
34824.
34825.SH DESCRIPTION
34826.
34827lvm provides the command-line tools for LVM2. A separate
34828manual page describes each command in detail.
34829.P
34830If \fBlvm\fP is invoked with no arguments it presents a readline prompt
34831(assuming it was compiled with readline support).
34832LVM commands may be entered interactively at this prompt with
34833readline facilities including history and command name and option
34834completion. Refer to \fBreadline\fP(3) for details.
34835.P
34836If \fBlvm\fP is invoked with argv[0] set to the name of a specific
34837LVM command (for example by using a hard or soft link) it acts as
34838that command.
34839.P
34840On invocation, \fBlvm\fP requires that only the standard file descriptors
34841stdin, stdout and stderr are available. If others are found, they
34842get closed and messages are issued warning about the leak.
34843This warning can be suppressed by setting the environment variable
34844.B LVM_SUPPRESS_FD_WARNINGS\fP.
34845.P
34846Where commands take VG or LV names as arguments, the full path name is
34847optional. An LV called "lvol0" in a VG called "vg0" can be specified
34848as "vg0/lvol0". Where a list of VGs is required but is left empty,
34849a list of all VGs will be substituted. Where a list of LVs is required
34850but a VG is given, a list of all the LVs in that VG will be substituted.
34851So \fBlvdisplay vg0\fP will display all the LVs in "vg0".
34852Tags can also be used - see \fB\-\-addtag\fP below.
34853.P
34854One advantage of using the built-in shell is that configuration
34855information gets cached internally between commands.
34856.P
34857A file containing a simple script with one command per line
34858can also be given on the command line. The script can also be
34859executed directly if the first line is #! followed by the absolute
34860path of \fBlvm\fP.
34861.
34862.SH BUILT-IN COMMANDS
34863.
34864The following commands are built into lvm without links
34865normally being created in the filesystem for them.
34866.sp
34867.PD 0
34868.TP 14
34869.B config
34870The same as \fBlvmconfig\fP(8) below.
34871.TP
34872.B devtypes
34873Display the recognised built-in block device types.
34874.TP
34875.B dumpconfig
34876The same as \fBlvmconfig\fP(8) below.
34877.TP
34878.B formats
34879Display recognised metadata formats.
34880.TP
34881.B fullreport
34882Report information about PVs, PV segments, VGs, LVs and LV segments,
34883all at once.
34884.TP
34885.B help
34886Display the help text.
34887.TP
34888.B lastlog
34889Display log report of last command run in LVM shell
34890if command log reporting is enabled.
34891.TP
34892.B lvpoll
34893Complete lvmpolld operations (Internal command).
34894.TP
34895.B pvdata
34896Not implemented in LVM2.
34897.TP
34898.B segtypes
34899Display recognised Logical Volume segment types.
34900.TP
34901.B systemid
34902Display any system ID currently set on this host.
34903.TP
34904.B tags
34905Display any tags defined on this host.
34906.TP
34907.B version
34908Display version information.
34909.PD
34910.
34911.SH COMMANDS
34912.
34913The following commands implement the core LVM functionality.
34914.sp
34915.PD 0
34916.TP 14
34917.B pvchange
34918Change attributes of a Physical Volume.
34919.TP
34920.B pvck
34921Check Physical Volume metadata.
34922.TP
34923.B pvcreate
34924Initialize a disk or partition for use by LVM.
34925.TP
34926.B pvdisplay
34927Display attributes of a Physical Volume.
34928.TP
34929.B pvmove
34930Move Physical Extents.
34931.TP
34932.B pvremove
34933Remove a Physical Volume.
34934.TP
34935.B pvresize
34936Resize a disk or partition in use by LVM2.
34937.TP
34938.B pvs
34939Report information about Physical Volumes.
34940.TP
34941.B pvscan
34942Scan all disks for Physical Volumes.
34943.TP
34944.B vgcfgbackup
34945Backup Volume Group descriptor area.
34946.TP
34947.B vgcfgrestore
34948Restore Volume Group descriptor area.
34949.TP
34950.B vgchange
34951Change attributes of a Volume Group.
34952.TP
34953.B vgck
34954Check Volume Group metadata.
34955.TP
34956.B vgconvert
34957Convert Volume Group metadata format.
34958.TP
34959.B vgcreate
34960Create a Volume Group.
34961.TP
34962.B vgdisplay
34963Display attributes of Volume Groups.
34964.TP
34965.B vgexport
34966Make volume Groups unknown to the system.
34967.TP
34968.B vgextend
34969Add Physical Volumes to a Volume Group.
34970.TP
34971.B vgimport
34972Make exported Volume Groups known to the system.
34973.TP
34974.B vgimportclone
34975Import and rename duplicated Volume Group (e.g. a hardware snapshot).
34976.TP
34977.B vgmerge
34978Merge two Volume Groups.
34979.TP
34980.B vgmknodes
34981Recreate Volume Group directory and Logical Volume special files
34982.TP
34983.B vgreduce
34984Reduce a Volume Group by removing one or more Physical Volumes.
34985.TP
34986.B vgremove
34987Remove a Volume Group.
34988.TP
34989.B vgrename
34990Rename a Volume Group.
34991.TP
34992.B vgs
34993Report information about Volume Groups.
34994.TP
34995.B vgscan
34996Scan all disks for Volume Groups and rebuild caches.
34997.TP
34998.B vgsplit
34999Split a Volume Group into two, moving any logical
35000volumes from one Volume Group to another by moving entire Physical
35001Volumes.
35002.TP
35003.B lvchange
35004Change attributes of a Logical Volume.
35005.TP
35006.B lvconvert
35007Convert a Logical Volume from linear to mirror or snapshot.
35008.TP
35009.B lvcreate
35010Create a Logical Volume in an existing Volume Group.
35011.TP
35012.B lvdisplay
35013Display attributes of a Logical Volume.
35014.TP
35015.B lvextend
35016Extend the size of a Logical Volume.
35017.TP
35018.B lvmchange
35019Change attributes of the Logical Volume Manager.
35020.TP
35021.B lvmconfig
35022Display the configuration information after
35023loading \fBlvm.conf\fP(5) and any other configuration files.
35024.TP
35025.B lvmdiskscan
35026Scan for all devices visible to LVM2.
35027.TP
35028.B lvmdump
35029Create lvm2 information dumps for diagnostic purposes.
35030.TP
35031.B lvreduce
35032Reduce the size of a Logical Volume.
35033.TP
35034.B lvremove
35035Remove a Logical Volume.
35036.TP
35037.B lvrename
35038Rename a Logical Volume.
35039.TP
35040.B lvresize
35041Resize a Logical Volume.
35042.TP
35043.B lvs
35044Report information about Logical Volumes.
35045.TP
35046.B lvscan
35047Scan (all disks) for Logical Volumes.
35048.PD
35049.P
35050The following commands are not implemented in LVM2 but might be
35051in the future:
35052.BR lvmsadc ", " lvmsar ", " pvdata .
35053.
35054.SH OPTIONS
35055.
35056The following options are available for many of the commands.
35057They are implemented generically and documented here rather
35058than repeated on individual manual pages.
35059.P
35060Additional hyphens within option names are ignored. For example,
35061\fB\-\-readonly\fP and \fB\-\-read\-only\fP are both accepted.
35062.
35063.HP
35064.BR \-h | \-? | \-\-help
35065.br
35066Display the help text.
35067.
35068.HP
35069.BR \-\-version
35070.br
35071Display version information.
35072.
35073.HP
35074.BR \-v | \-\-verbose
35075.br
35076Set verbose level. Repeat from 1 to 3 times to increase the detail
35077of messages sent to stdout and stderr. Overrides config file setting.
35078.
35079.HP
35080.BR \-d | \-\-debug
35081.br
35082Set debug level. Repeat from 1 to 6 times to increase the detail of
35083messages sent to the log file and/or syslog (if configured).
35084Overrides config file setting.
35085.
35086.HP
35087.BR \-q | \-\-quiet
35088.br
35089Suppress output and log messages.
35090Overrides \fB\-d\fP and \fB\-v\fP.
35091Repeat once to also suppress any prompts with answer 'no'.
35092.
35093.HP
35094.BR \-\-yes
35095.br
35096Don't prompt for confirmation interactively but instead always assume the
35097answer is 'yes'. Take great care if you use this!
35098.
35099.HP
35100.BR \-t | \-\-test
35101.br
35102Run in test mode. Commands will not update metadata.
35103This is implemented by disabling all metadata writing but nevertheless
35104returning success to the calling function. This may lead to unusual
35105error messages in multi-stage operations if a tool relies on reading
35106back metadata it believes has changed but hasn't.
35107.
35108.HP
35109.BR \-\-driverloaded
35110.RB { y | n }
35111.br
35112Whether or not the device-mapper kernel driver is loaded.
35113If you set this to \fBn\fP, no attempt will be made to contact the driver.
35114.
35115.HP
35116.BR \-A | \-\-autobackup
35117.RB { y | n }
35118.br
35119Whether or not to metadata should be backed up automatically after a change.
35120You are strongly advised not to disable this!
35121See \fBvgcfgbackup\fP(8).
35122.
35123.HP
35124.BR \-P | \-\-partial
35125.br
35126When set, the tools will do their best to provide access to Volume Groups
35127that are only partially available (one or more Physical Volumes belonging
35128to the Volume Group are missing from the system). Where part of a logical
35129volume is missing, \fI\%/dev/ioerror\fP will be substituted, and you could use
35130\fBdmsetup\fP(8) to set this up to return I/O errors when accessed,
35131or create it as a large block device of nulls. Metadata may not be
35132changed with this option. To insert a replacement Physical Volume
35133of the same or large size use \fBpvcreate \-u\fP to set the uuid to
35134match the original followed by \fBvgcfgrestore\fP(8).
35135.
35136.HP
35137.BR \-S | \-\-select
35138.IR Selection
35139.br
35140For reporting commands, display only rows that match \fISelection\fP criteria.
35141All rows are displayed with the additional "selected" column (\fB-o selected\fP)
35142showing 1 if the row matches the \fISelection\fP and 0 otherwise. For non-reporting
35143commands which process LVM entities, the selection can be used to match items
35144to process. See \fBSelection\fP section in \fBlvmreport\fP(7) man page for more
35145information about the way the selection criteria are constructed.
35146.
35147.HP
35148.BR \-M | \-\-metadatatype
35149.IR Type
35150.br
35151Specifies which \fItype\fP of on-disk metadata to use, such as \fBlvm1\fP
35152or \fBlvm2\fP, which can be abbreviated to \fB1\fP or \fB2\fP respectively.
35153The default (\fBlvm2\fP) can be changed by setting \fBformat\fP
35154in the \fBglobal\fP section of the config file \fBlvm.conf\fP(5).
35155.
35156.HP
35157.BR \-\-ignorelockingfailure
35158.br
35159This lets you proceed with read-only metadata operations such as
35160\fBlvchange \-ay\fP and \fBvgchange \-ay\fP even if the locking module fails.
35161One use for this is in a system init script if the lock directory
35162is mounted read-only when the script runs.
35163.
35164.HP
35165.BR \-\-ignoreskippedcluster
35166.br
35167Use to avoid exiting with an non-zero status code if the command is run
35168without clustered locking and some clustered Volume Groups have to be
35169skipped over.
35170.
35171.HP
35172.BR \-\-readonly
35173.br
35174Run the command in a special read-only mode which will read on-disk
35175metadata without needing to take any locks. This can be used to peek
35176inside metadata used by a virtual machine image while the virtual
35177machine is running.
35178It can also be used to peek inside the metadata of clustered Volume
35179Groups when clustered locking is not configured or running. No attempt
35180will be made to communicate with the device-mapper kernel driver, so
35181this option is unable to report whether or not Logical Volumes are
35182actually in use.
35183.
35184.HP
35185.BR \-\-foreign
35186.br
35187Cause the command to access foreign VGs, that would otherwise be skipped.
35188It can be used to report or display a VG that is owned by another host.
35189This option can cause a command to perform poorly because lvmetad caching
35190is not used and metadata is read from disks.
35191.
35192.HP
35193.BR \-\-shared
35194.br
35195Cause the command to access shared VGs, that would otherwise be skipped
35196when lvmlockd is not being used. It can be used to report or display a
35197lockd VG without locking. Applicable only if LVM is compiled with lockd
35198support.
35199.
35200.HP
35201.BR \-\-addtag
35202.IR Tag
35203.br
35204Add the tag \fITag\fP to a PV, VG or LV.
35205Supply this argument multiple times to add more than one tag at once.
35206A tag is a word that can be used to group LVM2 objects of the same type
35207together.
35208Tags can be given on the command line in place of PV, VG or LV
35209arguments. Tags should be prefixed with @ to avoid ambiguity.
35210Each tag is expanded by replacing it with all objects possessing
35211that tag which are of the type expected by its position on the command line.
35212PVs can only possess tags while they are part of a Volume Group:
35213PV tags are discarded if the PV is removed from the VG.
35214As an example, you could tag some LVs as \fBdatabase\fP and others
35215as \fBuserdata\fP and then activate the database ones
35216with \fBlvchange \-ay @database\fP.
35217Objects can possess multiple tags simultaneously.
35218Only the new LVM2 metadata format supports tagging: objects using the
35219LVM1 metadata format cannot be tagged because the on-disk format does not
35220support it.
35221Characters allowed in tags are:
35222.BR A - Z
35223.BR a - z
35224.BR 0 - 9
35225.BR "_ + . -"
35226and as of version 2.02.78 the following characters are also accepted:
35227.BR "/ = ! : # &" .
35228.
35229.HP
35230.BR \-\-deltag
35231.IR Tag
35232.br
35233Delete the tag \fITag\fP from a PV, VG or LV, if it's present.
35234Supply this argument multiple times to remove more than one tag at once.
35235.
35236.HP
35237.BR \-\-alloc
35238.RB { anywhere | contiguous | cling | inherit | normal }
35239.br
35240Selects the allocation policy when a command needs to allocate
35241Physical Extents from the Volume Group.
35242Each Volume Group and Logical Volume has an allocation policy defined.
35243The default for a Volume Group is \fBnormal\fP which applies
35244common-sense rules such as not placing parallel stripes on the same
35245Physical Volume. The default for a Logical Volume is \fBinherit\fP
35246which applies the same policy as for the Volume Group. These policies can
35247be changed using \fBlvchange\fP(8) and \fBvgchange\fP(8) or overridden
35248on the command line of any command that performs allocation.
35249The \fBcontiguous\fP policy requires that new Physical Extents be placed adjacent
35250to existing Physical Extents.
35251The \fBcling\fP policy places new Physical Extents on the same Physical
35252Volume as existing Physical Extents in the same stripe of the Logical Volume.
35253If there are sufficient free Physical Extents to satisfy
35254an allocation request but \fBnormal\fP doesn't use them,
35255\fBanywhere\fP will - even if that reduces performance by
35256placing two stripes on the same Physical Volume.
35257.
35258.HP
35259.BR \-\-commandprofile
35260.IR ProfileName
35261.br
35262Selects the command configuration profile to use when processing an LVM command.
35263See also \fBlvm.conf\fP(5) for more information about \fBcommand profile config\fP and
35264the way it fits with other LVM configuration methods. Using \fB\-\-commandprofile\fP
35265option overrides any command profile specified via \fBLVM_COMMAND_PROFILE\fP
35266environment variable.
35267.
35268.HP
35269.BR \-\-metadataprofile
35270.IR ProfileName
35271.br
35272Selects the metadata configuration profile to use when processing an LVM command.
35273When using metadata profile during Volume Group or Logical Volume creation,
35274the metadata profile name is saved in metadata. When such Volume Group or Logical
35275Volume is processed next time, the metadata profile is automatically applied
35276and the use of \fB\-\-metadataprofile\fP option is not necessary. See also
35277\fBlvm.conf\fP(5) for more information about \fBmetadata profile config\fP and the
35278way it fits with other LVM configuration methods.
35279.
35280.HP
35281.BR \-\-profile
35282.IR ProfileName
35283.br
35284A short form of \fB\-\-metadataprofile\fP for \fBvgcreate\fP, \fBlvcreate\fP,
35285\fBvgchange\fP and \fBlvchange\fP command and a short form of \fB\-\-commandprofile\fP
35286for any other command (with the exception of \fBlvmconfig\fP command where the
35287\fB\-\-profile\fP has special meaning, see \fBlvmconfig\fP(8) for more information).
35288.
35289.HP
35290.BR \-\-reportformat
35291.IR {basic|json}
35292.br
35293Overrides current output format for reports which is defined globally by
35294\fBreport/output_format\fP configuration setting in \fBlvm.conf\fP(5).
35295The \fBbasic\fP format is the original format with columns and rows and
35296if there is more than one report per command, each report is prefixed
35297with report's name for identification. The \fBjson\fP stands for report
35298output in JSON format.
35299.HP
35300.BR \-\-config
35301.IR ConfigurationString
35302.br
35303Uses the ConfigurationString as direct string representation of the configuration
35304to override the existing configuration. The ConfigurationString is of exactly
35305the same format as used in any LVM configuration file. See \fBlvm.conf\fP(5)
35306for more information about \fBdirect config override on command line\fP and the
35307way it fits with other LVM configuration methods.
35308.
35309.SH VALID NAMES
35310.
35311The valid characters for VG and LV names are:
35312.BR a - z
35313.BR A - Z
35314.BR 0 - 9
35315.BR "+ _ . -"
35316.P
35317VG names cannot begin with a hyphen.
35318The name of a new LV also cannot begin with a hyphen. However, if the
35319configuration setting \fBmetadata/record_lvs_history\fP is enabled then an LV
35320name with a hyphen as a prefix indicates that, although the LV was
35321removed, it is still being tracked because it forms part of the history of at
35322least one LV that is still present. This helps to record the ancestry of
35323thin snapshots even after some links in the chain have been removed.
35324A reference to the historical LV 'lvol1' in VG 'vg00' would be 'vg00/-lvol1'
35325or just '-lvol1' if the VG is already set. (The latter form must be preceded
35326by '--' to terminate command line option processing before reaching this
35327argument.)
35328.P
35329There are also various reserved names that are used internally by lvm that can
35330not be used as LV or VG names. A VG cannot be called anything that exists in
35331\fI/dev/\fP at the time of creation, nor can it be called '.' or '..'.
35332An LV cannot be called '.', '..', 'snapshot' or 'pvmove'.
35333The LV name may also not contain any of the following strings:
35334\fR'_cdata', '_cmeta', '_corig', '_mlog', '_mimage', '_pmspare',
35335\fR'_rimage', '_rmeta', '_tdata', '_tmeta' or '_vorigin'.
35336A directory bearing the name of each Volume Group is created under
35337\fI/dev\fP when any of its Logical Volumes are activated.
35338Each active Logical Volume is accessible from this directory as a symbolic
35339link leading to a device node.
35340Links or nodes in \fI/dev/mapper\fP are intended only for internal use and
35341the precise format and escaping might change between releases and distributions.
35342Other software and scripts should use the
35343\fI/dev/VolumeGroupName/LogicalVolumeName\fP format to reduce the chance of needing
35344amendment when the software is updated. Should you need to process the node
35345names in /dev/mapper, you may use \fBdmsetup splitname\fP to separate out the
35346original VG, LV and internal layer names.
35347.P
35348.
35349.SH UNIQUE NAMES
35350.
35351
35352VG names should be unique. vgcreate will produce an error if the
35353specified VG name matches an existing VG name. However, there are cases
35354where different VGs with the same name can appear to LVM, e.g. after
35355moving disks or changing filters.
35356
35357When VGs with the same name exist, commands operating on all VGs will
35358include all of the VGs with the same name. If the ambiguous VG name is
35359specified on the command line, the command will produce an error. The
35360error states that multiple VGs exist with the specified name. To process
35361one of the VGs specifically, the --select option should be used with the
35362UUID of the intended VG: '--select vg_uuid=<uuid>'.
35363
35364An exception is if all but one of the VGs with the shared name is foreign
35365(see
35366.BR lvmsystemid (7).)
35367In this case, the one VG that is not foreign is assumed to be the intended
35368VG and is processed.
35369.P
35370LV names are unique within a VG. The name of an historical LV cannot be
35371reused until the historical LV has itself been removed or renamed.
35372
35373.
35374.SH ALLOCATION
35375.
35376When an operation needs to allocate Physical Extents for one or more
35377Logical Volumes, the tools proceed as follows:
35378
35379First of all, they generate the complete set of unallocated Physical Extents
35380in the Volume Group. If any ranges of Physical Extents are supplied at
35381the end of the command line, only unallocated Physical Extents within
35382those ranges on the specified Physical Volumes are considered.
35383
35384Then they try each allocation policy in turn, starting with the strictest
35385policy (\fBcontiguous\fP) and ending with the allocation policy specified
35386using \fB\-\-alloc\fP or set as the default for the particular Logical
35387Volume or Volume Group concerned. For each policy, working from the
35388lowest-numbered Logical Extent of the empty Logical Volume space that
35389needs to be filled, they allocate as much space as possible according to
35390the restrictions imposed by the policy. If more space is needed,
35391they move on to the next policy.
35392
35393The restrictions are as follows:
35394
35395\fBContiguous\fP requires that the physical location of any Logical
35396Extent that is not the first Logical Extent of a Logical Volume is
35397adjacent to the physical location of the Logical Extent immediately
35398preceding it.
35399
35400\fBCling\fP requires that the Physical Volume used for any Logical
35401Extent to be added to an existing Logical Volume is already in use by at
35402least one Logical Extent earlier in that Logical Volume. If the
35403configuration parameter \fBallocation/cling_tag_list\fP is defined, then two
35404Physical Volumes are considered to match if any of the listed tags is
35405present on both Physical Volumes. This allows groups of Physical
35406Volumes with similar properties (such as their physical location) to be
35407tagged and treated as equivalent for allocation purposes.
35408
35409When a Logical Volume is striped or mirrored, the above restrictions are
35410applied independently to each stripe or mirror image (leg) that needs
35411space.
35412
35413\fBNormal\fP will not choose a Physical Extent that shares the same Physical
35414Volume as a Logical Extent already allocated to a parallel Logical
35415Volume (i.e. a different stripe or mirror image/leg) at the same offset
35416within that parallel Logical Volume.
35417
35418When allocating a mirror log at the same time as Logical Volumes to hold
35419the mirror data, Normal will first try to select different Physical
35420Volumes for the log and the data. If that's not possible and the
35421.B allocation/mirror_logs_require_separate_pvs
35422configuration parameter is set to 0, it will then allow the log
35423to share Physical Volume(s) with part of the data.
35424
35425When allocating thin pool metadata, similar considerations to those of a
35426mirror log in the last paragraph apply based on the value of the
35427.B allocation/thin_pool_metadata_require_separate_pvs
35428configuration parameter.
35429
35430If you rely upon any layout behaviour beyond that documented here, be
35431aware that it might change in future versions of the code.
35432
35433For example, if you supply on the command line two empty Physical
35434Volumes that have an identical number of free Physical Extents available for
35435allocation, the current code considers using each of them in the order
35436they are listed, but there is no guarantee that future releases will
35437maintain that property. If it is important to obtain a specific layout
35438for a particular Logical Volume, then you should build it up through a
35439sequence of \fBlvcreate\fP(8) and \fBlvconvert\fP(8) steps such that the
35440restrictions described above applied to each step leave the tools no
35441discretion over the layout.
35442
35443To view the way the allocation process currently works in any specific
35444case, read the debug logging output, for example by adding \fB\-vvvv\fP to
35445a command.
35446.
35447.SH LOGICAL VOLUME TYPES
35448.
35449Some logical volume types are simple to create and can be done with a
35450single \fBlvcreate\fP(8) command. The linear and striped logical
35451volume types are an example of this. Other logical volume types may
35452require more than one command to create. The cache (\fBlvmcache\fP(7))
35453and thin provisioning (\fBlvmthin\fP(7)) types are examples of this.
35454.
35455.SH DIAGNOSTICS
35456.
35457All tools return a status code of zero on success or non-zero on failure.
35458The non-zero codes distinguish only between the broad categories of
35459unrecognised commands, problems processing the command line arguments
35460and any other failures. As LVM remains under active development, the
35461code used in a specific case occasionally changes between releases.
35462Message text may also change.
35463.
35464.SH ENVIRONMENT VARIABLES
35465.
35466.TP
35467.B HOME
35468Directory containing \fI.lvm_history\fP if the internal readline
35469shell is invoked.
35470.TP
35471.B LVM_OUT_FD
35472File descriptor to use for common output from LVM commands.
35473.TP
35474.B LVM_ERR_FD
35475File descriptor to use for error output from LVM commands.
35476.TP
35477.B LVM_REPORT_FD
35478File descriptor to use for report output from LVM commands.
35479.TP
35480.B LVM_COMMAND_PROFILE
35481Name of default command profile to use for LVM commands. This profile
35482is overriden by direct use of \fB\-\-commandprofile\fP command line option.
35483.TP
35484.B LVM_SYSTEM_DIR
35485Directory containing \fBlvm.conf\fP(5) and other LVM system files.
35486Defaults to "\fI#DEFAULT_SYS_DIR#\fP".
35487.TP
35488.B LVM_SUPPRESS_FD_WARNINGS
35489Suppress warnings about unexpected file descriptors passed into LVM.
35490.TP
35491.B LVM_VG_NAME
35492The Volume Group name that is assumed for
35493any reference to a Logical Volume that doesn't specify a path.
35494Not set by default.
35495.TP
35496.B LVM_LVMETAD_PIDFILE
35497Path to the file that stores the lvmetad process ID.
35498.TP
35499.B LVM_LVMETAD_SOCKET
35500Path to the socket used to communicate with lvmetad.
35501.TP
35502.B LVM_LVMPOLLD_PIDFILE
35503Path to the file that stores the lvmpolld process ID.
35504.TP
35505.B LVM_LVMPOLLD_SOCKET
35506Path to the socket used to communicate with lvmpolld..
35507.TP
35508.B LVM_LOG_FILE_EPOCH
35509A string of up to 32 letters appended to the log filename and
35510followed by the process ID and a startup timestamp using
35511this format string "_%s_%d_%llu". When set, each process logs to a
35512separate file.
35513.TP
35514.B LVM_LOG_FILE_MAX_LINES
35515If more than this number of lines are sent to the log file, the command gets
35516aborted. Automated tests use this to terminate looping commands.
35517.TP
35518.B LVM_EXPECTED_EXIT_STATUS
35519The status anticipated when the process exits. Use ">N" to match any
35520status greater than N. If the actual exit status matches and a log
35521file got produced, it is deleted.
35522.B LVM_LOG_FILE_EPOCH
35523and
35524.B LVM_EXPECTED_EXIT_STATUS
35525together allow automated test scripts to discard uninteresting log data.
35526.TP
35527.B LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES
35528Used to suppress warning messages when the configured locking is known
35529to be unavailable.
35530.TP
35531.B DM_ABORT_ON_INTERNAL_ERRORS
35532Abort processing if the code detects a non-fatal internal error.
35533.TP
35534.B DM_DISABLE_UDEV
35535Avoid interaction with udev. LVM will manage the relevant nodes in /dev
35536directly.
35537.
35538.SH FILES
35539.
35540.I #DEFAULT_SYS_DIR#/lvm.conf
35541.br
35542.I $HOME/.lvm_history
35543.
35544.SH SEE ALSO
35545.
35546.nh
35547.BR lvm.conf (5),
35548.BR lvmcache (7),
35549.BR lvmreport(7),
35550.BR lvmthin (7),
35551.BR clvmd (8),
35552.BR dmsetup (8),
35553.BR lvchange (8),
35554.BR lvcreate (8),
35555.BR lvdisplay (8),
35556.BR lvextend (8),
35557.BR lvmchange (8),
35558.BR lvmconfig (8),
35559.BR lvmdiskscan (8),
35560.BR lvreduce (8),
35561.BR lvremove (8),
35562.BR lvrename (8),
35563.BR lvresize (8),
35564.BR lvs (8),
35565.BR lvscan (8),
35566.BR pvchange (8),
35567.BR pvck (8),
35568.BR pvcreate (8),
35569.BR pvdisplay (8),
35570.BR pvmove (8),
35571.BR pvremove (8),
35572.BR pvs (8),
35573.BR pvscan (8),
35574.BR vgcfgbackup (8),
35575.BR vgchange (8),
35576.BR vgck (8),
35577.BR vgconvert (8),
35578.BR vgcreate (8),
35579.BR vgdisplay (8),
35580.BR vgextend (8),
35581.BR vgimport (8),
35582.BR vgimportclone (8),
35583.BR vgmerge (8),
35584.BR vgmknodes (8),
35585.BR vgreduce (8),
35586.BR vgremove (8),
35587.BR vgrename (8),
35588.BR vgs (8),
35589.BR vgscan (8),
35590.BR vgsplit (8),
35591.BR readline (3)
35592\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgscan.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002625\013062740170\0017606\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGSCAN 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
35593.SH NAME
35594vgscan \(em scan all disks for volume groups and rebuild caches
35595.SH SYNOPSIS
35596.B vgscan
35597.RB [ \-\-commandprofile
35598.IR ProfileName ]
35599.RB [ \-d | \-\-debug ]
35600.RB [ \-h | \-? | \-\-help ]
35601.RB [ \-\-ignorelockingfailure ]
35602.RB [ \-\-mknodes ]
35603.RB [ \-\-notifydbus ]
35604.RB [ \-P | \-\-partial ]
35605.RB [ \-\-reportformat
35606.RB { basic | json }]
35607.RB [ \-v | \-\-verbose ]
35608.SH DESCRIPTION
35609vgscan scans all SCSI, (E)IDE disks, multiple devices and a bunch
35610of other disk devices in the system looking for LVM physical volumes
35611and volume groups. Define a filter in \fBlvm.conf\fP(5) to restrict
35612the scan to avoid a CD ROM, for example.
35613.LP
35614In LVM2, vgscans take place automatically; but you might still need to
35615run one explicitly after changing hardware.
35616.SH OPTIONS
35617See \fBlvm\fP(8) for common options.
35618.TP
35619.B \-\-mknodes
35620Also checks the LVM special files in /dev that are needed for active
35621logical volumes and creates any missing ones and removes unused ones.
35622.TP
35623.B \-\-notifydbus
35624Send a notification to D-Bus. The command will exit with an error
35625if LVM is not built with support for D-Bus notification, or if the
35626notify_dbus config setting is disabled.
35627.TP
35628.B \-\-cache
35629Scan devices for LVM physical volumes and volume groups and instruct
35630the lvmetad daemon to update its cached state accordingly.
35631.SH SEE ALSO
35632.BR lvm (8),
35633.BR vgcreate (8),
35634.BR vgchange (8)
35635\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgexport.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001777\013062740170\0020212\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGEXPORT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
35636.SH NAME
35637vgexport \- make volume groups unknown to the system
35638.SH SYNOPSIS
35639.B vgexport
35640.RB [ \-a | \-\-all ]
35641.RB [ \-\-commandprofile
35642.IR ProfileName ]
35643.RB [ \-d | \-\-debug ]
35644.RB [ \-h | \-? | \-\-help ]
35645.RB [ \-\-reportformat
35646.RB { basic | json }]
35647.RB [ \-S | \-\-select
35648.IR Selection ]
35649.RB [ \-v | \-\-verbose ]
35650.RI [ VolumeGroupName ...]
35651.SH DESCRIPTION
35652vgexport allows you to make the inactive
35653.IR VolumeGroupName (s)
35654unknown to the system.
35655You can then move all the Physical Volumes in that Volume Group to
35656a different system for later
35657.BR vgimport (8).
35658Most LVM2 tools ignore exported Volume Groups.
35659vgexport clears the VG system ID, and vgimport sets the VG system ID
35660to match the host running vgimport (if the host has a system ID).
35661.SH OPTIONS
35662See \fBlvm\fP(8) for common options.
35663.TP
35664.BR \-a ", " \-\-all
35665Export all inactive Volume Groups.
35666.SH SEE ALSO
35667.BR lvm (8),
35668.BR pvscan (8),
35669.BR vgimport (8),
35670.BR vgscan (8),
35671.BR lvmsystemid (7)
35672\0LVM2.2.02.168/man/vgck.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001042\013062740170\0017247\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCK 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
35673.SH NAME
35674vgck \(em check volume group metadata
35675.SH SYNOPSIS
35676.B vgck
35677.RB [ \-\-commandprofile
35678.IR ProfileName ]
35679.RB [ \-d | \-\-debug ]
35680.RB [ \-h | \-? | \-\-help ]
35681.RB [ \-\-reportformat
35682.RB { basic | json }]
35683.RB [ \-v | \-\-verbose ]
35684.RI [ VolumeGroupName ...]
35685.SH DESCRIPTION
35686vgck checks LVM metadata for each named volume group for consistency.
35687.SH OPTIONS
35688See \fBlvm\fP(8) for common options.
35689.SH SEE ALSO
35690.BR lvm (8),
35691.BR vgcreate (8),
35692.BR vgchange (8),
35693.BR vgscan (8)
35694\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmreport.7.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000153675\013062740170\0020372\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "LVMREPORT" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
35695
35696.SH NAME
35697lvmreport \(em LVM reporting and related features
35698
35699.SH DESCRIPTION
35700LVM uses single reporting infrastructure that sets standard on LVM command's
35701output and it provides wide range of configuration settings and command line
35702options to customize report and filter the report's output.
35703
35704.SH Categorization based on reporting facility
35705
35706Based on functionality, commands which make use of the reporting infrastructure
35707are divided in two groups:
35708.IP \fBReport-oriented commands\fP
35709These commands inform about current LVM state and their primary role is to
35710display this information in compendious way. To make a distinction, we will
35711name this report as \fBmain report\fP. The set of report-only commands include:
35712pvs, vgs, lvs, pvdisplay, vgdisplay, lvdisplay, lvm devtypes, lvm fullreport.
35713For further information about main report, see \fBmain report specifics\fP.
35714.IP \fBProcessing-oriented commands\fP
35715These commands are responsible for changing LVM state and they do not contain
35716any main report as identified for report-oriented commands, they only perform
35717some kind of processing. The set of processing-oriented commands includes:
35718pvcreate, vgcreate, lvcreate, pvchange, vgchange, lvchange, pvremove, vgremove,
35719lvremove, pvresize, vgextend, vgreduce, lvextend, lvreduce, lvresize, lvrename,
35720pvscan, vgscan, lvscan, pvmove, vgcfgbackup, vgck, vgconvert, vgexport,
35721vgimport, vgmknodes.
35722
35723.RE
35724If enabled, so called \fBlog report\fP is either displayed solely
35725(for processing-oriented commands) or in addition to main report
35726(for report-oriented commands). The log report contains a log of operations,
35727messages and per-object status with complete object identification collected
35728during LVM command execution. See \fBlog report specifics\fP for more
35729information about this report type.
35730
35731
35732.SH Terms
35733
35734When describing reporting functionality and features in this text, we will
35735use terms \fBrow\fP and \fBcolumn\fP. By row we mean series of values reported
35736for single entity (for example single PV, VG or LV). Each value from the row
35737then belongs to a column of certain type. The columns have \fBcolumn headings\fP
35738which are short descriptions for the columns. The columns are referenced by
35739\fBcolumn names\fP. Please note that this text is also using term \fBfield\fP
35740interchangeably with the term \fBcolumn\fP. Most of the time the term columns
35741is abbreviated as \fBcol\fP in configuration.
35742
35743.SH Common report configuration settings and command line options
35744
35745There are common configuration settings and command line options which apply
35746to both \fBmain report\fP and \fBlog report\fP. Following lists contain all
35747of them, separated into groups based on their use.
35748
35749.RS
35750\fBCommon configuration settings:\fP
35751
35752.RS
35753
35754.IP \[bu] 3
35755Changing report output format, composition and other output modifiers:
35756.RS
35757.IP - 3
35758global/units
35759.IP - 3
35760global/suffix
35761.IP - 3
35762report/output_format
35763.IP - 3
35764report/compact_output
35765.IP - 3
35766report/compact_output_cols
35767.IP - 3
35768report/aligned
35769.IP - 3
35770report/headings
35771.IP - 3
35772report/separator
35773.IP - 3
35774report/list_item_separator
35775.IP - 3
35776report/prefixes
35777.IP - 3
35778report/quoted
35779.IP - 3
35780report/columns_as_rows
35781.IP - 3
35782report/binary_values_as_numeric
35783.IP - 3
35784report/time_format
35785.IP - 3
35786report/mark_hidden_devices
35787.IP - 3
35788report/two_word_unknown_device
35789.RE
35790
35791.IP \[bu] 3
35792Special settings
35793.RS
35794.IP - 3
35795report/buffered
35796.RE
35797
35798.RE
35799
35800.RE
35801
35802This document does not describe these settings in more detail - if you need
35803detailed information, including values which are accepted for the settings,
35804please run \fBlvmconfig --type default --withcomments <setting>\fP. There are
35805more configuration settings in addition to the common set listed above, but
35806they are specific to either \fBmain report\fP or \fBlog report\fP,
35807see \fBmain report specifics\fP and \fBlog report specifics\fP for
35808these settings. Besides configuring reports globally by using configuration
35809settings, there are also command line options you can use to extend, override
35810or further specify the report configuration.
35811
35812.RS
35813\fBCommon command line options:\fP
35814
35815.RS
35816
35817.IP \[bu] 3
35818Definition of the set set of fields to use
35819.RS
35820.IP - 3
35821--options|-o FieldSet
35822.br
35823Field set to use. See \fBmain report specifics\fP and
35824\fBlog report specifics\fP for information about field sets configured with
35825global configuratin settings that this option overrides.
35826.IP - 3
35827--options|-o+ FieldSet
35828.br
35829Fields to include to current field set. See \fBmain report specifics\fP\ and
35830\fBlog report specifics\fP for information about field sets configured with
35831global configuration settings that this option extends.
35832.IP - 3
35833--options|-o- FieldSet
35834.br
35835Fields to exclude from current field set. See \fBmain report specifics\fP and
35836\fBlog report specifics\fP for information about field sets configured with
35837global configuration settings that this option reduces.
35838.IP - 3
35839--options|-o# FieldSet
35840.br
35841Compaction of unused fields. Overrides report/compact_output_cols configuration
35842setting.
35843.RE
35844
35845.IP \[bu] 3
35846Sorting
35847.RS
35848.IP - 3
35849--sort|-O+ FieldSet
35850.br
35851Fields to sort by in ascending order. See \fBmain report specifics\fP and
35852\fBlog report specifics\fP for information about field sets configured with
35853global configuration settings that this option overrides.
35854.IP - 3
35855--sort|-O- FieldSet
35856.br
35857Fields to sort by in descending order. See \fBmain report specifics\fP and
35858\fBlog report specifics\fP for information about fields sets configured with
35859global configuration settings that this options overrides.
35860.RE
35861
35862.IP \[bu] 3
35863Selection
35864.RS
35865.IP - 3
35866--select|-S Selection
35867.br
35868Define selection criteria for report output. For \fBlog report\fP, this also
35869overrides log/command_log_selection configuration setting, see also
35870\fBlog report specifics\fP.
35871.RE
35872
35873.IP \[bu] 3
35874Changing output format and composition
35875.RS
35876.IP - 3
35877--reportformat
35878.br
35879Overrides report/output_format configuration setting.
35880.IP - 3
35881--aligned
35882.br
35883Overrides report/aligned configuration setting.
35884.IP - 3
35885--binary
35886.br
35887Overrides report/binary_values_as_numeric configuration setting.
35888.IP - 3
35889--nameprefixes
35890.br
35891Overrides report/prefixes configuration setting.
35892.IP - 3
35893--noheadings
35894.br
35895Overrides report/noheadings configuration setting.
35896.IP - 3
35897--nosuffix
35898.br
35899Overrides global/suffix configuration setting.
35900.IP - 3
35901--rows
35902.br
35903Overrides report/columns_as_rows configuration setting.
35904.IP - 3
35905--separator
35906.br
35907Overrides report/separator configuration setting.
35908.IP - 3
35909--units
35910.br
35911Overrides global/units configuration setting.
35912.IP - 3
35913--unquoted
35914.br
35915Overrides report/quoted configuration setting.
35916.RE
35917
35918.IP \[bu] 3
35919Special options
35920.RS
35921.IP - 3
35922--configreport \fBReportName\fP
35923.br
35924This defines the \fBReportName\fP for which any subsequent -o|--columns,
35925-O|--sort or -S|--select applies to. See also \fBmain report specifics\fP
35926and \fBlog report specifics\fP for possible \fBReportName\fP values.
35927.IP - 3
35928--logonly
35929.br
35930When an LVM command contains both \fBmain report\fP and \fBlog report\fP,
35931this option suppresses the \fBmain report\fP output and it causes the
35932\fBlog report\fP output to be displayed only.
35933.IP - 3
35934--unbuffered
35935.br
35936Overrides report/bufffered configuration setting.
35937.RE
35938
35939.RE
35940
35941.RE
35942
35943The \fBFieldSet\fP mentioned in the lists above is a set of field names where
35944each field name is delimited by "," character. Field set definition, sorting
35945and selection may be repeated on command line (-o+/-o- includes/excludes fields
35946to/from current list, for all the other repeatable options, the last value
35947typed for the option on the command line is used). The \fBSelection\fP
35948is a string with \fBselection criteria\fP, see also \fBSelection\fP paragraph
35949below for more information about constructing these criteria.
35950
35951
35952.SH Main report specifics
35953
35954The \fBmain report\fP currently encompasses these distinct subtypes, referenced
35955by their name - \fBReportName\fP as listed below. The command in parenthesis is
35956representative command that uses the main report subtype by default.
35957Each subtype has its own configuration setting for global field set definition
35958as well as sort field definition (listed below each individual \fBReportName\fP):
35959
35960.RS
35961
35962.IP \[bu] 3
35963\fBpv\fP representing report about Physical Volumes (\fBpvs\fP)
35964.RS
35965.IP - 3
35966report/pvs_cols
35967.IP - 3
35968report/pvs_sort
35969.RE
35970
35971.IP \[bu] 3
35972\fBpvseg\fP representing report about Physical Volume Segments (\fBpvs --segments\fP)
35973.RS
35974.IP - 3
35975report/pvseg_cols
35976.IP - 3
35977report/pvseg_sort
35978.RE
35979
35980.IP \[bu] 3
35981\fBvg\fP representing report about Volume Groups (\fBvgs\fP)
35982.RS
35983.IP - 3
35984report/vgs_cols
35985.IP - 3
35986report/vgs_sort
35987.RE
35988
35989.IP \[bu] 3
35990\fBlv\fP representing report about Logical Volumes (\fBlvs\fP)
35991.RS
35992.IP - 3
35993report/lvs_cols
35994.IP - 3
35995report/lvs_sort
35996.RE
35997
35998.IP \[bu] 3
35999\fBseg\fP representing report about Logical Volume Segments (\fBlvs --segments\fP)
36000.RS
36001.IP - 3
36002report/segs_cols
36003.IP - 3
36004report/segs_sort
36005.RE
36006
36007.IP \[bu] 3
36008\fBfull\fP representing report combining all of the above as a whole (\fBlvm fullreport\fP)
36009.RS
36010.IP - 3
36011report/pvs_cols_full
36012.IP - 3
36013report/pvs_sort_full
36014.IP - 3
36015report/pvsegs_cols_full
36016.IP - 3
36017report/pvseg_sort_full
36018.IP - 3
36019report/vgs_cols_full
36020.IP - 3
36021report/vgs_sort_full
36022.IP - 3
36023report/lvs_cols_full
36024.IP - 3
36025report/lvs_sort_full
36026.IP - 3
36027report/segs_cols_full
36028.IP - 3
36029report/segs_sort_full
36030.RE
36031
36032.IP \[bu] 3
36033\fBdevtype\fP representing report about device types (\fBlvm devtypes\fP)
36034.RS
36035.IP - 3
36036report/devtypes_cols
36037.IP - 3
36038report/devtypes_sort
36039.RE
36040
36041.RE
36042
36043Use \fBpvs, vgs, lvs -o help\fP or \fBlvm devtypes -o help\fP to get complete
36044list of fields that you can use for main report. The list of fields in the
36045help output is separated in groups based on which report type they belong to.
36046Note that LVM can change final report type used if fields from different
36047groups are combined together. Some of these combinations are not allowed in
36048which case LVM will issue an error.
36049
36050For all main report subtypes except \fBfull\fP, it's not necessary to use
36051\fB--configreport ReportName\fP to denote which report any subsequent
36052\fB-o, -O or -S\fP option applies to as they always apply to the single main
36053report type. Currently, \fBlvm fullreport\fP is the only command that
36054includes more than one \fBmain report\fP subtype. Therefore, the --configreport
36055is particularly suitable for the full report if you need to configure each of
36056its subreports in a different way.
36057
36058
36059.SH Log report specifics
36060
36061You can enable log report with \fBlog/report_command_log\fP configuration
36062setting - this functionality is disabled by default. The \fBlog report\fP
36063contains a log collected during LVM command execution and then the log is
36064displayed just like any other report known from main report. There is only one
36065log report subtype as shown below together with related configuration settings
36066for fields, sorting and selection:
36067
36068.RS
36069
36070.IP \[bu] 3
36071\fBlog\fP representing log report
36072.RS
36073.IP - 3
36074log/command_log_cols
36075.IP - 3
36076log/command_log_sort
36077.IP - 3
36078log/command_log_selection
36079.RE
36080
36081.RE
36082
36083You always need to use \fB--configreport log\fP together with \fB-o|--options,
36084-O|--sort or -S|--selection\fP to override configuration settings directly on
36085command line for \fBlog report\fP. When compared to \fBmain report\fP, in
36086addition to usual configuration settings for report fields and sorting, the
36087\fBlog report\fP has also configuration option for selection -
36088\fBreport/command_log_selection\fP. This configuration setting is provided for
36089convenience so it's not necessary to use \fB-S|--select\fP on command line
36090each time an LVM command is executed and we need the same selection criteria
36091to be applied for \fBlog report\fP. Default selection criteria used for
36092\fBlog report\fP are
36093\fBlog/command_log_selection="!(log_type=status && message=success)"\fP.
36094This means that, by default, \fBlog report\fP doesn't display status messages
36095about successful operation and it displays only rows with error, warning,
36096print-type messages and messages about failure states (for more information,
36097see \fBlog report content\fP below).
36098
36099.B Log report coverage
36100.br
36101Currently, when running LVM commands directly (not in LVM shell), the log
36102report covers command's \fBprocessing stage\fP which is the moment when LVM
36103entities are iterated and processed one by one. It does not cover any command
36104initialization nor command finalization stage. If there is any message issued
36105out of log report's coverage range, such message goes directly to output,
36106bypassing the \fBlog report\fP. By default, that is \fBstandard error output\fP
36107for error and warning messages and \fBstandard output\fP for common print-like
36108messages.
36109
36110When running LVM commands in \fBLVM shell\fP, the log report covers the whole
36111LVM command's execution, including command's \fBprocessing\fP as well as
36112\fBinitialization\fP and \fBfinalization stage\fP. So from this point of view,
36113the log report coverage is complete for executed LVM commands. Note that there
36114are still a few moments when LVM shell needs to initialize itself before it
36115even enters the main loop in which it executes LVM commands. Also, there is a
36116moment when \fBLVM shell\fP needs to prepare \fBlog report\fP properly for
36117next command executed in the shell and then, after the command's run, the shell
36118needs to display the log report for that recently executed command. If there
36119is a failure or any other message issued during this time, the LVM will bypass
36120\fBlog report\fP and display messages on output directly.
36121
36122For these reasons and for completeness, it's not possible to rely fully on
36123\fBlog report\fP as the only indicator of LVM command's status and the only
36124place where all messages issued during LVM command execution are collected.
36125You always need to check whether the command has not failed out of log
36126report's range by checking the non-report output too.
36127
36128To help with this, LVM can separate output which you can then redirect to
36129any \fBcustom file descriptor\fP that you prepare before running an LVM
36130command or LVM shell and then you make LVM to use these file descriptors
36131for different kinds of output by defining environment variables with file
36132descriptor numbers. See also \fBLVM_OUT_FD\fP, \fBLVM_ERR_FD\fP and
36133\fBLVM_REPORT_FD\fP environment variable description in \fBlvm\fP(8)
36134man page.
36135
36136Also note that, by default, reports use the same file descriptor as
36137common print-like messages, which is \fBstandard output\fP. If you plan to
36138use \fBlog report\fP in your scripts or any external tool, you should use
36139\fBLVM_OUT_FD\fP, \fBLVM_ERR_FD\fP and \fBLVM_REPORT_FD\fP to separate all
36140output types to different file descriptors. For example, with bash, that
36141would be:
36142
36143.RS
36144LVM_OUT_FD=3 LVM_ERR_FD=4 LVM_REPORT_FD=5 <lvm command> 3>out_file 4>err_file 5>report_file
36145.RE
36146
36147Where the <lvm_command> is either direct LVM command or LVM shell.
36148You can collect all three types of output in particular files then.
36149
36150.B Log report content
36151.br
36152Each item in the log report consists of these set of fields providing various
36153information:
36154
36155.RS
36156
36157.IP \[bu] 3
36158Basic information (mandatory):
36159.RS
36160.IP - 3
36161log_seq_num
36162.br
36163Item sequence number. The sequence number is unique for each log item and it
36164increases in the order of the log items as they appeared during LVM command
36165execution.
36166
36167.IP - 3
36168log_type
36169.br
36170Type of log for the item. Currently, these types are used:
36171.RS
36172.IP
36173\fBstatus\fP for any status information that is logged
36174.IP
36175\fBprint\fP for any common message printed while the log is collected
36176.IP
36177\fBerror\fP for any error message printed while the log is collected
36178.IP
36179\fBwarn\fP for any warning message printed while the log is collected
36180.RE
36181
36182.IP - 3
36183log_context
36184.br
36185Context of the log for the item. Currently, two contexts are identified:
36186.RS
36187.IP
36188\fBshell\fP for the log collected in the outermost code before and after
36189executing concrete LVM commands
36190.IP
36191\fBprocessing\fP for the log collected while processing LVM entities during
36192LVM command execution
36193.RE
36194
36195.RE
36196
36197.IP \[bu] 3
36198Message (mandatory):
36199.RS
36200.IP - 3
36201log_message
36202.br
36203Any message associated with current item. For \fBstatus\fP log type,
36204the message contains either \fBsuccess\fP or \fBfailure\fP denoting
36205current state. For \fBprint\fP, \fBerror\fP and \fBwarn\fP log types,
36206the message contains the exact message of that type that got issued.
36207.RE
36208
36209.IP \[bu] 3
36210Object information (used only if applicable):
36211.RS
36212.IP - 3
36213log_object_type field
36214.br
36215Type of the object processed. Currently, these object types are recognized:
36216.RS
36217.IP
36218\fBcmd\fP for command as a whole
36219.IP
36220\fBorphan\fP for processing group of PVs not in any VG yet
36221.IP
36222\fBpv\fP for PV processing
36223.IP
36224\fBlabel\fP for direct PV label processing (without VG metadata)
36225.IP
36226\fBvg\fP for VG processing
36227.IP
36228\fBlv\fP for LV processing
36229.RE
36230
36231.IP - 3
36232log_object_name
36233.br
36234Name of the object processed.
36235
36236.IP - 3
36237log_object_id
36238.br
36239ID of the object processed.
36240
36241.IP - 3
36242log_object_group
36243.br
36244A group where the processed object belongs to.
36245
36246.IP - 3
36247log_object_group_id
36248.br
36249An ID of a group where the processed object belongs to.
36250.RE
36251
36252.IP \[bu] 3
36253Numeric status (used only if applicable)
36254.RS
36255.IP - 3
36256log_errno
36257.br
36258Error number associated with current item.
36259.IP - 3
36260log_ret_code
36261.br
36262Rreturn code associated with current item.
36263.RE
36264
36265.RE
36266
36267
36268You can also run \fB<lvm_command> --configreport log -o help\fP to
36269to display complete list of fields that you may use for the \fBlog report\fP.
36270
36271.SH Selection
36272Selection is used for a report to display only rows that match
36273\fBselection criteria\fP. All rows are displayed with the additional
36274\fBselected\fP field (\fB-o selected\fP) displaying 1 if the row matches the
36275\fISelection\fP and 0 otherwise. The \fBselection criteria\fP are a set of
36276\fBstatements\fP combined by \fBlogical and grouping operators\fP.
36277The \fBstatement\fP consists of a \fBfield\fP name for which a set of valid
36278\fBvalues\fP is defined using \fBcomparison operators\fP. For complete list
36279of fields names that you can use in selection, see the output of
36280\fB<lvm_command> -S help\fP. The help output also contains type of values
36281that each field displays enclosed in brackets.
36282
36283.B List of operators recognized in selection criteria
36284.RS
36285.IP \[bu] 3
36286Comparison operators (cmp_op)
36287.RS
36288.IP
36289\fB=~\fP matching regular expression.
36290.IP
36291\fB!~\fP not matching regular expression.
36292.IP
36293\fB= \fP equal to.
36294.IP
36295\fB!=\fP not equal to.
36296.IP
36297\fB>=\fP greater than or equal to.
36298.IP
36299\fB> \fP greater than
36300.IP
36301\fB<=\fP less than or equal to.
36302.IP
36303\fB< \fP less than.
36304.RE
36305
36306.IP \[bu] 3
36307Binary logical operators (cmp_log)
36308.RS
36309.IP
36310\fB&&\fP all fields must match
36311.IP
36312\fB, \fP all fields must match
36313.IP
36314\fB||\fP at least one field must match
36315.IP
36316\fB# \fP at least one field must match
36317.RE
36318
36319.IP \[bu] 3
36320Unary logical operators
36321.RS
36322.IP
36323\fB! \fP logical negation
36324.RE
36325
36326.IP \[bu] 3
36327Grouping operators
36328.RS
36329.IP
36330\fB( \fP left parenthesis
36331.IP
36332\fB) \fP right parenthesis
36333.IP
36334\fB[ \fP list start
36335.IP
36336\fB] \fP list end
36337.IP
36338\fB{ \fP list subset start
36339.IP
36340\fB} \fP list subset end
36341.RE
36342
36343.RE
36344
36345.B Field types and selection operands
36346.br
36347Field type restricts the set of operators and values that you may use with
36348the field when defining selection criteria. You can see field type for each
36349field if you run \fB<lvm command> -S help\fP where you can find the type name
36350enclosed in square brackets. Currently, LVM recognizes these field types in
36351reports:
36352
36353.RS
36354.IP \[bu] 3
36355\fBstring\fP for set of characters (for each string field type, you can use
36356either string or regular expression - regex for the value used in selection
36357criteria)
36358.IP \[bu] 3
36359\fBstring list\fP for set of strings
36360.IP \[bu] 3
36361\fBnumber\fP for integer value
36362.IP \[bu] 3
36363\fBsize\fP for integer or floating point number with size unit suffix
36364(see also \fBlvcreate\fP(8) man page and description for "-L|--size"
36365option for the list of recognized suffixes)
36366.IP \[bu] 3
36367\fBpercent\fP for floating point number with or without "%" suffix
36368(e.g. 50 or 50%)
36369.IP \[bu] 3
36370\fBtime\fP for time values
36371.RE
36372
36373When using \fBstring list\fP in selection criteria, there are several ways
36374how LVM can match string list fields from report, depending on what list
36375grouping operator is used and what item separator is used within that set
36376of items. Also, note that order of items does not matter here.
36377
36378.RS
36379.IP \[bu] 3
36380\fBmatching the set strictly\fP where all items must match - use [ ], e.g.
36381["a","b","c"]
36382.IP \[bu] 3
36383\fBmatching a subset of the set\fP - use { } with "," or "&&" as item
36384delimiter, e.g. {"a","b","c"}
36385.IP \[bu] 3
36386\fBmatching an intersection with the set\fP - use { } with "#" or
36387"||" as item delimiter, e.g. {"a" || "b" || "c"}
36388.RE
36389
36390When using \fBtime\fP in your selection criteria, LVM can recognize various
36391time formats using standard, absolute or freeform expressions. For examples
36392demonstrating time expressions in selection criteria, see \fBEXAMPLES\fP section.
36393
36394.RS
36395
36396.IP \[bu] 3
36397\fBStandard time format\fP
36398
36399.RS
36400.IP - 3
36401date
36402.RS
36403.IP
36404YYYY-MM-DD
36405.IP
36406YYYY-MM, auto DD=1
36407.IP
36408YYYY, auto MM=01 and DD=01
36409.RE
36410
36411.IP - 3
36412time
36413.RS
36414.IP
36415hh:mm:ss
36416.IP
36417hh:mm, auto ss=0
36418.IP
36419hh, auto mm=0, auto ss=0
36420.RE
36421
36422.IP - 3
36423timezone
36424.RS
36425.IP
36426+hh:mm or -hh:mm
36427.IP
36428+hh or -hh
36429.RE
36430
36431The full date/time specification is YYYY-MM-DD hh:mm:ss. Users are able
36432to leave date/time parts from right to left. Whenever these parts are left out,
36433a range is assumed automatically with second granularity. For example:
36434
36435.RS
36436.IP
36437"2015-07-07 9:51" means range of "2015-07-07 9:51:00" - "2015-07-07 9:51:59".
36438.IP
36439"2015-07" means range of "2015-07-01 0:00:00" - "2015-07-31 23:59:59"
36440.IP
36441"2015" means range of "2015-01-01 0:00:00" - "2015-12-31 23:59:59"
36442.RE
36443
36444.RE
36445
36446.IP \[bu] 3
36447\fBAbsolute time format\fP
36448
36449Absolute time is defined as number of seconds since the Epoch
36450(1970:01:01 00:00 +00:00).
36451
36452.RS
36453.IP - 3
36454@seconds
36455.RE
36456
36457.IP \[bu] 3
36458\fBFreeform time format\fP
36459.RS
36460.IP - 3
36461weekday names ("Sunday" - "Saturday" or abbreviated as "Sun" - "Sat")
36462.IP - 3
36463labels for points in time ("noon", "midnight")
36464.IP - 3
36465labels for a day relative to current day ("today", "yesterday")
36466.IP - 3
36467points back in time with relative offset from today (N is a number)
36468.RS
36469.IP
36470"N" "seconds" / "minutes" / "hours" / "days" / "weeks" / "years" "ago"
36471.IP
36472"N" "secs" / "mins" / "hrs" ... "ago"
36473.IP
36474"N" "s" / "m" / "h" ... "ago"
36475.RE
36476.IP - 3
36477time specification either in hh:mm:ss format or with AM/PM suffixes
36478.IP - 3
36479month names ("January" - "December" or abbreviated as "Jan" - "Dec")
36480.RE
36481
36482.RE
36483
36484.B Informal grammar specification
36485.RS
36486.IP
36487.BR STATEMENT " = " column " cmp_op " VALUE " | " \%STATEMENT " log_op " STATEMENT " | " \%(STATEMENT) " | " \%!(STATEMENT)
36488.IP
36489.BR VALUE " = " [VALUE " log_op " VALUE]
36490.br
36491For list-based types: string list. Matches strictly.
36492The log_op must always be of one type within the whole list value.
36493.IP
36494.BR VALUE " = " {VALUE " log_op " VALUE}
36495.br
36496For list-based types: string list. Matches a subset.
36497The log_op must always be of one type within the whole list value.
36498.IP
36499.BR VALUE " = " value
36500.br
36501For scalar types: number, size, percent, string (or string regex).
36502.RE
36503
36504.SH EXAMPLES
36505
36506.SS Basic usage
36507
36508We start our examples with default configuration - \fBlvmconfig\fP(8) is
36509helpful command to display configuration settings which are currently used,
36510including all configuration related to reporting. We will use it throughout
36511examples below to display current configuration.
36512
36513.nf
36514# lvmconfig --type full global/units global/suffix \\
36515 report/output_format report/compact_output \\
36516 report/compact_output_cols report/aligned \\
36517 report/headings report/separator \\
36518 report/list_item_separator report/prefixes \\
36519 report/quoted report/columns_as_rows \\
36520 report/binary_values_as_numeric report/time_format \\
36521 report/mark_hidden_devices report/two_word_unknown_device \\
36522 report/buffered
36523units="h"
36524suffix=1
36525output_format="basic"
36526compact_output=0
36527compact_output_cols=""
36528aligned=1
36529headings=1
36530separator=" "
36531list_item_separator=","
36532prefixes=0
36533quoted=1
36534columns_as_rows=0
36535binary_values_as_numeric=0
36536time_format="%Y-%m-%d %T %z"
36537mark_hidden_devices=1
36538two_word_unknown_device=0
36539buffered=1
36540.fi
36541
36542Also, we start with simple LVM layout with two PVs (/dev/sda, /dev/sdb),
36543VG (vg) and two LVs (lvol0 and lvol1) in the VG. We display all possible
36544reports as single commands here, see also \fBpvs\fP(8), \fBvgs\fP(8),
36545\fBlvs\fP(8) man pages for more information. The field set for each report
36546type is configured with configuration settings as we already mentioned in
36547\fBmain report specifics\fP section in this man page.
36548
36549.nf
36550# lvmconfig --type full report/pvs_cols report/pvs_sort \\
36551 report/pvsegs_cols report/pvsegs_sort report/vgs_cols \\
36552 report/vgs_sort report/lvs_cols report/lvs_sort \\
36553 report/segs_cols report/segs_sort
36554pvs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
36555pvs_sort="pv_name"
36556pvsegs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,
36557 pvseg_start,pvseg_size"
36558pvsegs_sort="pv_name,pvseg_start"
36559vgs_cols="vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
36560vgs_sort="vg_name"
36561lvs_cols="lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,move_pv,
36562 mirror_log,copy_percent,convert_lv"
36563lvs_sort="vg_name,lv_name"
36564segs_cols="lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
36565segs_sort="vg_name,lv_name,seg_start"
36566.fi
36567
36568.nf
36569# pvs
36570 PV VG Fmt Attr PSize PFree
36571 /dev/sda vg lvm2 a-- 100.00m 88.00m
36572 /dev/sdb vg lvm2 a-- 100.00m 92.00m
36573
36574# pvs --segments
36575 PV VG Fmt Attr PSize PFree Start SSize
36576 /dev/sda vg lvm2 a-- 100.00m 88.00m 0 1
36577 /dev/sda vg lvm2 a-- 100.00m 88.00m 1 1
36578 /dev/sda vg lvm2 a-- 100.00m 88.00m 2 1
36579 /dev/sda vg lvm2 a-- 100.00m 88.00m 3 22
36580 /dev/sdb vg lvm2 a-- 100.00m 92.00m 0 1
36581 /dev/sdb vg lvm2 a-- 100.00m 92.00m 1 1
36582 /dev/sdb vg lvm2 a-- 100.00m 92.00m 2 23
36583
36584# vgs
36585 VG #PV #LV #SN Attr VSize VFree
36586 vg 2 2 0 wz--n- 200.00m 180.00m
36587
36588# lvs
36589 LV VG Attr LSize Pool Origin Move Log Cpy%Sync Convert
36590 lvol0 vg -wi-a----- 4.00m
36591 lvol1 vg rwi-a-r--- 4.00m 100.00
36592
36593# lvs --segments
36594 LV VG Attr #Str Type SSize
36595 lvol0 vg -wi-a----- 1 linear 4.00m
36596 lvol1 vg rwi-a-r--- 2 raid1 4.00m
36597.fi
36598
36599We will use \fBreport/lvs_cols\fP and \fBreport/lvs_sort\fP configuration
36600settings to define our own list of fields to use and to sort by that is
36601different from defaults. You can do this for other reports in same manner
36602with \fBreport/{pvs,pvseg,vgs,seg}_{cols,sort}\fP configuration settings.
36603Also note that in the example below, we don't display the "lv_time" field
36604even though we're using it for sorting - this is allowed.
36605
36606.nf
36607# lvmconfig --type full report/lvs_cols report/lvs_sort
36608lvs_cols="lv_name,lv_size,origin,pool_lv,copy_percent"
36609lvs_sort="-lv_time"
36610
36611# lvs
36612 LV LSize Origin Pool Cpy%Sync
36613 lvol1 4.00m 100.00
36614 lvol0 4.00m
36615.fi
36616
36617You can use \fB-o|--options\fP command line option to override current
36618configuration directly on command line.
36619
36620.nf
36621# lvs -o lv_name,lv_size
36622 LV LSize
36623 lvol1 4.00m
36624 lvol0 4.00m
36625
36626# lvs -o+lv_layout
36627 LV LSize Origin Pool Cpy%Sync Layout
36628 lvol1 4.00m 100.00 raid,raid1
36629 lvol0 4.00m linear
36630
36631# lvs -o-origin
36632 LV LSize Pool Cpy%Sync
36633 lvol1 4.00m 100.00
36634 lvol0 4.00m
36635
36636# lvs -o lv_name,lv_size,origin -o+lv_layout -o-origin -O lv_name
36637 LV LSize Layout
36638 lvol0 4.00m linear
36639 lvol1 4.00m raid,raid1
36640.fi
36641
36642You can obtain the same information with single command where all the
36643information about PVs, PV segments, LVs and LV segments are obtained
36644per VG under a single VG lock for consistency, see also \fBlvm fullreport\fP(8)
36645man page for more information. The fullreport has its own configuration
36646settings to define field sets to use, similar to individual reports as
36647displayed above, but configuration settings have "_full" suffix now.
36648This way, it's possible to configure different sets of fields to display
36649and to sort by for individual reports as well as the full report.
36650
36651.nf
36652# lvmconfig --type full report/pvs_cols_full \\
36653 report/pvs_sort_full report/pvsegs_cols_full \\
36654 report/pvsegs_sort_full report/vgs_cols_full \\
36655 report/vgs_sort_full report/lvs_cols_full \\
36656 report/lvs_sort_full report/segs_cols_full \\
36657 report/segs_sort_full
36658pvs_cols_full="pv_name,vg_name"
36659pvs_sort_full="pv_name"
36660pvsegs_cols_full="pv_name,pvseg_start,pvseg_size"
36661pvsegs_sort_full="pv_uuid,pvseg_start"
36662vgs_cols_full="vg_name"
36663vgs_sort_full="vg_name"
36664lvs_cols_full="lv_name,vg_name"
36665lvs_sort_full="vg_name,lv_name"
36666segs_cols_full="lv_name,seg_start,seg_size"
36667segs_sort_full="lv_uuid,seg_start"
36668.fi
36669
36670.nf
36671# lvm fullreport
36672 VG
36673 vg
36674 PV VG
36675 /dev/sda vg
36676 /dev/sdb vg
36677 LV VG
36678 lvol0 vg
36679 lvol1 vg
36680 PV Start SSize
36681 /dev/sda 0 1
36682 /dev/sda 1 1
36683 /dev/sda 2 1
36684 /dev/sda 3 22
36685 /dev/sdb 0 1
36686 /dev/sdb 1 1
36687 /dev/sdb 2 23
36688 LV Start SSize
36689 lvol0 0 4.00m
36690 lvol1 0 4.00m
36691.fi
36692
36693.SS Automatic output compaction
36694
36695If you look at the lvs output above, you can see that the report also contains
36696fields for which there is no information to display (e.g. the columns under
36697"Origin" and "Pool" heading - the "origin" and "pool_lv" fields). LVM can
36698automatically compact report output so such fields are not included in final
36699output. To enable this feature and to compact all fields, use
36700\fBreport/compact_output=1\fP in your configuration.
36701
36702.nf
36703# lvmconfig --type full report/compact_output
36704compact_output=1
36705
36706# lvs
36707 LV LSize Cpy%Sync
36708 lvol1 4.00m 100.00
36709 lvol0 4.00m
36710
36711# lvs vg/lvol0
36712 LV LSize
36713 lvol0 4.00m
36714.fi
36715
36716Alternatively, you can define which fields should be compacted by configuring
36717\fBreport/compact_output_cols\fP configuration setting (or \fB-o|--options #\fP
36718command line option).
36719
36720.nf
36721# lvmconfig --type full report/compact_output report/compact_output_cols
36722compact_output=0
36723compact_output_cols="origin"
36724
36725# lvs
36726 LV LSize Pool Cpy%Sync
36727 lvol1 4.00m 100.00
36728 lvol0 4.00m
36729
36730# lvs vg/lvol0
36731 LV LSize Pool
36732 lvol0 4.00m
36733
36734# lvs -o#pool_lv
36735 LV LSize Origin Cpy%Sync
36736 lvol1 4.00m 100.00
36737 lvol0 4.00m
36738.fi
36739
36740We will use \fBreport/compact_output=1\fP for subsequent examples.
36741
36742.SS Further formatting options
36743
36744By default, LVM displays sizes in reports in human-readable form which means
36745that the most suitable unit is used so it's easy to read. You can use
36746\fBreport/units\fP configuration setting (or \fB--units\fP option directly
36747on command line) and \fBreport/suffix\fP
36748configuration setting (or \fB--nosuffix\fP command line option) to change this.
36749
36750.nf
36751# lvs --units b --nosuffix
36752 LV LSize Cpy%Sync
36753 lvol1 4194304 100.00
36754 lvol0 4194304
36755.fi
36756
36757If you want to configure whether report headings are displayed or not, use
36758\fBreport/headings\fP configuration settings (or \fB--noheadings\fP command
36759line option).
36760
36761.nf
36762# lvs --noheadings
36763 lvol1 4.00m 100.00
36764 lvol0 4.00m
36765.fi
36766
36767In some cases, it may be useful to display report content as key=value pairs
36768where key here is actually the field name. Use \fBreport/prefixes\fP
36769configuration setting (or \fB--nameprefixes\fP command line option) to switch
36770between standard output and the key=value output. The key=value pair is the
36771output that is suitable for use in scripts and for other tools to parse easily.
36772Usually, you also don't want to display headings with the output that has these
36773key=value pairs.
36774
36775.nf
36776# lvs --noheadings --nameprefixes
36777 LVM2_LV_NAME='lvol1' LVM2_LV_SIZE='4.00m' LVM2_COPY_PERCENT='100.00'
36778 LVM2_LV_NAME='lvol0' LVM2_LV_SIZE='4.00m' LVM2_COPY_PERCENT=''
36779.fi
36780
36781To define whether quotation marks in key=value pairs should be used or not,
36782use \fBreport/quoted\fP configuration setting (or \fB--unquoted\fP command
36783line option).
36784
36785.nf
36786# lvs --noheadings --nameprefixes --unquoted
36787 LVM2_LV_NAME=lvol1 LVM2_LV_SIZE=4.00m LVM2_COPY_PERCENT=100.00
36788 LVM2_LV_NAME=lvol0 LVM2_LV_SIZE=4.00m LVM2_COPY_PERCENT=
36789.fi
36790
36791For easier parsing, you can even transpose the report so each column now
36792becomes a row in the output. This is done with \fBreport/output_as_rows\fP
36793configuration setting (or \fB--rows\fP command line option).
36794
36795.nf
36796# lvs --noheadings --nameprefixes --unquoted --rows
36797 LVM2_LV_NAME=lvol1 LVM2_LV_NAME=lvol0
36798 LVM2_LV_SIZE=4.00m LVM2_LV_SIZE=4.00m
36799 LVM2_COPY_PERCENT=100.00 LVM2_COPY_PERCENT=
36800.fi
36801
36802Use \fBreport/separator\fP configuration setting (or \fB--separator\fP command
36803line option) to define your own field separator to use.
36804
36805.nf
36806# lvs --noheadings --nameprefixes --unquoted --separator " | "
36807 LVM2_LV_NAME=lvol1 | LVM2_LV_SIZE=4.00m | LVM2_COPY_PERCENT=100.00
36808 LVM2_LV_NAME=lvol0 | LVM2_LV_SIZE=4.00m | LVM2_COPY_PERCENT=
36809.fi
36810
36811If you are using your own separator, the columns in the output are not aligned
36812by default. Use \fBreport/aligned\fP configuration setting (or \fB--aligned\fP
36813command line option) for LVM to add extra spaces in report to align the output
36814properly.
36815
36816.nf
36817# lvs --separator " | "
36818 LV | LSize | Cpy%Sync
36819 lvol1 | 4.00m | 100.00
36820 lvol0 | 4.00m |
36821
36822# lvs --separator " | " --aligned
36823 LV | LSize | Cpy%Sync
36824 lvol1 | 4.00m | 100.00
36825 lvol0 | 4.00m |
36826.fi
36827
36828Let's display one one more field in addition ("lv_tags" in this example)
36829for the lvs report output.
36830
36831.nf
36832# lvs -o+lv_tags
36833 LV LSize Cpy%Sync LV Tags
36834 lvol1 4.00m 100.00
36835 lvol0 4.00m tagA,tagB
36836.fi
36837
36838The "LV Tags" column in the example above displays two list values,
36839separated by "," character for LV lvol0. If you need different list item
36840separator, use \fBreport/list_item_separator\fP configuration setting its
36841definition.
36842
36843.nf
36844# lvmconfig --type full report/list_item_separator
36845list_item_separator=";"
36846
36847# lvs -o+tags
36848 LV LSize Cpy%Sync LV Tags
36849 lvol1 4.00m 100.00
36850 lvol0 4.00m tagA;tagB
36851.fi
36852
36853But let's still use the original "," character for list_item_separator
36854for subsequent examples.
36855
36856Format for any of time values displayed in reports can be configured with
36857\fBreport/time_format\fP configuretion setting. By default complete date
36858and time is displayed, including timezone.
36859
36860.nf
36861# lvmconfig --type full report/time_format
36862time_format="%Y-%m-%d %T %z"
36863
36864# lvs -o+time
36865 LV LSize Cpy%Sync CTime
36866 lvol1 4.00m 100.00 2016-08-29 12:53:36 +0200
36867 lvol0 4.00m 2016-08-29 10:15:17 +0200
36868.fi
36869
36870We can change time format in similar way as we do when using \fBdate\fP(1)
36871command or \fBstrftime\fP(3) function
36872(\fBlvmconfig --type default --withcomments report/time_format\fP will
36873give you complete list of available formatting options). In the example
36874below, we decided to use %s for number of seconds since Epoch (1970-01-01 UTC).
36875
36876.nf
36877# lvmconfig --type full report/time_format
36878time_format="%s"
36879
36880# lvs
36881 LV Attr LSize Cpy%Sync LV Tags CTime
36882 lvol1 rwi-a-r--- 4.00m 100.00 1472468016
36883 lvol0 -wi-a----- 4.00m tagA,tagB 1472458517
36884.fi
36885
36886The \fBlvs\fP does not display hidden LVs by default - to include these LVs
36887in the output, you need to use \fB-a|--all\fP command line option. Names for
36888these hidden LVs are displayed within square brackets.
36889
36890.nf
36891# lvs -a
36892 LV LSize Cpy%Sync
36893 lvol1 4.00m 100.00
36894 [lvol1_rimage_0] 4.00m
36895 [lvol1_rmeta_0] 4.00m
36896 [lvol1_rimage_1] 4.00m
36897 [lvol1_rmeta_1] 4.00m
36898 lvol0 4.00m
36899.fi
36900
36901You can configure LVM to display the square brackets for hidden LVs or not with
36902\fBreport/mark_hidden_devices\fP configuration setting.
36903
36904.nf
36905# lvmconfig --type full report/mark_hidden_devices
36906mark_hidden_devices=0
36907
36908# lvs -a
36909 LV LSize Cpy%Sync
36910 lvol1 4.00m 100.00
36911 lvol1_rimage_0 4.00m
36912 lvol1_rmeta_0 4.00m
36913 lvol1_rimage_1 4.00m
36914 lvol1_rmeta_1 4.00m
36915 lvol0 4.00m
36916.fi
36917
36918It's not recommended to use LV marks for hidden devices to decide whether the
36919LV is the one to use by end users or not. Please, use "lv_role" field instead
36920which can report whether the LV is "public" or "private". The private LVs are
36921used by LVM only and they should not be accessed directly by end users.
36922
36923.nf
36924# lvs -a -o+lv_role
36925 LV LSize Cpy%Sync Role
36926 lvol1 4.00m 100.00 public
36927 lvol1_rimage_0 4.00m private,raid,image
36928 lvol1_rmeta_0 4.00m private,raid,metadata
36929 lvol1_rimage_1 4.00m private,raid,image
36930 lvol1_rmeta_1 4.00m private,raid,metadata
36931 lvol0 4.00m public
36932.fi
36933
36934Some of the reporting fields that LVM reports are of binary nature. For such
36935fields, it's either possible to display word representation of the value
36936(this is used by default) or numeric value (0/1 or -1 in case the value is
36937undefined).
36938
36939.nf
36940# lvs -o+lv_active_locally
36941 LV LSize Cpy%Sync ActLocal
36942 lvol1 4.00m 100.00 active locally
36943 lvol0 4.00m active locally
36944.fi
36945
36946We can change the way how these binary values are displayed with
36947\fBreport/binary_values_as_numeric\fP configuration setting.
36948
36949.nf
36950# lvmconfig --type full report/binary_values_as_numeric
36951binary_values_as_numeric=1
36952
36953# lvs -o+lv_active_locally
36954 LV LSize Cpy%Sync ActLocal
36955 lvol1 4.00m 100.00 1
36956 lvol0 4.00m 1
36957.fi
36958
36959.SS Changing output format
36960
36961LVM can output reports in different formats - use \fBreport/output_format\fP
36962configuration setting (or \fB--reportformat\fP command line option) to swith
36963the report output format. Currently, LVM supports \fB"basic"\fP (all the examples
36964we used above used this format) and \fB"JSON"\fP output format.
36965
36966.nf
36967# lvs -o lv_name,lv_size --reportformat json
36968 {
36969 "report": [
36970 {
36971 "lv": [
36972 {"lv_name":"lvol1", "lv_size":"4.00m"},
36973 {"lv_name":"lvol0", "lv_size":"4.00m"}
36974 ]
36975 }
36976 ]
36977 }
36978.fi
36979
36980Note that some configuration settings and command line options have no
36981effect with certain report formats. For example, with \fBJSON\fP output,
36982it doesn't have any meaning to use \fBreport/aligned\fP (\fB--aligned\fP),
36983\fBreport/noheadings\fP (\fB--noheadings\fP), \fBreport/columns_as_rows\fP
36984(\fB--rows\fP) or \fBreport/buffered\fP (\fB--unbuffered\fP). All these
36985configuration settings and command line options are ignored if using the
36986\fBJSON\fP report output format.
36987
36988.SS Selection
36989
36990If you need to select only specific rows from report, you can use LVM's
36991report selection feature. If you call \fB<lvm_command> -S help\fP, you'll get
36992quick help on selection. The help contains list of all fields that LVM
36993can use in reports together with its type enclosed in square brackets.
36994The example below contains a line from lvs -S help.
36995
36996.nf
36997# lvs -S help
36998 ...
36999 lv_size - Size of LV in current units. [size]
37000 ...
37001.fi
37002
37003This line tells you you that the "lv_size" field is of "size" type. If you
37004look at the bottom of the help output, you can see section about
37005"Selection operators" and its "Comparison operators".
37006
37007.nf
37008# lvs -S help
37009 ...
37010Selection operators
37011-------------------
37012Comparison operators:
37013 =~ - Matching regular expression. [regex]
37014 !~ - Not matching regular expression. [regex]
37015 = - Equal to. [number, size, percent, string, string list, time]
37016 != - Not equal to. [number, size, percent, string, string_list, time]
37017 >= - Greater than or equal to. [number, size, percent, time]
37018 > - Greater than. [number, size, percent, time]
37019 <= - Less than or equal to. [number, size, percent, time]
37020 < - Less than. [number, size, percent, time]
37021since - Since specified time (same as '>='). [time]
37022after - After specified time (same as '>'). [time]
37023until - Until specified time (same as '<='). [time]
37024before - Before specified time (same as '<'). [time]
37025 ...
37026.fi
37027
37028Here you can match comparison operators that you may use with the "lv_size"
37029field which is of type "size" - it's =, !=, >=, >, <= and <. You can find
37030applicable comparison operators for other fields and other field types the
37031same way.
37032
37033To demostrate selection functionality in LVM, we will create more LVs in
37034addition to lvol0 and lvol1 we used in our previous examples.
37035
37036.nf
37037# lvs -o name,size,origin,snap_percent,tags,time
37038 LV LSize Origin Snap% LV Tags CTime
37039 lvol4 4.00m lvol2 24.61 2016-09-09 16:57:44 +0200
37040 lvol3 4.00m lvol2 5.08 2016-09-09 16:56:48 +0200
37041 lvol2 8.00m tagA,tagC,tagD 2016-09-09 16:55:12 +0200
37042 lvol1 4.00m 2016-08-29 12:53:36 +0200
37043 lvol0 4.00m tagA,tagB 2016-08-29 10:15:17 +0200
37044.fi
37045
37046When selecting size and percent fields, we don't need to use units.
37047For sizes, default "m" (for MiB) is used - this is the same behaviour
37048as already used for LVM commands when specifying sizes (e.g. lvcreate -L).
37049For percent fields, "%" is assumed automatically if it's not specified.
37050The example below also demonstrates how several criteria can be combined
37051together.
37052
37053.nf
37054# lvs -o name,size,snap_percent -S 'size=8m'
37055 LV LSize
37056 lvol2 8.00m
37057
37058# lvs -o name,size,snap_percent -S 'size=8'
37059 LV LSize
37060 lvol2 8.00m
37061
37062# lvs -o name,size,snap_percent -S 'size < 5000k'
37063 LV LSize Snap%
37064 lvol4 4.00m 24.61
37065 lvol3 4.00m 5.08
37066 lvol1 4.00m
37067 lvol0 4.00m
37068
37069# lvs -o name,size,snap_percent -S 'size < 5000k && snap_percent > 20'
37070 LV LSize Snap%
37071 lvol4 4.00m 24.61
37072
37073# lvs -o name,size,snap_percent \\
37074 -S '(size < 5000k && snap_percent > 20%) || name=lvol2'
37075 LV LSize Snap%
37076 lvol4 4.00m 24.61
37077 lvol2 8.00m
37078.fi
37079
37080You can also use selection together with processing-oriented commands.
37081
37082.nf
37083# lvchange --addtag test -S 'size < 5000k'
37084 Logical volume vg/lvol1 changed.
37085 Logical volume vg/lvol0 changed.
37086 Logical volume vg/lvol3 changed.
37087 Logical volume vg/lvol4 changed.
37088
37089# lvchange --deltag test -S 'tags = test'
37090 Logical volume vg/lvol1 changed.
37091 Logical volume vg/lvol0 changed.
37092 Logical volume vg/lvol3 changed.
37093 Logical volume vg/lvol4 changed.
37094.fi
37095
37096LVM can recognize more complex values used in selection criteria for
37097string list and time field types. For string lists, you can match
37098whole list strictly, its subset or intersection. Let's take "lv_tags"
37099field as an example - we select only rows which contain "tagA" within
37100tags field. We're using { } to denote that we're interested in subset
37101that matches. If the subset has only one item, we can leave out { }.
37102
37103.nf
37104# lvs -o name,tags -S 'tags={tagA}'
37105 LV LV Tags
37106 lvol2 tagA,tagC,tagD
37107 lvol0 tagA,tagB
37108
37109# lvs -o name,tags -S 'tags=tagA'
37110 LV LV Tags
37111 lvol2 tagA,tagC,tagD
37112 lvol0 tagA,tagB
37113.fi
37114
37115Depending on whether we use "&&" (or ",") or "||" ( or "#") as delimiter
37116for items in the set we define in selection criterion for string list,
37117we either match subset ("&&" or ",") or even intersection ("||" or "#").
37118
37119.nf
37120# lvs -o name,tags -S 'tags={tagA,tagC,tagD}'
37121 LV LV Tags
37122 lvol2 tagA,tagC,tagD
37123
37124# lvs -o name,tags -S 'tags={tagA || tagC || tagD}'
37125 LV LV Tags
37126 lvol2 tagA,tagC,tagD
37127 lvol0 tagA,tagB
37128.fi
37129
37130To match the complete set, use [ ] with "&&" (or ",") as delimiter for items.
37131Also note that the order in which we define items in the set is not relevant.
37132
37133.nf
37134# lvs -o name,tags -S 'tags=[tagA]'
37135
37136# lvs -o name,tags -S 'tags=[tagB,tagA]'
37137 LV LV Tags
37138 lvol0 tagA,tagB
37139.fi
37140
37141If you use [ ] with "||" (or "#"), this is exactly the same as using { }.
37142
37143.nf
37144# lvs -o name,tags -S 'tags=[tagA || tagC || tagD]'
37145 LV LV Tags
37146 lvol2 tagA,tagC,tagD
37147 lvol0 tagA,tagB
37148.fi
37149
37150To match a set with no items, use "" to denote this (note that we have
37151output compaction enabled so the "LV Tags" column is not displayed in
37152the example below because it's blank and so it gets compacted).
37153
37154.nf
37155# lvs -o name,tags -S 'tags=""'
37156 LV
37157 lvol4
37158 lvol3
37159 lvol1
37160
37161# lvs -o name,tags -S 'tags!=""'
37162 LV LV Tags
37163 lvol2 tagA,tagC,tagD
37164 lvol0 tagA,tagB
37165.fi
37166
37167When doing selection based on time fields, we can use either standard,
37168absolute or freeform time expressions in selection criteria. Examples below
37169are using standard forms.
37170
37171.nf
37172# lvs -o name,time
37173 LV CTime
37174 lvol4 2016-09-09 16:57:44 +0200
37175 lvol3 2016-09-09 16:56:48 +0200
37176 lvol2 2016-09-09 16:55:12 +0200
37177 lvol1 2016-08-29 12:53:36 +0200
37178 lvol0 2016-08-29 10:15:17 +0200
37179
37180# lvs -o name,time -S 'time since "2016-09-01"'
37181 LV CTime
37182 lvol4 2016-09-09 16:57:44 +0200
37183 lvol3 2016-09-09 16:56:48 +0200
37184 lvol2 2016-09-09 16:55:12 +0200
37185
37186# lvs -o name,time -S 'time since "2016-09-09 16:56"'
37187 LV CTime
37188 lvol4 2016-09-09 16:57:44 +0200
37189 lvol3 2016-09-09 16:56:48 +0200
37190
37191# lvs -o name,time -S 'time since "2016-09-09 16:57:30"'
37192 LV CTime
37193 lvol4 2016-09-09 16:57:44 +0200
37194
37195# lvs -o name,time \\
37196 -S 'time since "2016-08-29" && time until "2016-09-09 16:55:12"'
37197 LV CTime
37198 lvol2 2016-09-09 16:55:12 +0200
37199 lvol1 2016-08-29 12:53:36 +0200
37200 lvol0 2016-08-29 10:15:17 +0200
37201
37202# lvs -o name,time \\
37203 -S 'time since "2016-08-29" && time before "2016-09-09 16:55:12"'
37204 LV CTime
37205 lvol1 2016-08-29 12:53:36 +0200
37206 lvol0 2016-08-29 10:15:17 +0200
37207.fi
37208
37209Time operators have synonyms: ">=" for since, "<=" for until,
37210">" for "after" and "<" for "before".
37211
37212.nf
37213# lvs -o name,time \\
37214 -S 'time >= "2016-08-29" && time <= "2016-09-09 16:55:30"'
37215 LV CTime
37216 lvol2 2016-09-09 16:55:12 +0200
37217 lvol1 2016-08-29 12:53:36 +0200
37218 lvol0 2016-08-29 10:15:17 +0200
37219
37220# lvs -o name,time \\
37221 -S 'time since "2016-08-29" && time < "2016-09-09 16:55:12"'
37222 LV CTime
37223 lvol1 2016-08-29 12:53:36 +0200
37224 lvol0 2016-08-29 10:15:17 +0200
37225.fi
37226
37227Example below demonstrates using absolute time expression.
37228
37229.nf
37230# lvs -o name,time --config report/time_format="%s"
37231 LV CTime
37232 lvol4 1473433064
37233 lvol3 1473433008
37234 lvol2 1473432912
37235 lvol1 1472468016
37236 lvol0 1472458517
37237
37238# lvs -o name,time -S 'time since @1473433008'
37239 LV CTime
37240 lvol4 2016-09-09 16:57:44 +0200
37241 lvol3 2016-09-09 16:56:48 +0200
37242.fi
37243
37244Examples below demonstrates using freeform time expressions.
37245
37246.nf
37247# lvs -o name,time -S 'time since "2 weeks ago"'
37248 LV CTime
37249 lvol4 2016-09-09 16:57:44 +0200
37250 lvol3 2016-09-09 16:56:48 +0200
37251 lvol2 2016-09-09 16:55:12 +0200
37252 lvol1 2016-08-29 12:53:36 +0200
37253 lvol0 2016-08-29 10:15:17 +0200
37254
37255# lvs -o name,time -S 'time since "1 week ago"'
37256 LV CTime
37257 lvol4 2016-09-09 16:57:44 +0200
37258 lvol3 2016-09-09 16:56:48 +0200
37259 lvol2 2016-09-09 16:55:12 +0200
37260
37261# lvs -o name,time -S 'time since "2 weeks ago"'
37262 LV CTime
37263 lvol1 2016-08-29 12:53:36 +0200
37264 lvol0 2016-08-29 10:15:17 +0200
37265
37266# lvs -o name,time -S 'time before "1 week ago"'
37267 LV CTime
37268 lvol1 2016-08-29 12:53:36 +0200
37269 lvol0 2016-08-29 10:15:17 +0200
37270
37271# lvs -o name,time -S 'time since "68 hours ago"'
37272 LV CTime
37273 lvol4 2016-09-09 16:57:44 +0200
37274 lvol3 2016-09-09 16:56:48 +0200
37275 lvol2 2016-09-09 16:55:12 +0200
37276
37277# lvs -o name,time -S 'time since "1 year 3 months ago"'
37278 LV CTime
37279 lvol4 2016-09-09 16:57:44 +0200
37280 lvol3 2016-09-09 16:56:48 +0200
37281 lvol2 2016-09-09 16:55:12 +0200
37282 lvol1 2016-08-29 12:53:36 +0200
37283 lvol0 2016-08-29 10:15:17 +0200
37284.fi
37285
37286.SS Command log reporting
37287
37288As described in \fBcategorization based on reporting facility\fP section
37289at the beginning of this document, both \fBreport-oriented\fP and
37290\fBprocessing-oriented\fP LVM commands can report the command log if
37291this is enabled with \fBlog/report_command_log\fP configuration setting.
37292Just like any other report, we can set the set of fields to display
37293(\fBlog/command_log_cols\fP) and to sort by (\fBlog/command_log_sort\fP)
37294for this report.
37295
37296.nf
37297# lvmconfig --type full log/report_command_log log/command_log_cols \\
37298 log/command_log_sort log/command_log_selection
37299report_command_log=1
37300command_log_cols="log_seq_num,log_type,log_context,log_object_type,
37301 log_object_name,log_object_group,log_message,
37302 log_errno,log_ret_code"
37303command_log_sort="log_seq_num"
37304command_log_selection="!(log_type=status && message=success)"
37305
37306
37307# lvs
37308 Logical Volume
37309 ==============
37310 LV LSize Cpy%Sync
37311 lvol1 4.00m 100.00
37312 lvol0 4.00m
37313
37314 Command Log
37315 ===========
37316 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37317.fi
37318
37319As you can see, the command log is empty (it contains only field names).
37320By default, LVM uses selection on the command log report and this case
37321no row matched the selection criteria, see also \fBlog report specifics\fP
37322section in this document for more information. We're displaying complete
37323log report in the example below where we can see that both LVs lvol0 and
37324lvol1 were successfully processed as well as the VG vg they are part of.
37325
37326.nf
37327# lvmconfig --type full log/command_log_selection
37328command_log_selection="all"
37329
37330# lvs
37331 Logical Volume
37332 ==============
37333 LV LSize Cpy%Sync
37334 lvol1 4.00m 100.00
37335 lvol0 4.00m
37336
37337 Command Log
37338 ===========
37339 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37340 1 status processing lv lvol0 vg success 0 1
37341 2 status processing lv lvol1 vg success 0 1
37342 3 status processing vg vg success 0 1
37343
37344# lvchange -an vg/lvol1
37345 Command Log
37346 ===========
37347 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37348 1 status processing lv lvol1 vg success 0 1
37349 2 status processing vg vg success 0 1
37350.fi
37351
37352.SS Handling multiple reports per single command
37353
37354To configure the log report directly on command line, we need to use
37355\fB--configreport\fP option before we start any \fB-o|--options\fP,
37356\fB-O|--sort\fP or \fB-S|--select\fP that is targeted for log report.
37357
37358.nf
37359# lvs -o lv_name,lv_size --configreport log -o log_object_type, \\
37360 log_object_name,log_message,log_ret_code
37361 Logical Volume
37362 ==============
37363 LV LSize
37364 lvol1 4.00m
37365 lvol0 4.00m
37366
37367 Command Log
37368 ===========
37369 ObjType ObjName Msg RetCode
37370 lv lvol0 success 1
37371 lv lvol1 success 1
37372 vg vg success 1
37373.fi
37374
37375The \fBlvm fullreport\fP, with or without log report, consists of several
37376reports - the \fB--configreport\fP is also used to target particular
37377subreport here.
37378
37379Below is an extended example with \fBlvm fullreport\fP to illustrate
37380combination of various options. The report output is in JSON format.
37381Also, we configure "vg", "pvseg", "seg" and "log" subreport to contain
37382only specified fields. For the "pvseg" subreport, we're intested only
37383in PV names having "sda" in their name. For the "log" subreport we're
37384intested only in log lines related to either "lvol0" object or object
37385having "sda" in its name. Also, for the log subreport we define ordering
37386to be based on "log_object_type" field.
37387
37388.nf
37389# lvm fullreport --reportformat json \\
37390 --configreport vg -o vg_name,vg_size \\
37391 --configreport pvseg -o pv_name,pvseg_start \\
37392 -S 'pv_name=~sda' \\
37393 --configreport seg -o lv_name,seg_start \\
37394 --configreport log -o log_object_type,log_object_name \\
37395 -O log_object_type \\
37396 -S 'log_object_name=lvol0 || \\
37397 log_object_name=~sda'
37398 {
37399 "report": [
37400 {
37401 "vg": [
37402 {"vg_name":"vg", "vg_size":"200.00m"}
37403 ]
37404 ,
37405 "pv": [
37406 {"pv_name":"/dev/sda", "vg_name":"vg"},
37407 {"pv_name":"/dev/sdb", "vg_name":"vg"}
37408 ]
37409 ,
37410 "lv": [
37411 {"lv_name":"lvol0", "vg_name":"vg"},
37412 {"lv_name":"lvol1", "vg_name":"vg"}
37413 ]
37414 ,
37415 "pvseg": [
37416 {"pv_name":"/dev/sda", "pvseg_start":"0"},
37417 {"pv_name":"/dev/sda", "pvseg_start":"1"},
37418 {"pv_name":"/dev/sda", "pvseg_start":"2"},
37419 {"pv_name":"/dev/sda", "pvseg_start":"3"}
37420 ]
37421 ,
37422 "seg": [
37423 {"lv_name":"lvol0", "seg_start":"0 "},
37424 {"lv_name":"lvol1", "seg_start":"0 "}
37425 ]
37426 }
37427 ]
37428 ,
37429 "log": [
37430 {"log_object_type":"lv", "log_object_name":"lvol0"},
37431 {"log_object_type":"lv", "log_object_name":"lvol0"},
37432 {"log_object_type":"pv", "log_object_name":"/dev/sda"},
37433 {"log_object_type":"pv", "log_object_name":"/dev/sda"},
37434 ]
37435 }
37436.fi
37437
37438.SS Report extensions for LVM shell
37439
37440As already stated in \fBlog report coverage\fP paragraph under
37441\fBlog report specifics\fP in this documentation, when using \fBLVM shell\fP
37442the \fBlog report\fP coverage is wider. There's also special command
37443designed to query last command's log report in the \fBLVM shell\fP -
37444the \fBlastlog\fP command.
37445
37446The example below illustrates a situation where we called lvs command.
37447After that, we inspected the log report with the \fBlastlog\fP, without
37448any selection so all the log report is displayed on output. Then we called
37449\fBlastlog\fP further, giving various selection criteria. Then we ran
37450unknown LVM command "abc" for which the log report displays appropriate
37451failure state.
37452
37453.nf
37454# lvm
37455lvm> lvs
37456 Logical Volume
37457 ==============
37458 LV LSize Cpy%Sync
37459 lvol1 4.00m 100.00
37460 lvol0 4.00m
37461
37462 Command Log
37463 ===========
37464 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37465 1 status processing lv lvol0 vg success 0 1
37466 2 status processing lv lvol1 vg success 0 1
37467 3 status processing vg vg success 0 1
37468 4 status shell cmd lvs success 0 1
37469
37470lvm> lastlog
37471 Command Log
37472 ===========
37473 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37474 1 status processing lv lvol0 vg success 0 1
37475 2 status processing lv lvol1 vg success 0 1
37476 3 status processing vg vg success 0 1
37477 4 status shell cmd lvs success 0 1
37478
37479lvm> lastlog -S log_object_type=lv
37480 Command Log
37481 ===========
37482 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37483 1 status processing lv lvol0 vg success 0 1
37484 2 status processing lv lvol1 vg success 0 1
37485
37486lvm> lastlog -S log_context=shell
37487 Command Log
37488 ===========
37489 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37490 4 status shell cmd lvs success 0 1
37491
37492lvm> abc
37493 Command Log
37494 ===========
37495 Seq LogType Context ObjType ObjName ObjGrp Msg Errno RetCode
37496 1 error shell cmd abc No such command 'abc'. Try 'help'. -1 0
37497 2 status shell cmd abc failure -1 2
37498.fi
37499
37500.SH SEE ALSO
37501\fBlvm\fP (8),
37502\fBlvmconfig\fP (8),
37503\fBlvm fullreport\fP (8)
37504\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvresize.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000012275\013062740170\0020172\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVRESIZE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37505.SH NAME
37506lvresize \(em resize a logical volume
37507.SH SYNOPSIS
37508.B lvresize
37509.RB [ \-\-alloc " " \fIAllocationPolicy ]
37510.RB [ \-\-noudevsync ]
37511.RB [ \-\-commandprofile
37512.IR ProfileName ]
37513.RB [ \-i | \-\-stripes " " \fIStripes
37514.RB [ \-I | \-\-stripesize " " \fIStripeSize ]]
37515.RB { \-l | \-\-extents
37516.RI [ + | \- ] LogicalExtentsNumber [ % { VG | LV | PVS | FREE | ORIGIN "}] |"
37517.BR \-L | \-\-size
37518.RI [ + | \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]}
37519.RB [ \-\-poolmetadatasize
37520.RI [ + ] MetadataVolumeSize [ bBsSkKmMgG ]]
37521.RB [ \-f | \-\-force ]
37522.RB [ \-n | \-\-nofsck ]
37523.RB [ \-\-reportformat
37524.RB { basic | json }]
37525.RB [ \-r | \-\-resizefs ]
37526.IR LogicalVolume { Name | Path }
37527.RI [ PhysicalVolumePath [ :PE [ \-PE ]]...]
37528.SH DESCRIPTION
37529lvresize allows you to resize a logical volume.
37530Be careful when reducing a logical volume's size, because data in the reduced
37531part is lost!!!
37532You should therefore ensure that any filesystem on the volume is
37533shrunk first so that the extents that are to be removed are not in use.
37534Resizing snapshot logical volumes (see
37535.BR lvcreate (8)
37536for information about creating snapshots) is supported as well.
37537But to change the number of copies in a mirrored logical
37538volume use
37539.BR lvconvert (8).
37540.SH OPTIONS
37541See \fBlvm\fP(8) for common options.
37542.TP
37543.BR \-f ", " \-\-force
37544Force resize without prompting even when it may cause data loss.
37545.TP
37546.BR \-n ", " \-\-nofsck
37547Do not perform fsck before resizing filesystem when filesystem
37548requires it. You may need to use \fB\-\-force\fR to proceed with
37549this option.
37550.TP
37551.BR \-r ", " \-\-resizefs
37552Resize underlying filesystem together with the logical volume using
37553\fBfsadm\fR(8).
37554.TP
37555.IR \fB\-l ", " \fB\-\-extents " [" + | \- ] LogicalExtentsNumber [ % { VG | LV | PVS | FREE | ORIGIN }]
37556Change or set the logical volume size in units of logical extents.
37557With the \fI+\fP or \fI\-\fP sign the value is added to or subtracted from the actual size
37558of the logical volume and without it, the value is taken as an absolute one.
37559The total number of physical extents affected will be
37560greater than this if, for example, the volume is mirrored.
37561The number can also be expressed as a percentage of the total space
37562in the Volume Group with the suffix \fI%VG\fP, relative to the existing
37563size of the Logical Volume with the suffix \fI%LV\fP, as a percentage of
37564the remaining free space of the PhysicalVolumes on the command line with the
37565suffix \fI%PVS\fP, as a percentage of the remaining free space in the
37566Volume Group with the suffix \fI%FREE\fP, or (for a snapshot) as a percentage
37567of the total space in the Origin Logical Volume with the suffix \fI%ORIGIN\fP.
37568The resulting value is rounded downward for the subtraction otherwise
37569it is rounded upward.
37570N.B. In a future release, when expressed as a percentage with PVS, VG or FREE,
37571the number will be treated as an approximate total number of physical extents
37572to be allocated or freed (including extents used by any mirrors, for example).
37573The code may currently allocate or remove more space than you might otherwise
37574expect.
37575.TP
37576.IR \fB\-L ", " \fB\-\-size " [" + | \- ] LogicalVolumeSize [ bBsSkKmMgGtTpPeE ]
37577Change or set the logical volume size in units of megabytes.
37578A size suffix of \fIM\fP for megabytes,
37579\fIG\fP for gigabytes, \fIT\fP for terabytes, \fIP\fP for petabytes
37580or \fIE\fP for exabytes is optional.
37581With the \fI+\fP or \fI\-\fP sign the value is added or subtracted
37582from the actual size of the logical volume and rounded
37583to the full extent size and without it,
37584the value is taken as an absolute one.
37585.TP
37586.BR \-i ", " \-\-stripes " " \fIStripes
37587Gives the number of stripes to use when extending a Logical Volume.
37588Defaults to whatever the last segment of the Logical Volume uses.
37589Not applicable to LVs using the original metadata LVM format, which must
37590use a single value throughout.
37591.TP
37592.IR \fB\-\-poolmetadatasize " [" + ] MetadataVolumeSize [ bBsSkKmMgG ]
37593Change or set the thin pool metadata logical volume size.
37594With the \fI+\fP sign the value is added to the actual size
37595of the metadata volume and rounded to the full extent size
37596and without it, the value is taken as an absolute one.
37597Maximal size is 16GiB. Default unit is megabytes.
37598.TP
37599.BR \-I ", " \-\-stripesize " " \fIStripeSize
37600Gives the number of kilobytes for the granularity of the stripes.
37601Defaults to whatever the last segment of the Logical Volume uses.
37602Not applicable to LVs using the original metadata LVM format, which
37603must use a single value throughout.
37604.br
37605StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
37606For metadata in LVM2 format, the stripe size may be a larger
37607power of 2 but must not exceed the physical extent size.
37608.TP
37609.B \-\-noudevsync
37610Disable udev synchronisation. The
37611process will not wait for notification from udev.
37612It will continue irrespective of any possible udev processing
37613in the background. You should only use this if udev is not running
37614or has rules that ignore the devices LVM2 creates.
37615.SH EXAMPLES
37616.br
37617Extend a logical volume vg1/lv1 by 16MB using physical extents
37618/dev/sda:0\-1 and /dev/sdb:0\-1 for allocation of extents:
37619.sp
37620.B lvresize \-L+16M vg1/lv1 /dev/sda:0\-1 /dev/sdb:0\-1
37621.SH SEE ALSO
37622.BR fsadm (8),
37623.BR lvm (8),
37624.BR lvconvert (8),
37625.BR lvcreate (8),
37626.BR lvreduce (8),
37627.BR lvchange (8)
37628\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgextend.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004427\013062740170\0020153\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGEXTEND 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37629.SH NAME
37630vgextend \(em add physical volumes to a volume group
37631.SH SYNOPSIS
37632.B vgextend
37633.RB [ \-A | \-\-autobackup
37634.RI { y | n }]
37635.RB [ \-\-commandprofile
37636.IR ProfileName ]
37637.RB [ \-d | \-\-debug ]
37638.RB [ \-h | \-? | \-\-help ]
37639.RB [ \-\-reportformat
37640.RB { basic | json }]
37641.RB [ \-\-restoremissing ]
37642.RB [ \-f | \-\-force ]
37643.RB [ \-t | \-\-test ]
37644.RB [ \-v | \-\-verbose ]
37645.RB [ "PHYSICAL DEVICE OPTIONS" ]
37646.I VolumeGroupName PhysicalDevicePath
37647.RI [ PhysicalDevicePath ...]
37648.SH DESCRIPTION
37649vgextend allows you to add one or more initialized physical volumes
37650(see \fBpvcreate\fP(8)) to an existing volume group to extend it in size. Moreover, it allows you to
37651re-add a physical volume that has gone missing previously, due to a transient
37652device failure, without re-initialising it. Use
37653\fBvgextend \-\-restoremissing\fP to that effect.
37654.sp
37655If \fIPhysicalDevicePath\fP was not previously configured for LVM with
37656\fBpvcreate\fP(8), the device will be initialized with the same
37657default values used with \fBpvcreate\fP(8). If non-default
37658\fPpvcreate\fP(8) values are desired, they may be given on the
37659commandline with the same options as \fPpvcreate\fP(8). See
37660.B PHYSICAL DEVICE OPTIONS
37661for available options. Note that the restore-related options such as
37662.BR \-\-restorefile ", " \-\-uuid " and " \-\-physicalvolumesize
37663are not available. If a restore operation
37664is needed, use \fBpvcreate\fP(8) and \fBvgcfgrestore\fP(8).
37665.SH OPTIONS
37666See \fBlvm\fP(8) for common options.
37667.SH PHYSICAL DEVICE OPTIONS
37668The following options are available for initializing physical devices in the
37669volume group. These options are further described in the
37670\fBpvcreate\fP(8) man page.
37671.TP
37672.BR \-f ", " \-\-force
37673.TP
37674.BR \-y ", " \-\-yes
37675.TP
37676.BR \-Z ", " \-\-zero " {" \fIy | \fIn }
37677.TP
37678.B \-\-labelsector \fIsector
37679.TP
37680.B \-\-metadatasize \fIsize
37681.TP
37682.BR \-\-metadataignore " {" \fIy | \fIn }
37683.TP
37684.B \-\-pvmetadatacopies \fIcopies
37685.TP
37686.B \-\-dataalignment \fIalignment
37687.TP
37688.B \-\-dataalignmentoffset \fIalignment_offset
37689.SH Examples
37690Extends the existing volume group "vg00" by the new physical volumes
37691(see \fBpvcreate\fP(8)) "/dev/sda4" and "/dev/sdn1".
37692.sp
37693.B vgextend vg00 /dev/sda4 /dev/sdn1
37694.SH SEE ALSO
37695.BR lvm (8),
37696.BR vgcreate (8),
37697.BR vgreduce (8),
37698.BR pvcreate (8)
37699\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/dmeventd.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003771\013062740170\0020136\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH DMEVENTD 8 "DM TOOLS #VERSION#" "Red Hat Inc" \" -*- nroff -*-
37700.
37701.SH NAME
37702.
37703dmeventd \(em Device-mapper event daemon
37704.
37705.SH SYNOPSIS
37706.
37707.B dmeventd
37708.RB [ \-d
37709.RB [ \-d
37710.RB [ \-d ]]]
37711.RB [ \-f ]
37712.RB [ \-h ]
37713.RB [ \-l ]
37714.RB [ \-R ]
37715.RB [ \-V ]
37716.RB [ \-? ]
37717.
37718.SH DESCRIPTION
37719.
37720dmeventd is the event monitoring daemon for device-mapper devices.
37721Library plugins can register and carry out actions triggered when
37722particular events occur.
37723.
37724.SH LVM PLUGINS
37725.
37726.HP
37727.IR Mirror
37728.br
37729Attempts to handle device failure automatically. See
37730.BR lvm.conf (5).
37731.
37732.HP
37733.IR Raid
37734.br
37735Attempts to handle device failure automatically. See
37736.BR lvm.conf (5).
37737.
37738.HP
37739.IR Snapshot
37740.br
37741Monitors how full a snapshot is becoming and emits a warning to
37742syslog when it exceeds 80% full.
37743The warning is repeated when 85%, 90% and 95% of the snapshot is filled.
37744See
37745.BR lvm.conf (5).
37746Snapshot which runs out of space gets invalid and when it is mounted,
37747it gets umounted if possible.
37748.
37749.HP
37750.IR Thin
37751.br
37752Monitors how full a thin pool data and metadata is becoming and emits
37753a warning to syslog when it exceeds 80% full.
37754The warning is repeated when 85%, 90% and 95% of the thin pool is filled.
37755See
37756.BR lvm.conf (5).
37757If the thin-pool runs out of space, thin volumes are umounted if possible.
37758.
37759.SH OPTIONS
37760.
37761.HP
37762.BR \-d
37763.br
37764Repeat from 1 to 3 times (
37765.BR \-d ,
37766.BR \-dd ,
37767.BR \-ddd
37768) to increase the detail of
37769debug messages sent to syslog.
37770Each extra d adds more debugging information.
37771.
37772.HP
37773.BR \-f
37774.br
37775Don't fork, run in the foreground.
37776.
37777.HP
37778.BR \-h
37779.br
37780Show help information.
37781.
37782.HP
37783.BR \-l
37784.br
37785Log through stdout and stderr instead of syslog.
37786This option works only with option \-f, otherwise it is ignored.
37787.
37788.HP
37789.BR \-?
37790.br
37791Show help information on stderr.
37792.
37793.HP
37794.BR \-R
37795.br
37796Replace a running dmeventd instance. The running dmeventd must be version
377972.02.77 or newer. The new dmeventd instance will obtain a list of devices and
37798events to monitor from the currently running daemon.
37799.
37800.HP
37801.BR \-V
37802.br
37803Show version of dmeventd.
37804.
37805.SH SEE ALSO
37806.
37807.BR lvm (8),
37808.BR lvm.conf (5)
37809\0\0\0\0\0\0\0LVM2.2.02.168/man/vgmknodes.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001655\013062740170\0020324\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGMKNODES 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37810.SH NAME
37811vgmknodes \(em recreate volume group directory and logical volume special files
37812.SH SYNOPSIS
37813.B vgmknodes
37814.RB [ \-\-commandprofile
37815.IR ProfileName ]
37816.RB [ \-d | \-\-debug ]
37817.RB [ \-h | \-\-help ]
37818.RB [ \-\-refresh ]
37819.RB [ \-\-reportformat
37820.RB { basic | json }]
37821.RB [ \-v | \-\-verbose ]
37822.RI [[ VolumeGroupName | LogicalVolumePath ]...]
37823.SH DESCRIPTION
37824Checks the LVM2 special files in /dev that are needed for active
37825logical volumes and creates any missing ones and removes unused ones.
37826.SH OPTIONS
37827.TP
37828See \fBlvm\fP(8) for common options.
37829.TP
37830.BR \-\-refresh
37831If any logical volume in the volume group is active, reload its metadata.
37832This is not necessary in normal operation, but may be useful
37833if something has gone wrong or if you're doing clustering
37834manually without a clustered lock manager.
37835.SH SEE ALSO
37836.BR lvm (8),
37837.BR vgscan (8),
37838.BR dmsetup (8)
37839\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgcfgbackup.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002300\013062740170\0020575\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCFGBACKUP 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37840.SH NAME
37841vgcfgbackup \(em backup volume group descriptor area
37842.SH SYNOPSIS
37843.B vgcfgbackup
37844.RB [ \-\-commandprofile
37845.IR ProfileName ]
37846.RB [ \-d | \-\-debug ]
37847.RB [ \-f | \-\-file
37848.IR Filename ]
37849.RB [ \-h | \-\-help ]
37850.RB [ \-\-ignorelockingfailure ]
37851.RB [ \-P | \-\-partial ]
37852.RB [ \-\-reportformat
37853.RB { basic | json }]
37854.RB [ \-v | \-\-verbose ]
37855.RI [ VolumeGroupName ...]
37856.SH DESCRIPTION
37857vgcfgbackup allows you to backup the metadata of your volume groups.
37858If you don't name any volume groups on the command line, all of them
37859will be backed up.
37860.sp
37861In a default installation, each volume group gets backed up into a separate
37862file bearing the name of the volume group in the directory
37863\fI#DEFAULT_BACKUP_DIR#\fP.
37864You can write the backup to an alternative file using \fB\-f\fP. In this case
37865if you are backing up more than one volume group the filename is
37866treated as a template, and %s gets replaced by the volume group name.
37867.sp
37868NB. This DOESN'T backup user/system data in logical
37869volume(s)! Backup \fI#DEFAULT_SYS_DIR#\fP regularly too.
37870.SH OPTIONS
37871See \fBlvm\fP(8) for common options.
37872.SH SEE ALSO
37873.BR lvm (8),
37874.BR vgcfgrestore (8)
37875\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgcfgrestore.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004143\013062740170\0021022\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCFGRESTORE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37876.SH NAME
37877vgcfgrestore \(em restore volume group descriptor area
37878.SH SYNOPSIS
37879.B vgcfgrestore
37880.RB [ \-\-commandprofile
37881.IR ProfileName ]
37882.RB [ \-d | \-\-debug ]
37883.RB [ \-f | \-\-file
37884.RI < filename >]
37885.RB [ \-\-force ]
37886.RB [ \-l [ l ]| \-\-list ]
37887.RB [ \-h | \-\-help ]
37888.RB [ \-M | \-\-metadatatype
37889.IR 1 | 2 ]
37890.RB [ \-t | \-\-test ]
37891.RB [ \-v | \-\-verbose ]
37892.RI \fIVolumeGroupName\fP
37893.SH DESCRIPTION
37894vgcfgrestore allows you to restore the metadata of \fIVolumeGroupName\fP
37895from a text backup file produced by \fBvgcfgbackup\fP.
37896You can specify a backup file with \fB\-\-file\fP.
37897If no backup file is specified, the most recent
37898one is used. Use \fB\-\-list\fP for a list of the available
37899backup and archive files of \fIVolumeGroupName\fP.
37900.SH OPTIONS
37901See \fBlvm\fP(8) for common options.
37902.TP
37903.BR \-l ", " \-\-list\fP
37904List files pertaining to \fIVolumeGroupName\fP
37905List metadata backup and archive files pertaining to \fIVolumeGroupName\fP.
37906May be used with the \fB\-f\fP option. Does not restore \fIVolumeGroupName\fP.
37907.TP
37908.BR \-f ", " \-\-file " " \fIfilename
37909Name of LVM metadata backup file
37910Specifies a metadata backup or archive file to be used for restoring
37911VolumeGroupName. Often this file has been created with \fBvgcfgbackup\fP.
37912.TP
37913.B \-\-force
37914Necessary to restore metadata with thin pool volumes.
37915.br
37916\fBWARNING: Use with extreme caution.
37917Most changes to thin metadata cannot be reverted.
37918You may lose data if you restore metadata that does not match the thin pool
37919kernel metadata precisely.\fP
37920.SH REPLACING PHYSICAL VOLUMES
37921\fBvgdisplay \-\-partial \-\-verbose\fP will show you the UUIDs and sizes of
37922any PVs that are no longer present.
37923If a PV in the VG is lost and you wish to substitute
37924another of the same size, use
37925\fBpvcreate \-\-restorefile filename \-\-uuid uuid\fP (plus additional
37926arguments as appropriate) to initialise it with the same UUID as
37927the missing PV. Repeat for all other missing PVs in the VG.
37928Then use \fBvgcfgrestore \-\-file filename\fP to restore the volume
37929group's metadata.
37930.SH SEE ALSO
37931.BR lvm (8),
37932.BR vgcreate (8)
37933\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/pvresize.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002765\013062740170\0020201\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH PVRESIZE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37934.SH NAME
37935pvresize \(em resize a disk or partition in use by LVM2
37936.SH SYNOPSIS
37937.B pvresize
37938.RB [ \-\-commandprofile
37939.IR ProfileName ]
37940.RB [ \-d | \-\-debug ]
37941.RB [ \-h | \-\-help ]
37942.RB [ \-t | \-\-test ]
37943.RB [ \-v | \-\-verbose ]
37944.RB [ \-\-version ]
37945.RB [ \-\-reportformat
37946.RB { basic | json }]
37947.RB [ \-\-setphysicalvolumesize
37948.IR size ]
37949.I PhysicalVolume
37950.RI [ PhysicalVolume ...]
37951.SH DESCRIPTION
37952pvresize resizes
37953.I PhysicalVolume
37954which may already be in a volume group and have active logical volumes
37955allocated on it.
37956.SH OPTIONS
37957See \fBlvm\fP(8) for common options.
37958.TP
37959.BI \-\-setphysicalvolumesize " size"
37960Overrides the automatically-detected size of the PV. Use with care, or
37961prior to reducing the physical size of the device.
37962.SH EXAMPLES
37963Expand the PV on /dev/sda1 after enlarging the partition with fdisk:
37964.sp
37965.B pvresize /dev/sda1
37966.sp
37967Shrink the PV on /dev/sda1 prior to shrinking the partition with fdisk
37968(ensure that the PV size is appropriate for your intended new partition
37969size):
37970.sp
37971.B pvresize \-\-setphysicalvolumesize 40G /dev/sda1
37972.sp
37973.SH RESTRICTIONS
37974pvresize will refuse to shrink
37975.I PhysicalVolume
37976if it has allocated extents after where its new end would be. In the future,
37977it should relocate these elsewhere in the volume group if there is sufficient
37978free space, like
37979.B pvmove
37980does.
37981.sp
37982.B pvresize
37983won't currently work correctly on LVM1 volumes.
37984.SH SEE ALSO
37985.BR lvm (8),
37986.BR pvmove (8),
37987.BR lvresize (8),
37988.BR fdisk (8)
37989\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgconvert.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002523\013062740170\0020337\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGCONVERT 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
37990.SH NAME
37991vgconvert \- convert volume group metadata format
37992.SH SYNOPSIS
37993.B vgconvert
37994.RB [ \-\-commandprofile
37995.IR ProfileName ]
37996.RB [ \-d | \-\-debug ]
37997.RB [ \-h | \-\-help ]
37998.RB [ \-t | \-\-test ]
37999.RB [ \-v | \-\-verbose ]
38000.RB [ \-\-labelsector ]
38001.RB [ \-\-bootloaderareasize
38002.IR size ]
38003.RB [ \-M | \-\-metadatatype
38004.IR type ]
38005.RB [ \-\-pvmetadatacopies
38006.IR NumberOfCopies ]
38007.RB [ \-\-metadatasize
38008.IR size ]
38009.RB [ \-\-reportformat
38010.RB { basic | json }]
38011.RB [ \-\-version ]
38012.I VolumeGroupName
38013.RI [ VolumeGroupName ...]
38014.SH DESCRIPTION
38015vgconvert converts
38016.I VolumeGroupName
38017metadata from one format to another provided that the metadata
38018fits into the same space.
38019.SH OPTIONS
38020See \fBlvm\fP(8) and \fBpvcreate\fP(8) for options.
38021.SH Examples
38022Convert volume group vg1 from LVM1 metadata format to the new LVM2
38023metadata format.
38024.sp
38025.B vgconvert \-M2 vg1
38026.SH RECOVERY
38027Use \fBpvscan\fP(8) to see which PVs lost their metadata.
38028Run \fBpvcreate\fP(8) with the \fB\-\-uuid\fP and \fB\-\-restorefile\fP
38029options on each such PV to reformat it as it was, using the archive
38030file that \fBvgconvert\fP(8) created at the start of the procedure.
38031Finally run \fBvgcfgrestore\fP(8) with that archive file to restore
38032the original metadata.
38033.SH SEE ALSO
38034.BR lvm (8),
38035.BR pvcreate (8),
38036.BR vgcfgrestore (8)
38037\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/vgmerge.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002272\013062740170\0017757\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH VGMERGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
38038.SH NAME
38039vgmerge \(em merge two volume groups
38040.SH SYNOPSIS
38041.B vgmerge
38042.RB [ \-A | \-\-autobackup
38043.RI { y | n }]
38044.RB [ \-\-commandprofile
38045.IR ProfileName ]
38046.RB [ \-d | \-\-debug ]
38047.RB [ \-h | \-? | \-\-help ]
38048.RB [ \-l | \-\-list ]
38049.RB [ \-t | \-\-test ]
38050.RB [ \-v | \-\-verbose ]
38051.I DestinationVolumeGroupName
38052.I SourceVolumeGroupName
38053.SH DESCRIPTION
38054vgmerge merges two existing volume groups. The inactive
38055\fISourceVolumeGroupName\fP will be merged into
38056the \fIDestinationVolumeGroupName\fP if physical extent sizes
38057are equal and physical and logical volume summaries of both volume groups
38058fit into \fIDestinationVolumeGroupName\fP's limits.
38059.SH OPTIONS
38060See \fBlvm\fP(8) for common options.
38061.TP
38062.BR \-l ", " \-\-list
38063Display merged \fIDestinationVolumeGroupName\fP like \fBvgdisplay \-v\fP.
38064.TP
38065.BR \-t ", " \-\-test
38066Do a test run WITHOUT making any real changes.
38067.SH Examples
38068Merge the inactive volume group named "my_vg"
38069into the active or inactive volume group named "databases" giving verbose
38070runtime information:
38071.sp
38072.B vgmerge \-v databases my_vg
38073.SH SEE ALSO
38074.BR lvm (8),
38075.BR vgcreate (8),
38076.BR vgextend (8),
38077.BR vgreduce (8)
38078\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/fsadm.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004166\013062740170\0017421\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
38079.SH "NAME"
38080fsadm \(em utility to resize or check filesystem on a device
38081.SH SYNOPSIS
38082.
38083.PD 0
38084.ad l
38085.HP 5
38086.B fsadm
38087.RI [ options ]
38088.BR check
38089.IR device
38090.
38091.HP
38092.B fsadm
38093.RI [ options ]
38094.BR resize
38095.IR device
38096.RI [ new_size ]
38097.PD
38098.ad b
38099.
38100.SH DESCRIPTION
38101.
38102fsadm utility checks or resizes the filesystem on a device.
38103It tries to use the same API for
38104.BR ext2 ,
38105.BR ext3 ,
38106.BR ext4 ,
38107.BR ReiserFS
38108.RB and
38109.BR XFS
38110filesystem.
38111.
38112.SH OPTIONS
38113.
38114.HP
38115.BR \-e | \-\-ext\-offline
38116.br
38117Unmount ext2/ext3/ext4 filesystem before doing resize.
38118.
38119.HP
38120.BR \-f | \-\-force
38121.br
38122Bypass some sanity checks.
38123.
38124.HP
38125.BR \-h | \-\-help
38126.br
38127Display the help text.
38128.
38129.HP
38130.BR \-n | \-\-dry\-run
38131.br
38132Print commands without running them.
38133.
38134.HP
38135.BR \-v | \-\-verbose
38136.br
38137Be more verbose.
38138.
38139.HP
38140.BR \-y | \-\-yes
38141.br
38142Answer "yes" at any prompts.
38143.
38144.HP
38145.BR \fInew_size [ B | K | M | G | T | P | E ]
38146.br
38147Absolute number of filesystem blocks to be in the filesystem,
38148or an absolute size using a suffix (in powers of 1024).
38149If new_size is not supplied, the whole device is used.
38150.
38151.SH DIAGNOSTICS
38152.
38153On successful completion, the status code is 0.
38154A status code of 2 indicates the operation was interrupted by the user.
38155A status code of 3 indicates the requested check operation could not be performed
38156because the filesystem is mounted and does not support an online
38157.BR fsck (8).
38158A status code of 1 is used for other failures.
38159.
38160.SH EXAMPLES
38161.
38162Resize the filesystem on logical volume \fI/dev/vg/test\fP to 1000 megabytes.
38163If \fI/dev/vg/test\fP contains ext2/ext3/ext4
38164filesystem it will be unmounted prior the resize.
38165All [y/n] questions will be answered 'y'.
38166.sp
38167.B fsadm \-e \-y resize /dev/vg/test 1000M
38168.
38169.SH ENVIRONMENT VARIABLES
38170.
38171.TP
38172.B "TMPDIR "
38173The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
38174.TP
38175.B DM_DEV_DIR
38176The device directory name.
38177Defaults to "\fI/dev\fP" and must be an absolute path.
38178
38179.SH SEE ALSO
38180.nh
38181.BR lvm (8),
38182.BR lvresize (8),
38183.BR lvm.conf (5),
38184.BR fsck (8),
38185.BR tune2fs (8),
38186.BR resize2fs (8),
38187.BR reiserfstune (8),
38188.BR resize_reiserfs (8),
38189.BR xfs_info (8),
38190.BR xfs_growfs (8),
38191.BR xfs_check (8)
38192\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/man/lvmchange.8.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000507\013062740170\0020266\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0.TH LVMCHANGE 8 "LVM TOOLS #VERSION#" "Sistina Software UK" \" -*- nroff -*-
38193.SH NAME
38194lvmchange \(em change attributes of the logical volume manager
38195.SH SYNOPSIS
38196.B lvmchange
38197.SH DESCRIPTION
38198lvmchange is not currently supported under LVM2, although
38199\fBdmsetup\fP(8) has a \fBremove_all\fP command.
38200.SH SEE ALSO
38201.BR dmsetup (8)
38202\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/INSTALL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001671\013062740170\0016105\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Installation
38203============
38204
382051) Generate custom makefiles.
38206
38207 Run the 'configure' script from the top directory.
38208
38209 If you don't want to include the LVM1 backwards-compatibility code use:
38210 ./configure --with-lvm1=none
38211
38212 To separate the LVM1 support into a shared library loaded by lvm.conf use:
38213 ./configure --with-lvm1=shared
38214
38215 Use ./configure --help to see other options.
38216
382172) Build and install.
38218
38219 Run 'make' from the top directory to build everything you configured.
38220 Run 'make install' to build and install everything you configured.
38221
38222 If you only want the device-mapper libraries and tools use
38223 'make device-mapper' or 'make install_device-mapper'.
38224
382253) If using LVM2, create a configuration file.
38226
38227 The tools will work fine without a configuration file being
38228 present, but you ought to review the example file in doc/example.conf.
38229
38230Please also refer to the WHATS_NEW file and the manual pages for the
38231individual commands.
38232
38233\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000015600\013062740170\0017116\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
38234# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
38235# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
38236#
38237# This file is part of LVM2.
38238#
38239# This copyrighted material is made available to anyone wishing to use,
38240# modify, copy, or redistribute it subject to the terms and conditions
38241# of the GNU General Public License v.2.
38242#
38243# You should have received a copy of the GNU General Public License
38244# along with this program; if not, write to the Free Software Foundation,
38245# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38246
38247srcdir = @srcdir@
38248top_srcdir = @top_srcdir@
38249top_builddir = @top_builddir@
38250abs_top_builddir = @abs_top_builddir@
38251abs_top_srcdir = @abs_top_srcdir@
38252
38253SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
38254
38255ifeq ("@UDEV_RULES@", "yes")
38256 SUBDIRS += udev
38257endif
38258
38259ifeq ("@INTL@", "yes")
38260 SUBDIRS += po
38261endif
38262
38263ifeq ("@APPLIB@", "yes")
38264 SUBDIRS += liblvm
38265endif
38266
38267ifeq ("@PYTHON_BINDINGS@", "yes")
38268 SUBDIRS += python
38269endif
38270
38271ifeq ($(MAKECMDGOALS),clean)
38272 SUBDIRS += test
38273endif
38274# FIXME Should use intermediate Makefiles here!
38275ifeq ($(MAKECMDGOALS),distclean)
38276 SUBDIRS = conf include man test scripts \
38277 libdaemon lib tools daemons libdm \
38278 udev po liblvm python \
38279 unit-tests/datastruct unit-tests/mm unit-tests/regex
38280tools.distclean: test.distclean
38281endif
38282DISTCLEAN_DIRS += lcov_reports*
38283DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
38284
38285include make.tmpl
38286
38287libdm: include
38288libdaemon: include
38289lib: libdm libdaemon
38290liblvm: lib
38291daemons: lib libdaemon tools
38292tools: lib libdaemon device-mapper
38293po: tools daemons
38294scripts: liblvm libdm
38295
38296lib.device-mapper: include.device-mapper
38297libdm.device-mapper: include.device-mapper
38298liblvm.device-mapper: include.device-mapper
38299daemons.device-mapper: libdm.device-mapper
38300tools.device-mapper: libdm.device-mapper
38301scripts.device-mapper: include.device-mapper
38302device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
38303
38304ifeq ("@INTL@", "yes")
38305lib.pofile: include.pofile
38306tools.pofile: lib.pofile
38307daemons.pofile: lib.pofile
38308po.pofile: tools.pofile daemons.pofile
38309pofile: po.pofile
38310endif
38311
38312ifeq ("@PYTHON_BINDINGS@", "yes")
38313python: liblvm
38314endif
38315
38316ifneq ("$(CFLOW_CMD)", "")
38317tools.cflow: libdm.cflow lib.cflow
38318daemons.cflow: tools.cflow
38319cflow: include.cflow
38320endif
38321
38322ifneq ("@CSCOPE_CMD@", "")
38323cscope.out:
38324 @CSCOPE_CMD@ -b -R -s$(top_srcdir)
38325all: cscope.out
38326endif
38327DISTCLEAN_TARGETS += cscope.out
38328CLEAN_DIRS += autom4te.cache
38329
38330check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
38331 $(MAKE) -C test $(@)
38332
38333conf.generate: tools
38334
38335# how to use parenthesis in makefiles
38336leftparen:=(
38337LVM_VER := $(firstword $(subst $(leftparen), ,$(LVM_VERSION)))
38338VER := LVM2.$(LVM_VER)
38339# release file name
38340FILE_VER := $(VER).tgz
38341CLEAN_TARGETS += $(FILE_VER)
38342CLEAN_DIRS += $(rpmbuilddir)
38343
38344dist:
38345 @echo "Generating $(FILE_VER)";\
38346 (cd $(top_srcdir); git ls-tree -r HEAD --name-only | xargs tar --transform "s,^,$(VER)/," -c) | gzip >$(FILE_VER)
38347
38348rpm: dist
38349 $(RM) -r $(rpmbuilddir)/SOURCES
38350 $(MKDIR_P) $(rpmbuilddir)/SOURCES
38351 $(LN_S) -f $(abs_top_builddir)/$(FILE_VER) $(rpmbuilddir)/SOURCES
38352 $(LN_S) -f $(abs_top_srcdir)/spec/build.inc $(rpmbuilddir)/SOURCES
38353 $(LN_S) -f $(abs_top_srcdir)/spec/macros.inc $(rpmbuilddir)/SOURCES
38354 $(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES
38355 DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\
38356 GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\
38357 sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
38358 -e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \
38359 -e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \
38360 $(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
38361 rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
38362
38363generate: conf.generate
38364 $(MAKE) -C conf generate
38365
38366all_man:
38367 $(MAKE) -C man all_man
38368
38369install_system_dirs:
38370 $(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
38371 $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
38372 $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
38373 $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
38374 $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
38375 $(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
38376 $(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
38377
38378install_initscripts:
38379 $(MAKE) -C scripts install_initscripts
38380
38381install_systemd_generators:
38382 $(MAKE) -C scripts install_systemd_generators
38383 $(MAKE) -C man install_systemd_generators
38384
38385install_systemd_units:
38386 $(MAKE) -C scripts install_systemd_units
38387
38388install_all_man:
38389 $(MAKE) -C man install_all_man
38390
38391ifeq ("@PYTHON_BINDINGS@", "yes")
38392install_python_bindings:
38393 $(MAKE) -C liblvm/python install_python_bindings
38394endif
38395
38396install_tmpfiles_configuration:
38397 $(MAKE) -C scripts install_tmpfiles_configuration
38398
38399LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
38400 libdaemon/client.info libdaemon/server.info \
38401 daemons/clvmd.info \
38402 daemons/dmeventd.info \
38403 daemons/lvmetad.info \
38404 daemons/lvmlockd.info \
38405 daemons/lvmpolld.info
38406
38407CLEAN_TARGETS += $(LCOV_TRACES)
38408
38409ifneq ("$(LCOV)", "")
38410.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
38411
38412ifeq ($(MAKECMDGOALS),lcov-dated)
38413LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
38414lcov-dated: lcov
38415else
38416LCOV_REPORTS_DIR := lcov_reports
38417endif
38418
38419lcov-reset:
38420 $(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
38421
38422# maybe use subdirs processing to create tracefiles...
38423$(LCOV_TRACES):
38424 $(LCOV) -b $(basename $@) -d $(basename $@) \
38425 --ignore-errors source -c -o - | $(SED) \
38426 -e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
38427 -e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \
38428 >$@
38429
38430ifneq ("$(GENHTML)", "")
38431lcov: $(LCOV_TRACES)
38432 $(RM) -r $(LCOV_REPORTS_DIR)
38433 $(MKDIR_P) $(LCOV_REPORTS_DIR)
38434 for i in $(LCOV_TRACES); do \
38435 test -s $$i -a $$(wc -w <$$i) -ge 100 && lc="$$lc $$i"; \
38436 done; \
38437 test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
38438 -o $(LCOV_REPORTS_DIR) $$lc
38439endif
38440
38441endif
38442
38443ifeq ("$(TESTING)", "yes")
38444# testing and report generation
38445RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
38446
38447.PHONY: unit-test ruby-test test-programs
38448
38449# FIXME: put dependencies on libdm and liblvm
38450# FIXME: Should be handled by Makefiles in subdirs, not here at top level.
38451test-programs:
38452 cd unit-tests/regex && $(MAKE)
38453 cd unit-tests/datastruct && $(MAKE)
38454 cd unit-tests/mm && $(MAKE)
38455
38456unit-test: test-programs
38457 $(RUBY) report-generators/unit_test.rb $(shell find . -name TESTS)
38458 $(RUBY) report-generators/title_page.rb
38459
38460memcheck: test-programs
38461 $(RUBY) report-generators/memcheck.rb $(shell find . -name TESTS)
38462 $(RUBY) report-generators/title_page.rb
38463
38464ruby-test:
38465 $(RUBY) report-generators/test/ts.rb
38466endif
38467
38468ifneq ($(shell which ctags),)
38469.PHONY: tags
38470tags:
38471 test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
38472 test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
38473
38474CLEAN_TARGETS += tags
38475endif
38476\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/VERSION\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000031\013062740170\0016111\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\02.02.168(2) (2016-11-30)
38477\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/make.tmpl.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000035617\013062740170\0017303\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# @configure_input@
38478#
38479# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
38480# Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
38481#
38482# This file is part of LVM2.
38483#
38484# This copyrighted material is made available to anyone wishing to use,
38485# modify, copy, or redistribute it subject to the terms and conditions
38486# of the GNU General Public License v.2.
38487#
38488# You should have received a copy of the GNU General Public License
38489# along with this program; if not, write to the Free Software Foundation,
38490# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38491
38492SHELL = /bin/sh
38493
38494@SET_MAKE@
38495
38496CC = @CC@
38497RANLIB = @RANLIB@
38498INSTALL = @INSTALL@
38499INSTALL_DATA = @INSTALL@ -m 644
38500MKDIR_P = @MKDIR_P@
38501MSGFMT = @MSGFMT@
38502LCOV = @LCOV@
38503GENHTML = @GENHTML@
38504LN_S = @LN_S@
38505SED = @SED@
38506CFLOW_CMD = @CFLOW_CMD@
38507AWK = @AWK@
38508CHMOD = @CHMOD@
38509PYTHON2 = @PYTHON2@
38510PYTHON3 = @PYTHON3@
38511PYCOMPILE = $(top_srcdir)/autoconf/py-compile
38512
38513LIBS = @LIBS@
38514# Extra libraries always linked with static binaries
38515STATIC_LIBS = $(SELINUX_LIBS) $(UDEV_LIBS) $(BLKID_LIBS)
38516DEFS += @DEFS@
38517# FIXME set this only where it's needed, not globally?
38518CFLAGS ?= @COPTIMISE_FLAG@ @CFLAGS@
38519LDFLAGS ?= @COPTIMISE_FLAG@ @LDFLAGS@
38520CLDFLAGS += @CLDFLAGS@
38521ELDFLAGS += @ELDFLAGS@
38522LDDEPS += @LDDEPS@
38523LIB_SUFFIX = @LIB_SUFFIX@
38524LVMINTERNAL_LIBS = -llvm-internal $(DAEMON_LIBS) $(UDEV_LIBS) $(DL_LIBS) $(BLKID_LIBS)
38525DL_LIBS = @DL_LIBS@
38526M_LIBS = @M_LIBS@
38527PTHREAD_LIBS = @PTHREAD_LIBS@
38528READLINE_LIBS = @READLINE_LIBS@
38529SELINUX_LIBS = @SELINUX_LIBS@
38530UDEV_CFLAGS = @UDEV_CFLAGS@
38531UDEV_LIBS = @UDEV_LIBS@
38532BLKID_CFLAGS = @BLKID_CFLAGS@
38533BLKID_LIBS = @BLKID_LIBS@
38534VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
38535TESTING = @TESTING@
38536
38537# Setup directory variables
38538prefix = @prefix@
38539exec_prefix = @exec_prefix@
38540udev_prefix = @udev_prefix@
38541sysconfdir = @sysconfdir@
38542rootdir = $(DESTDIR)/
38543bindir = $(DESTDIR)@bindir@
38544confdir = $(DESTDIR)@CONFDIR@/lvm
38545includedir = $(DESTDIR)@includedir@
38546libdir = $(DESTDIR)@libdir@
38547libexecdir = $(DESTDIR)@libexecdir@
38548usrlibdir = $(DESTDIR)@usrlibdir@
38549sbindir = $(DESTDIR)@sbindir@
38550usrsbindir = $(DESTDIR)@usrsbindir@
38551datarootdir = @datarootdir@
38552datadir = $(DESTDIR)@datadir@
38553infodir = $(DESTDIR)@infodir@
38554mandir = $(DESTDIR)@mandir@
38555localedir = $(DESTDIR)@localedir@
38556staticdir = $(DESTDIR)@STATICDIR@
38557udevdir = $(DESTDIR)@udevdir@
38558pkgconfigdir = $(usrlibdir)/pkgconfig
38559initdir = $(DESTDIR)$(sysconfdir)/rc.d/init.d
38560dbusconfdir = $(DESTDIR)$(sysconfdir)/dbus-1/system.d
38561dbusservicedir = $(datadir)/dbus-1/system-services
38562systemd_unit_dir = $(DESTDIR)@systemdsystemunitdir@
38563systemd_generator_dir = $(DESTDIR)$(SYSTEMD_GENERATOR_DIR)
38564systemd_dir = $(DESTDIR)@systemdutildir@
38565tmpfiles_dir = $(DESTDIR)@tmpfilesdir@
38566ocf_scriptdir = $(DESTDIR)@OCFDIR@
38567pythonprefix = $(DESTDIR)$(prefix)
38568
38569# N.B. No $(DESTDIR) prefix here.
38570python2dir = @PYTHON2DIR@
38571python3dir = @PYTHON3DIR@
38572
38573USRLIB_RELPATH = @libdir@/
38574
38575SYSTEMD_GENERATOR_DIR = @systemdutildir@/system-generators
38576DEFAULT_SYS_DIR = @DEFAULT_SYS_DIR@
38577DEFAULT_ARCHIVE_DIR = $(DEFAULT_SYS_DIR)/@DEFAULT_ARCHIVE_SUBDIR@
38578DEFAULT_BACKUP_DIR = $(DEFAULT_SYS_DIR)/@DEFAULT_BACKUP_SUBDIR@
38579DEFAULT_CACHE_DIR = $(DEFAULT_SYS_DIR)/@DEFAULT_CACHE_SUBDIR@
38580DEFAULT_PROFILE_DIR = $(DEFAULT_SYS_DIR)/@DEFAULT_PROFILE_SUBDIR@
38581DEFAULT_LOCK_DIR = @DEFAULT_LOCK_DIR@
38582DEFAULT_RUN_DIR = @DEFAULT_RUN_DIR@
38583DEFAULT_MANGLING = @MANGLING@
38584
38585# Setup vpath search paths for some suffixes
38586vpath %.c $(srcdir)
38587vpath %.cpp $(srcdir)
38588vpath %.in $(srcdir)
38589vpath %.po $(srcdir)
38590vpath %.exported_symbols $(srcdir)
38591
38592interface = @interface@
38593interfacebuilddir = $(top_builddir)/libdm/$(interface)
38594rpmbuilddir = $(abs_top_builddir)/build
38595
38596# The number of jobs to run, if blank, defaults to the make standard
38597ifndef MAKEFLAGS
38598MAKEFLAGS = @JOBS@
38599endif
38600
38601# Handle installation of files
38602INSTALL_PROGRAM = $(INSTALL)
38603INSTALL_DATA = $(INSTALL) -m 644
38604INSTALL_WDATA = $(INSTALL_DATA)
38605
38606INSTALL_DIR = $(INSTALL) -m 755 -d
38607INSTALL_ROOT_DIR = $(INSTALL) -m 700 -d
38608INSTALL_ROOT_DATA = $(INSTALL) -m 600
38609INSTALL_SCRIPT = $(INSTALL_PROGRAM)
38610
38611.SUFFIXES: .c .cpp .d .o .so .a .po .pot .mo .dylib
38612
38613WFLAGS +=\
38614 -Wall\
38615 -Wcast-align\
38616 -Wfloat-equal\
38617 -Wformat-security\
38618 -Winline\
38619 -Wmissing-format-attribute\
38620 -Wmissing-include-dirs\
38621 -Wmissing-noreturn\
38622 -Wpointer-arith\
38623 -Wredundant-decls\
38624 -Wshadow\
38625 -Wundef\
38626 -Wwrite-strings
38627
38628WCFLAGS +=\
38629 -Wmissing-declarations\
38630 -Wmissing-prototypes\
38631 -Wnested-externs\
38632 -Wold-style-definition\
38633 -Wstrict-prototypes\
38634 -Wuninitialized
38635
38636ifeq ("@HAVE_WJUMP@", "yes")
38637WCFLAGS += -Wjump-misses-init
38638endif
38639
38640ifeq ("@HAVE_WCLOBBERED@", "yes")
38641WFLAGS +=\
38642 -Wclobbered\
38643 -Wempty-body\
38644 -Wignored-qualifiers\
38645 -Wlogical-op\
38646 -Wtype-limits
38647
38648WCFLAGS +=\
38649 -Wmissing-parameter-type\
38650 -Wold-style-declaration\
38651 -Woverride-init
38652endif
38653
38654ifeq ("@HAVE_WSYNCNAND@", "yes")
38655WFLAGS += -Wsync-nand
38656endif
38657
38658ifneq ("@STATIC_LINK@", "yes")
38659ifeq ("@HAVE_PIE@", "yes")
38660ifeq ("@HAVE_FULL_RELRO@", "yes")
38661 EXTRA_EXEC_CFLAGS += -fPIE
38662 EXTRA_EXEC_LDFLAGS += -Wl,-z,relro,-z,now -pie -fPIE
38663 CLDFLAGS += -Wl,-z,relro
38664endif
38665endif
38666endif
38667
38668#WFLAGS += -W -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers
38669#WFLAGS += -Wsign-compare -Wunused-parameter -Wmissing-field-initializers
38670#WFLAGS += -Wconversion -Wbad-function-cast -Wcast-qual -Waggregate-return -Wpacked
38671#WFLAGS += -pedantic -std=gnu99
38672#DEFS += -DDEBUG_CRC32
38673
38674#
38675# Avoid recursive extension of CFLAGS
38676# by checking whether CFLAGS already has fPIC string
38677#
38678ifeq (,$(findstring fPIC,$(CFLAGS)))
38679
38680CFLAGS += -fPIC
38681
38682ifeq ("@DEBUG@", "yes")
38683 CFLAGS += -g -fno-omit-frame-pointer
38684 DEFS += -DDEBUG
38685 # memory debugging is not thread-safe yet
38686 ifneq ("@DMEVENTD@", "yes")
38687 DEFS += -DDEBUG_MEM
38688 endif
38689endif
38690
38691# end of fPIC protection
38692endif
38693
38694LDFLAGS += -L$(top_builddir)/libdm -L$(top_builddir)/lib
38695CLDFLAGS += -L$(top_builddir)/libdm -L$(top_builddir)/lib
38696
38697DAEMON_LIBS = -ldaemonclient
38698LDFLAGS += -L$(top_builddir)/libdaemon/client
38699CLDFLAGS += -L$(top_builddir)/libdaemon/client
38700
38701ifeq ("@DMEVENTD@", "yes")
38702 LDFLAGS += -L$(top_builddir)/daemons/dmeventd
38703 CLDFLAGS += -L$(top_builddir)/daemons/dmeventd
38704endif
38705
38706# Combination of DEBUG_POOL and DEBUG_ENFORCE_POOL_LOCKING is not suppored.
38707#DEFS += -DDEBUG_POOL
38708# Default pool locking is using the crc checksum. With mprotect memory
38709# enforcing compilation faulty memory write could be easily found.
38710#DEFS += -DDEBUG_ENFORCE_POOL_LOCKING
38711#DEFS += -DBOUNDS_CHECK
38712
38713# LVM is not supposed to use mmap while devices are suspended.
38714# This code causes a core dump if gets called.
38715#DEFS += -DDEBUG_MEMLOCK
38716
38717#CFLAGS += -pg
38718#LDFLAGS += -pg
38719
38720STRIP=
38721#STRIP = -s
38722
38723LVM_VERSION := $(shell cat $(top_srcdir)/VERSION)
38724
38725LIB_VERSION_LVM := $(shell $(AWK) -F '.' '{printf "%s.%s",$$1,$$2}' $(top_srcdir)/VERSION)
38726
38727LIB_VERSION_DM := $(shell $(AWK) -F '.' '{printf "%s.%s",$$1,$$2}' $(top_srcdir)/VERSION_DM)
38728
38729LIB_VERSION_APP := $(shell $(AWK) -F '[(). ]' '{printf "%s.%s",$$1,$$4}' $(top_srcdir)/VERSION)
38730
38731INCLUDES += -I$(srcdir) -I$(top_builddir)/include
38732
38733INC_LNS = $(top_builddir)/include/.symlinks_created
38734
38735DEPS = $(top_builddir)/make.tmpl $(top_srcdir)/VERSION \
38736 $(top_builddir)/Makefile $(INC_LNS)
38737
38738OBJECTS = $(SOURCES:%.c=%.o) $(CXXSOURCES:%.cpp=%.o)
38739POTFILES = $(SOURCES:%.c=%.pot)
38740
38741.PHONY: all pofile distclean clean cleandir cflow device-mapper
38742.PHONY: install install_cluster install_device-mapper install_lvm2
38743.PHONY: install_dbus_service
38744.PHONY: install_lib_shared install_dm_plugin install_lvm2_plugin
38745.PHONY: install_ocf install_systemd_generators install_all_man all_man man help
38746.PHONY: python_bindings install_python_bindings
38747.PHONY: $(SUBDIRS) $(SUBDIRS.install) $(SUBDIRS.clean) $(SUBDIRS.distclean)
38748.PHONY: $(SUBDIRS.pofile) $(SUBDIRS.install_cluster) $(SUBDIRS.cflow)
38749.PHONY: $(SUBDIRS.device-mapper) $(SUBDIRS.install-device-mapper)
38750.PHONY: $(SUBDIRS.generate) generate
38751
38752SUBDIRS.device-mapper := $(SUBDIRS:=.device-mapper)
38753SUBDIRS.install := $(SUBDIRS:=.install)
38754SUBDIRS.install_cluster := $(SUBDIRS:=.install_cluster)
38755SUBDIRS.install_device-mapper := $(SUBDIRS:=.install_device-mapper)
38756SUBDIRS.install_lvm2 := $(SUBDIRS:=.install_lvm2)
38757SUBDIRS.install_ocf := $(SUBDIRS:=.install_ocf)
38758SUBDIRS.pofile := $(SUBDIRS:=.pofile)
38759SUBDIRS.cflow := $(SUBDIRS:=.cflow)
38760SUBDIRS.clean := $(SUBDIRS:=.clean)
38761SUBDIRS.distclean := $(SUBDIRS:=.distclean)
38762
38763TARGETS += $(LIB_SHARED) $(LIB_STATIC)
38764
38765all: $(SUBDIRS) $(TARGETS)
38766
38767install: all $(SUBDIRS.install)
38768install_cluster: all $(SUBDIRS.install_cluster)
38769install_device-mapper: $(SUBDIRS.install_device-mapper)
38770install_lvm2: $(SUBDIRS.install_lvm2)
38771install_ocf: $(SUBDIRS.install_ocf)
38772cflow: $(SUBDIRS.cflow)
38773
38774$(SUBDIRS): $(SUBDIRS.device-mapper)
38775 $(MAKE) -C $@
38776
38777$(SUBDIRS.device-mapper):
38778 $(MAKE) -C $(@:.device-mapper=) device-mapper
38779
38780$(SUBDIRS.install): $(SUBDIRS)
38781 $(MAKE) -C $(@:.install=) install
38782
38783$(SUBDIRS.install_cluster): $(SUBDIRS)
38784 $(MAKE) -C $(@:.install_cluster=) install_cluster
38785
38786$(SUBDIRS.install_device-mapper): device-mapper
38787 $(MAKE) -C $(@:.install_device-mapper=) install_device-mapper
38788
38789$(SUBDIRS.install_lvm2): $(SUBDIRS)
38790 $(MAKE) -C $(@:.install_lvm2=) install_lvm2
38791
38792$(SUBDIRS.install_ocf):
38793 $(MAKE) -C $(@:.install_ocf=) install_ocf
38794
38795$(SUBDIRS.clean):
38796 -$(MAKE) -C $(@:.clean=) clean
38797
38798$(SUBDIRS.distclean):
38799 -$(MAKE) -C $(@:.distclean=) distclean
38800
38801$(SUBDIRS.cflow):
38802 $(MAKE) -C $(@:.cflow=) cflow
38803
38804ifeq ("@INTL@", "yes")
38805pofile: $(SUBDIRS.pofile) $(POTFILES)
38806
38807$(SUBDIRS.pofile):
38808 $(MAKE) -C $(@:.pofile=) pofile
38809endif
38810
38811$(SUBDIRS.generate):
38812 $(MAKE) -C $(@:.generate=) generate
38813
38814ifneq ("$(CFLOW_LIST_TARGET)", "")
38815CLEAN_CFLOW += $(CFLOW_LIST_TARGET)
38816$(CFLOW_LIST_TARGET): $(CFLOW_LIST)
38817 echo "CFLOW_SOURCES += $(addprefix \
38818 \$$(top_srcdir)$(subst $(top_srcdir),,$(srcdir))/, $(CFLOW_LIST))" > $@
38819cflow: $(CFLOW_LIST_TARGET)
38820endif
38821
38822ifneq ("$(CFLOW_TARGET)", "")
38823CLEAN_CFLOW += \
38824 $(CFLOW_TARGET).cflow \
38825 $(CFLOW_TARGET).xref \
38826 $(CFLOW_TARGET).tree \
38827 $(CFLOW_TARGET).rtree \
38828 $(CFLOW_TARGET).rxref
38829
38830ifneq ("$(CFLOW_CMD)", "")
38831CFLOW_FLAGS +=\
38832 --cpp="$(CC) -E" \
38833 --symbol _ISbit:wrapper \
38834 --symbol __attribute__:wrapper \
38835 --symbol __const__:wrapper \
38836 --symbol __const:type \
38837 --symbol __restrict:type \
38838 --symbol __extension__:wrapper \
38839 --symbol __nonnull:wrapper \
38840 --symbol __nothrow__:wrapper \
38841 --symbol __pure__:wrapper \
38842 --symbol __REDIRECT:wrapper \
38843 --symbol __REDIRECT_NTH:wrapper \
38844 --symbol __wur:wrapper \
38845 -I$(top_srcdir)/libdm \
38846 -I$(top_srcdir)/libdm/ioctl \
38847 -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2/ \
38848 $(INCLUDES) $(DEFS)
38849
38850$(CFLOW_TARGET).cflow: $(CFLOW_SOURCES)
38851 $(CFLOW_CMD) -o$@ $(CFLOW_FLAGS) $(CFLOW_SOURCES)
38852$(CFLOW_TARGET).rxref: $(CFLOW_SOURCES)
38853 $(CFLOW_CMD) -o$@ $(CFLOW_FLAGS) -r --omit-arguments $(CFLOW_SOURCES)
38854$(CFLOW_TARGET).tree: $(CFLOW_SOURCES)
38855 $(CFLOW_CMD) -o$@ $(CFLOW_FLAGS) --omit-arguments -T -b $(CFLOW_SOURCES)
38856$(CFLOW_TARGET).xref: $(CFLOW_SOURCES)
38857 $(CFLOW_CMD) -o$@ $(CFLOW_FLAGS) --omit-arguments -x $(CFLOW_SOURCES)
38858#$(CFLOW_TARGET).rtree: $(CFLOW_SOURCES)
38859# $(CFLOW_CMD) -o$@ $(CFLOW_FLAGS) -r --omit-arguments -T -b $(CFLOW_SOURCES)
38860cflow: $(CFLOW_TARGET).cflow $(CFLOW_TARGET).tree $(CFLOW_TARGET).rxref $(CFLOW_TARGET).xref
38861#$(CFLOW_TARGET).rtree
38862endif
38863endif
38864
38865%.o: %.c
38866 $(CC) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(WCFLAGS) $(CFLAGS) $(CFLAGS_$@) $< -o $@
38867
38868%.o: %.cpp
38869 $(CXX) -c $(INCLUDES) $(DEFS) $(WFLAGS) $(CXXFLAGS) $(CXXFLAGS_$@) $< -o $@
38870
38871%.pot: %.c Makefile
38872 $(CC) -E $(INCLUDES) $(BLKID_CFLAGS) $(VALGRIND_CFLAGS) $(UDEV_CFLAGS) -include $(top_builddir)/include/pogen.h \
38873 $(DEFS) $(WFLAGS) $(CFLAGS) $< > $@
38874
38875%.so: %.o
38876 $(CC) -c $(CFLAGS) $(CLDFLAGS) $< $(LIBS) -o $@
38877
38878ifneq (,$(LIB_SHARED))
38879
38880TARGETS += $(LIB_SHARED).$(LIB_VERSION)
38881$(LIB_SHARED).$(LIB_VERSION): $(OBJECTS) $(LDDEPS)
38882ifeq ("@LIB_SUFFIX@","so")
38883 $(CC) -shared -Wl,-soname,$(notdir $@) \
38884 $(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
38885endif
38886ifeq ("@LIB_SUFFIX@","dylib")
38887 $(CC) -dynamiclib -dylib_current_version,$(LIB_VERSION) \
38888 $(CFLAGS) $(CLDFLAGS) $(OBJECTS) $(LIBS) -o $@
38889endif
38890
38891$(LIB_SHARED): $(LIB_SHARED).$(LIB_VERSION)
38892 $(LN_S) -f $(<F) $@
38893
38894CLEAN_TARGETS += $(LDDEPS) .exported_symbols_generated
38895
38896install_lib_shared: $(LIB_SHARED)
38897 $(INSTALL_PROGRAM) -D $< $(libdir)/$(<F).$(LIB_VERSION)
38898 $(INSTALL_DIR) $(usrlibdir)
38899 $(LN_S) -f $(USRLIB_RELPATH)$(<F).$(LIB_VERSION) $(usrlibdir)/$(<F)
38900
38901# FIXME: plugins are installed to subdirs
38902# and for compatibility links in libdir are created
38903# when the code is fixed links could be removed.
38904install_dm_plugin: $(LIB_SHARED)
38905 $(INSTALL_PROGRAM) -D $< $(libdir)/device-mapper/$(<F)
38906 $(LN_S) -f device-mapper/$(<F) $(libdir)/$(<F)
38907
38908install_lvm2_plugin: $(LIB_SHARED)
38909 $(INSTALL_PROGRAM) -D $< $(libdir)/lvm2/$(<F)
38910 $(LN_S) -f lvm2/$(<F) $(libdir)/$(<F)
38911 $(LN_S) -f $(<F) $(libdir)/$(<F).$(LIB_VERSION)
38912endif
38913
38914$(LIB_STATIC): $(OBJECTS)
38915 $(RM) $@
38916 $(AR) rs $@ $(OBJECTS)
38917
38918%.d: %.c $(INC_LNS)
38919 $(MKDIR_P) $(dir $@); \
38920 set -e; \
38921 FILE=`echo $@ | sed 's/\\//\\\\\\//g;s/\\.d//g'`; \
38922 DEPS=`echo $(DEPS) | sed -e 's/\\//\\\\\\//g'`; \
38923 $(CC) -MM $(INCLUDES) $(BLKID_CFLAGS) $(VALGRIND_CFLAGS) $(UDEV_CFLAGS) $(DEFS) -o $@ $<; \
38924 sed -i "s/\(.*\)\.o[ :]*/$$FILE.o $$FILE.d $$FILE.pot: $$DEPS /g" $@; \
38925 DEPLIST=`sed 's/ \\\\//;s/.*://;' < $@`; \
38926 echo $$DEPLIST | fmt -1 | sed 's/ //g;s/\(.*\)/\1:/' >> $@; \
38927 [ -s $@ ] || $(RM) $@
38928
38929%.mo: %.po
38930 $(MSGFMT) -o $@ $<
38931
38932CLEAN_TARGETS += \
38933 $(SOURCES:%.c=%.d) $(SOURCES:%.c=%.gcno) $(SOURCES:%.c=%.gcda) \
38934 $(SOURCES2:%.c=%.o) $(SOURCES2:%.c=%.d) $(SOURCES2:%.c=%.gcno) $(SOURCES2:%.c=%.gcda) \
38935 $(POTFILES) $(CLEAN_CFLOW)
38936
38937cleandir:
38938ifneq (,$(firstword $(CLEAN_DIRS)))
38939 $(RM) -r $(CLEAN_DIRS)
38940endif
38941 $(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) core
38942
38943clean: $(SUBDIRS.clean) cleandir
38944
38945distclean: cleandir $(SUBDIRS.distclean)
38946ifneq (,$(firstword $(DISTCLEAN_DIRS)))
38947 $(RM) -r $(DISTCLEAN_DIRS)
38948endif
38949 $(RM) $(DISTCLEAN_TARGETS) Makefile
38950
38951.exported_symbols_generated: $(EXPORTED_HEADER) .exported_symbols $(DEPS)
38952 set -e; \
38953 ( cat $(srcdir)/.exported_symbols; \
38954 if test -n "$(EXPORTED_HEADER)"; then \
38955 $(CC) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \
38956 $(SED) -ne "/^typedef|}/!s/.*[ *]\($(EXPORTED_FN_PREFIX)_[a-z0-9_]*\)(.*/\1/p"; \
38957 fi \
38958 ) > $@
38959
38960EXPORTED_UC := $(shell echo $(EXPORTED_FN_PREFIX) | tr '[a-z]' '[A-Z]')
38961EXPORTED_SYMBOLS := $(wildcard $(srcdir)/.exported_symbols.Base $(srcdir)/.exported_symbols.$(EXPORTED_UC)_[0-9_]*[0-9])
38962
38963.export.sym: .exported_symbols_generated $(EXPORTED_SYMBOLS)
38964ifeq (,$(firstword $(EXPORTED_SYMBOLS)))
38965 set -e; (echo "Base {"; echo " global:";\
38966 $(SED) "s/^/ /;s/$$/;/" $<;\
38967 echo "};";\
38968 echo "Local {"; echo " local:"; echo " *;"; echo "};";\
38969 ) > $@
38970else
38971 set -e;\
38972 R=$$(sort $^ | uniq -u);\
38973 test -z "$$R" || { echo "Mismatch between symbols in shared library and lists in .exported_symbols.* files: $$R"; false; } ;\
38974 ( for i in $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | sort -rnt_ -k5 ); do\
38975 echo "$${i##*.} {"; echo " global:";\
38976 $(SED) "s/^/ /;s/$$/;/" $$i;\
38977 echo "};";\
38978 done;\
38979 echo "Local {"; echo " local:"; echo " *;"; echo "};";\
38980 ) > $@
38981endif
38982
38983ifeq ("@USE_TRACKING@","yes")
38984ifeq (,$(findstring $(MAKECMDGOALS),cscope.out cflow clean distclean lcov \
38985 help check check_local check_cluster check_lvmetad check_lvmpolld))
38986 ifdef SOURCES
38987 -include $(SOURCES:.c=.d) $(CXXSOURCES:.cpp=.d)
38988 endif
38989 ifdef SOURCES2
38990 -include $(SOURCES2:.c=.d)
38991 endif
38992endif
38993endif
38994\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/acinclude.m4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003466\013062740170\0017251\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dnl AC_GCC_VERSION
38995dnl check for compiler version
38996dnl sets COMPILER_VERSION and GCC_VERSION
38997
38998AC_DEFUN([AC_CC_VERSION],
38999[
39000 AC_MSG_CHECKING([C compiler version])
39001 COMPILER_VERSION=`$CC -v 2>&1 | grep version`
39002 case "$COMPILER_VERSION" in
39003 *gcc*)
39004 dnl Ok, how to turn $3 into the real $3
39005 GCC_VERSION=`echo $COMPILER_VERSION | \
39006 sed -e 's/[[^ ]]*\ [[^ ]]*\ \([[^ ]]*\)\ .*/\1/'` ;;
39007 *) GCC_VERSION=unknown ;;
39008 esac
39009 AC_MSG_RESULT($GCC_VERSION)
39010])
39011
39012dnl AC_TRY_CCFLAG([CCFLAG], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS])
39013dnl check if $CC supports a given flag
39014
39015AC_DEFUN([AC_TRY_CCFLAG],
39016[
39017 AC_REQUIRE([AC_PROG_CC])
39018 ac_save_CFLAGS=$CFLAGS
39019 CFLAGS=$1
39020 AC_CACHE_CHECK([whether $CC accepts $1 flag], [ac_cv_flag_$2],
39021 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
39022 [AS_VAR_SET([ac_cv_flag_$2], [yes])],
39023 [AS_VAR_SET([ac_cv_flag_$2], [no])])])
39024 CFLAGS=$ac_save_CFLAGS
39025 $2=AS_VAR_GET([ac_cv_flag_$2])
39026 if test "$2" = yes; then
39027 ifelse([$3], [], [:], [$3])
39028 else
39029 ifelse([$4], [], [:], [$4])
39030 fi
39031])
39032
39033dnl AC_IF_YES([TEST-FOR-YES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
39034dnl AS_IF() abstraction, checks shell variable for 'yes'
39035AC_DEFUN([AC_IF_YES], [AS_IF([test $$1 = yes], [$2], [$3])])
39036
39037dnl AC_TRY_LDFLAGS([LDFLAGS], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS])
39038dnl check if $CC supports given ld flags
39039
39040AC_DEFUN([AC_TRY_LDFLAGS],
39041[
39042 AC_REQUIRE([AC_PROG_CC])
39043 ac_save_LDFLAGS=$LDFLAGS
39044 LDFLAGS=$1
39045 AC_CACHE_CHECK([whether $CC accepts $1 ld flags], [ac_cv_flag_$2],
39046 [AC_LINK_IFELSE([AC_LANG_PROGRAM()],
39047 [AS_VAR_SET([ac_cv_flag_$2], [yes])],
39048 [AS_VAR_SET([ac_cv_flag_$2], [no])])])
39049 LDFLAGS=$ac_save_LDFLAGS
39050 $2=AS_VAR_GET([ac_cv_flag_$2])
39051 if test "$2" = yes; then
39052 ifelse([$3], [], [:], [$3])
39053 else
39054 ifelse([$4], [], [:], [$4])
39055 fi
39056])
39057\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/VERSION_DM\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000026\013062740170\0016475\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01.02.137 (2016-11-30)
39058\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0016475\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020315\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003164\013062740170\0022366\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
39059# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
39060#
39061# This file is part of LVM2.
39062#
39063# This copyrighted material is made available to anyone wishing to use,
39064# modify, copy, or redistribute it subject to the terms and conditions
39065# of the GNU General Public License v.2.
39066#
39067# You should have received a copy of the GNU General Public License
39068# along with this program; if not, write to the Free Software Foundation,
39069# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
39070
39071srcdir = @srcdir@
39072top_srcdir = @top_srcdir@
39073top_builddir = @top_builddir@
39074
39075lvmdbusdir = $(python3dir)/lvmdbusd
39076
39077LVMDBUS_SRCDIR_FILES = \
39078 automatedproperties.py \
39079 background.py \
39080 cfg.py \
39081 cmdhandler.py \
39082 fetch.py \
39083 __init__.py \
39084 job.py \
39085 loader.py \
39086 lvmdb.py \
39087 main.py \
39088 lvm_shell_proxy.py \
39089 lv.py \
39090 manager.py \
39091 objectmanager.py \
39092 pv.py \
39093 request.py \
39094 state.py \
39095 udevwatch.py \
39096 utils.py \
39097 vg.py
39098
39099LVMDBUS_BUILDDIR_FILES = \
39100 path.py
39101
39102LVMDBUSD = $(srcdir)/lvmdbusd
39103
39104include $(top_builddir)/make.tmpl
39105
39106.PHONY: install_lvmdbusd
39107
39108install_lvmdbusd:
39109 $(INSTALL_DIR) $(sbindir)
39110 $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
39111 $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
39112 (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
39113 $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
39114 PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
39115 $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
39116 $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
39117
39118install_lvm2: install_lvmdbusd
39119
39120install: install_lvm2
39121
39122DISTCLEAN_TARGETS+= \
39123 $(LVMDBUS_BUILDDIR_FILES)
39124\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/udevwatch.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002635\013062740170\0022667\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
39125#
39126# This copyrighted material is made available to anyone wishing to use,
39127# modify, copy, or redistribute it subject to the terms and conditions
39128# of the GNU General Public License v.2.
39129#
39130# You should have received a copy of the GNU General Public License
39131# along with this program. If not, see <http://www.gnu.org/licenses/>.
39132
39133import pyudev
39134import threading
39135from . import cfg
39136
39137observer = None
39138observer_lock = threading.RLock()
39139
39140
39141# noinspection PyUnusedLocal
39142def filter_event(action, device):
39143 # Filter for events of interest and add a request object to be processed
39144 # when appropriate.
39145 refresh = False
39146
39147 if '.ID_FS_TYPE_NEW' in device:
39148 fs_type_new = device['.ID_FS_TYPE_NEW']
39149
39150 if 'LVM' in fs_type_new:
39151 refresh = True
39152 elif fs_type_new == '':
39153 # Check to see if the device was one we knew about
39154 if 'DEVNAME' in device:
39155 found = cfg.om.get_object_by_lvm_id(device['DEVNAME'])
39156 if found:
39157 refresh = True
39158
39159 if 'DM_LV_NAME' in device:
39160 refresh = True
39161
39162 if refresh:
39163 cfg.event()
39164
39165
39166def add():
39167 with observer_lock:
39168 global observer
39169 context = pyudev.Context()
39170 monitor = pyudev.Monitor.from_netlink(context)
39171 monitor.filter_by('block')
39172 observer = pyudev.MonitorObserver(monitor, filter_event)
39173 observer.start()
39174
39175
39176def remove():
39177 with observer_lock:
39178 global observer
39179 if observer:
39180 observer.stop()
39181 observer = None
39182 return True
39183 return False
39184\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/background.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010421\013062740170\0023004\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
39185#
39186# This copyrighted material is made available to anyone wishing to use,
39187# modify, copy, or redistribute it subject to the terms and conditions
39188# of the GNU General Public License v.2.
39189#
39190# You should have received a copy of the GNU General Public License
39191# along with this program. If not, see <http://www.gnu.org/licenses/>.
39192
39193import subprocess
39194from . import cfg
39195from .cmdhandler import options_to_cli_args
39196import dbus
39197from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
39198import os
39199import threading
39200
39201
39202def pv_move_lv_cmd(move_options, lv_full_name,
39203 pv_source, pv_source_range, pv_dest_range_list):
39204 cmd = ['pvmove', '-i', '1']
39205 cmd.extend(options_to_cli_args(move_options))
39206
39207 if lv_full_name:
39208 cmd.extend(['-n', lv_full_name])
39209
39210 pv_range_append(cmd, pv_source, *pv_source_range)
39211 pv_dest_ranges(cmd, pv_dest_range_list)
39212
39213 return cmd
39214
39215
39216def lv_merge_cmd(merge_options, lv_full_name):
39217 cmd = ['lvconvert', '--merge', '-i', '1']
39218 cmd.extend(options_to_cli_args(merge_options))
39219 cmd.append(lv_full_name)
39220 return cmd
39221
39222
39223def _move_merge(interface_name, command, job_state):
39224 # We need to execute these command stand alone by forking & exec'ing
39225 # the command always as we will be getting periodic output from them on
39226 # the status of the long running operation.
39227 command.insert(0, cfg.LVM_CMD)
39228 process = subprocess.Popen(command, stdout=subprocess.PIPE,
39229 env=os.environ,
39230 stderr=subprocess.PIPE, close_fds=True)
39231
39232 log_debug("Background process for %s is %d" %
39233 (str(command), process.pid))
39234
39235 lines_iterator = iter(process.stdout.readline, b"")
39236 for line in lines_iterator:
39237 line_str = line.decode("utf-8")
39238
39239 # Check to see if the line has the correct number of separators
39240 try:
39241 if line_str.count(':') == 2:
39242 (device, ignore, percentage) = line_str.split(':')
39243 job_state.Percent = round(
39244 float(percentage.strip()[:-1]), 1)
39245 except ValueError:
39246 log_error("Trying to parse percentage which failed for %s" %
39247 line_str)
39248
39249 out = process.communicate()
39250
39251 if process.returncode == 0:
39252 job_state.Percent = 100
39253 else:
39254 raise dbus.exceptions.DBusException(
39255 interface_name,
39256 'Exit code %s, stderr = %s' % (str(process.returncode), out[1]))
39257
39258 cfg.load()
39259 return '/'
39260
39261
39262def move(interface_name, lv_name, pv_src_obj, pv_source_range,
39263 pv_dests_and_ranges, move_options, job_state):
39264 """
39265 Common code for the pvmove handling.
39266 :param interface_name: What dbus interface we are providing for
39267 :param lv_name: Optional (None or name of LV to move)
39268 :param pv_src_obj: dbus object patch for source PV
39269 :param pv_source_range: (0,0 to ignore, else start, end segments)
39270 :param pv_dests_and_ranges: Array of PV object paths and start/end segs
39271 :param move_options: Hash with optional arguments
39272 :param job_state: Used to convey information about jobs between processes
39273 :return: '/' When complete, the empty object path
39274 """
39275 pv_dests = []
39276 pv_src = cfg.om.get_object_by_path(pv_src_obj)
39277 if pv_src:
39278
39279 # Check to see if we are handling a move to a specific
39280 # destination(s)
39281 if len(pv_dests_and_ranges):
39282 for pr in pv_dests_and_ranges:
39283 pv_dbus_obj = cfg.om.get_object_by_path(pr[0])
39284 if not pv_dbus_obj:
39285 raise dbus.exceptions.DBusException(
39286 interface_name,
39287 'PV Destination (%s) not found' % pr[0])
39288
39289 pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
39290
39291 cmd = pv_move_lv_cmd(move_options,
39292 lv_name,
39293 pv_src.lvm_id,
39294 pv_source_range,
39295 pv_dests)
39296
39297 return _move_merge(interface_name, cmd, job_state)
39298 else:
39299 raise dbus.exceptions.DBusException(
39300 interface_name, 'pv_src_obj (%s) not found' % pv_src_obj)
39301
39302
39303def merge(interface_name, lv_uuid, lv_name, merge_options, job_state):
39304 # Make sure we have a dbus object representing it
39305 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
39306 if dbo:
39307 cmd = lv_merge_cmd(merge_options, dbo.lvm_id)
39308 return _move_merge(interface_name, cmd, job_state)
39309 else:
39310 raise dbus.exceptions.DBusException(
39311 interface_name,
39312 'LV with uuid %s and name %s not present!' % (lv_uuid, lv_name))
39313
39314
39315def _run_cmd(req):
39316 log_debug(
39317 "_run_cmd: Running method: %s with args %s" %
39318 (str(req.method), str(req.arguments)))
39319 req.run_cmd()
39320 log_debug("_run_cmd: complete!")
39321
39322
39323def cmd_runner(request):
39324 t = threading.Thread(target=_run_cmd, args=(request,))
39325 t.start()
39326\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/lvm_shell_proxy.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000015627\013062740170\0024133\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/usr/bin/env python3
39327
39328# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
39329#
39330# This copyrighted material is made available to anyone wishing to use,
39331# modify, copy, or redistribute it subject to the terms and conditions
39332# of the GNU General Public License v.2.
39333#
39334# You should have received a copy of the GNU General Public License
39335# along with this program. If not, see <http://www.gnu.org/licenses/>.
39336#
39337# Copyright 2015-2016, Vratislav Podzimek <vpodzime@redhat.com>
39338
39339import subprocess
39340import shlex
39341from fcntl import fcntl, F_GETFL, F_SETFL
39342import os
39343import traceback
39344import sys
39345import tempfile
39346import time
39347import select
39348import copy
39349
39350try:
39351 import simplejson as json
39352except ImportError:
39353 import json
39354
39355
39356from lvmdbusd.cfg import LVM_CMD
39357from lvmdbusd.utils import log_debug, log_error
39358
39359SHELL_PROMPT = "lvm> "
39360
39361
39362def _quote_arg(arg):
39363 if len(shlex.split(arg)) > 1:
39364 return '"%s"' % arg
39365 else:
39366 return arg
39367
39368
39369class LVMShellProxy(object):
39370
39371 @staticmethod
39372 def _read(stream):
39373 tmp = stream.read()
39374 if tmp:
39375 return tmp.decode("utf-8")
39376 return ''
39377
39378 # Read until we get prompt back and a result
39379 # @param: no_output Caller expects no output to report FD
39380 # Returns stdout, report, stderr (report is JSON!)
39381 def _read_until_prompt(self, no_output=False):
39382 stdout = ""
39383 report = ""
39384 stderr = ""
39385 keep_reading = True
39386 extra_passes = 3
39387 report_json = {}
39388 prev_report_len = 0
39389
39390 # Try reading from all FDs to prevent one from filling up and causing
39391 # a hang. Keep reading until we get the prompt back and the report
39392 # FD does not contain valid JSON
39393 while keep_reading:
39394 try:
39395 rd_fd = [
39396 self.lvm_shell.stdout.fileno(),
39397 self.report_stream.fileno(),
39398 self.lvm_shell.stderr.fileno()]
39399 ready = select.select(rd_fd, [], [], 2)
39400
39401 for r in ready[0]:
39402 if r == self.lvm_shell.stdout.fileno():
39403 stdout += LVMShellProxy._read(self.lvm_shell.stdout)
39404 elif r == self.report_stream.fileno():
39405 report += LVMShellProxy._read(self.report_stream)
39406 elif r == self.lvm_shell.stderr.fileno():
39407 stderr += LVMShellProxy._read(self.lvm_shell.stderr)
39408
39409 # Check to see if the lvm process died on us
39410 if self.lvm_shell.poll():
39411 raise Exception(self.lvm_shell.returncode, "%s" % stderr)
39412
39413 if stdout.endswith(SHELL_PROMPT):
39414 if no_output:
39415 keep_reading = False
39416 else:
39417 cur_report_len = len(report)
39418 if cur_report_len != 0:
39419 # Only bother to parse if we have more data
39420 if prev_report_len != cur_report_len:
39421 prev_report_len = cur_report_len
39422 # Parse the JSON if it's good we are done,
39423 # if not we will try to read some more.
39424 try:
39425 report_json = json.loads(report)
39426 keep_reading = False
39427 except ValueError:
39428 pass
39429
39430 if keep_reading:
39431 extra_passes -= 1
39432 if extra_passes <= 0:
39433 if len(report):
39434 raise ValueError("Invalid json: %s" %
39435 report)
39436 else:
39437 raise ValueError(
39438 "lvm returned no JSON output!")
39439
39440 except IOError as ioe:
39441 log_debug(str(ioe))
39442 pass
39443
39444 return stdout, report_json, stderr
39445
39446 def _write_cmd(self, cmd):
39447 cmd_bytes = bytes(cmd, "utf-8")
39448 num_written = self.lvm_shell.stdin.write(cmd_bytes)
39449 assert (num_written == len(cmd_bytes))
39450 self.lvm_shell.stdin.flush()
39451
39452 @staticmethod
39453 def _make_non_block(stream):
39454 flags = fcntl(stream, F_GETFL)
39455 fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
39456
39457 def __init__(self):
39458
39459 # Create a temp directory
39460 tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
39461 tmp_file = "%s/lvmdbus_report" % (tmp_dir)
39462
39463 try:
39464 # Lets create fifo for the report output
39465 os.mkfifo(tmp_file, 0o600)
39466 except FileExistsError:
39467 pass
39468
39469 # We have to open non-blocking as the other side isn't open until
39470 # we actually fork the process.
39471 self.report_fd = os.open(tmp_file, os.O_NONBLOCK)
39472 self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
39473
39474 # Setup the environment for using our own socket for reporting
39475 local_env = copy.deepcopy(os.environ)
39476 local_env["LVM_REPORT_FD"] = "32"
39477 local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
39478
39479 # Disable the abort logic if lvm logs too much, which easily happens
39480 # when utilizing the lvm shell.
39481 local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
39482
39483 # run the lvm shell
39484 self.lvm_shell = subprocess.Popen(
39485 [LVM_CMD + " 32>%s" % tmp_file],
39486 stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
39487 stderr=subprocess.PIPE, close_fds=True, shell=True)
39488
39489 try:
39490 LVMShellProxy._make_non_block(self.lvm_shell.stdout)
39491 LVMShellProxy._make_non_block(self.lvm_shell.stderr)
39492
39493 # wait for the first prompt
39494 errors = self._read_until_prompt(no_output=True)[2]
39495 if errors and len(errors):
39496 raise RuntimeError(errors)
39497 except:
39498 raise
39499 finally:
39500 # These will get deleted when the FD count goes to zero so we
39501 # can be sure to clean up correctly no matter how we finish
39502 os.unlink(tmp_file)
39503 os.rmdir(tmp_dir)
39504
39505 def get_error_msg(self):
39506 # We got an error, lets go fetch the error message
39507 self._write_cmd('lastlog\n')
39508
39509 # read everything from the STDOUT to the next prompt
39510 stdout, report_json, stderr = self._read_until_prompt()
39511 if 'log' in report_json:
39512 error_msg = ""
39513 # Walk the entire log array and build an error string
39514 for log_entry in report_json['log']:
39515 if log_entry['log_type'] == "error":
39516 if error_msg:
39517 error_msg += ', ' + log_entry['log_message']
39518 else:
39519 error_msg = log_entry['log_message']
39520
39521 return error_msg
39522
39523 return 'No error reason provided! (missing "log" section)'
39524
39525 def call_lvm(self, argv, debug=False):
39526 rc = 1
39527 error_msg = ""
39528
39529 if self.lvm_shell.poll():
39530 raise Exception(
39531 self.lvm_shell.returncode,
39532 "Underlying lvm shell process is not present!")
39533
39534 # create the command string
39535 cmd = " ".join(_quote_arg(arg) for arg in argv)
39536 cmd += "\n"
39537
39538 # run the command by writing it to the shell's STDIN
39539 self._write_cmd(cmd)
39540
39541 # read everything from the STDOUT to the next prompt
39542 stdout, report_json, stderr = self._read_until_prompt()
39543
39544 # Parse the report to see what happened
39545 if 'log' in report_json:
39546 if report_json['log'][-1:][0]['log_ret_code'] == '1':
39547 rc = 0
39548 else:
39549 error_msg = self.get_error_msg()
39550
39551 if debug or rc != 0:
39552 log_error(('CMD: %s' % cmd))
39553 log_error(("EC = %d" % rc))
39554 log_error(("ERROR_MSG=\n %s\n" % error_msg))
39555
39556 return rc, report_json, error_msg
39557
39558 def exit_shell(self):
39559 try:
39560 self._write_cmd('exit\n')
39561 except Exception as e:
39562 log_error(str(e))
39563
39564 def __del__(self):
39565 try:
39566 self.lvm_shell.terminate()
39567 except:
39568 pass
39569
39570
39571if __name__ == "__main__":
39572 shell = LVMShellProxy()
39573 in_line = "start"
39574 try:
39575 while in_line:
39576 in_line = input("lvm> ")
39577 if in_line:
39578 start = time.time()
39579 ret, out, err = shell.call_lvm(in_line.split())
39580 end = time.time()
39581
39582 print(("RC: %d" % ret))
39583 print(("OUT:\n%s" % out))
39584 print(("ERR:\n%s" % err))
39585
39586 print("Command = %f seconds" % (end - start))
39587 except KeyboardInterrupt:
39588 pass
39589 except EOFError:
39590 pass
39591 except Exception:
39592 traceback.print_exc(file=sys.stdout)
39593\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/manager.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000016221\013062740170\0022303\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
39594#
39595# This copyrighted material is made available to anyone wishing to use,
39596# modify, copy, or redistribute it subject to the terms and conditions
39597# of the GNU General Public License v.2.
39598#
39599# You should have received a copy of the GNU General Public License
39600# along with this program. If not, see <http://www.gnu.org/licenses/>.
39601
39602from .automatedproperties import AutomatedProperties
39603
39604from . import utils
39605from .cfg import MANAGER_INTERFACE
39606import dbus
39607from . import cfg
39608from . import cmdhandler
39609from .request import RequestEntry
39610from . import udevwatch
39611
39612
39613# noinspection PyPep8Naming
39614class Manager(AutomatedProperties):
39615 _Version_meta = ("s", MANAGER_INTERFACE)
39616
39617 def __init__(self, object_path):
39618 super(Manager, self).__init__(object_path)
39619 self.set_interface(MANAGER_INTERFACE)
39620
39621 @property
39622 def Version(self):
39623 return dbus.String('1.0.0')
39624
39625 @staticmethod
39626 def _pv_create(device, create_options):
39627
39628 # Check to see if we are already trying to create a PV for an existing
39629 # PV
39630 pv = cfg.om.get_object_path_by_uuid_lvm_id(device, device)
39631 if pv:
39632 raise dbus.exceptions.DBusException(
39633 MANAGER_INTERFACE, "PV Already exists!")
39634
39635 rc, out, err = cmdhandler.pv_create(create_options, [device])
39636 if rc == 0:
39637 cfg.load()
39638 created_pv = cfg.om.get_object_path_by_lvm_id(device)
39639 else:
39640 raise dbus.exceptions.DBusException(
39641 MANAGER_INTERFACE,
39642 'Exit code %s, stderr = %s' % (str(rc), err))
39643
39644 return created_pv
39645
39646 @dbus.service.method(
39647 dbus_interface=MANAGER_INTERFACE,
39648 in_signature='sia{sv}',
39649 out_signature='(oo)',
39650 async_callbacks=('cb', 'cbe'))
39651 def PvCreate(self, device, tmo, create_options, cb, cbe):
39652 utils.validate_device_path(MANAGER_INTERFACE, device)
39653 r = RequestEntry(
39654 tmo, Manager._pv_create,
39655 (device, create_options), cb, cbe)
39656 cfg.worker_q.put(r)
39657
39658 @staticmethod
39659 def _create_vg(name, pv_object_paths, create_options):
39660 pv_devices = []
39661
39662 for p in pv_object_paths:
39663 pv = cfg.om.get_object_by_path(p)
39664 if pv:
39665 pv_devices.append(pv.Name)
39666 else:
39667 raise dbus.exceptions.DBusException(
39668 MANAGER_INTERFACE, 'object path = %s not found' % p)
39669
39670 rc, out, err = cmdhandler.vg_create(create_options, pv_devices, name)
39671
39672 if rc == 0:
39673 cfg.load()
39674 return cfg.om.get_object_path_by_lvm_id(name)
39675 else:
39676 raise dbus.exceptions.DBusException(
39677 MANAGER_INTERFACE,
39678 'Exit code %s, stderr = %s' % (str(rc), err))
39679
39680 @dbus.service.method(
39681 dbus_interface=MANAGER_INTERFACE,
39682 in_signature='saoia{sv}',
39683 out_signature='(oo)',
39684 async_callbacks=('cb', 'cbe'))
39685 def VgCreate(self, name, pv_object_paths, tmo, create_options, cb, cbe):
39686 utils.validate_vg_name(MANAGER_INTERFACE, name)
39687 r = RequestEntry(
39688 tmo, Manager._create_vg,
39689 (name, pv_object_paths, create_options,),
39690 cb, cbe)
39691 cfg.worker_q.put(r)
39692
39693 @staticmethod
39694 def _refresh():
39695 utils.log_debug('Manager.Refresh - entry')
39696
39697 # This is a diagnostic and should not be run in normal operation, so
39698 # lets remove the log entries for refresh as it's implied.
39699
39700 # Run an internal diagnostic on the object manager look up tables
39701 lc = cfg.om.validate_lookups()
39702
39703 rc = cfg.load(log=False)
39704
39705 if rc != 0:
39706 utils.log_debug('Manager.Refresh - exit %d' % (rc),
39707 'bg_black', 'fg_light_red')
39708 else:
39709 utils.log_debug('Manager.Refresh - exit %d' % (rc))
39710 return rc + lc
39711
39712 @dbus.service.method(
39713 dbus_interface=MANAGER_INTERFACE,
39714 out_signature='t',
39715 async_callbacks=('cb', 'cbe'))
39716 def Refresh(self, cb, cbe):
39717 """
39718 Take all the objects we know about and go out and grab the latest
39719 more of a test method at the moment to make sure we are handling object
39720 paths correctly.
39721
39722 :param cb Callback for result
39723 :param cbe Callback for errors
39724
39725 Returns the number of changes, object add/remove/properties changed
39726 """
39727 r = RequestEntry(-1, Manager._refresh, (), cb, cbe, False)
39728 cfg.worker_q.put(r)
39729
39730 @dbus.service.method(
39731 dbus_interface=MANAGER_INTERFACE,
39732 in_signature='s',
39733 out_signature='o')
39734 def LookUpByLvmId(self, key):
39735 """
39736 Given a lvm id in one of the forms:
39737
39738 /dev/sda
39739 some_vg
39740 some_vg/some_lv
39741 Oe1rPX-Pf0W-15E5-n41N-ZmtF-jXS0-Osg8fn
39742
39743 return the object path in O(1) time.
39744
39745 :param key: The lookup value
39746 :return: Return the object path. If object not found you will get '/'
39747 """
39748 p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
39749 if p:
39750 return p
39751 return '/'
39752
39753 @staticmethod
39754 def _use_lvm_shell(yes_no):
39755 return dbus.Boolean(cmdhandler.set_execution(yes_no))
39756
39757 @dbus.service.method(
39758 dbus_interface=MANAGER_INTERFACE,
39759 in_signature='b', out_signature='b',
39760 async_callbacks=('cb', 'cbe'))
39761 def UseLvmShell(self, yes_no, cb, cbe):
39762 """
39763 Allow the client to enable/disable lvm shell, used for testing
39764 :param yes_no:
39765 :param cb: dbus python call back parameter, not client visible
39766 :param cbe: dbus python error call back parameter, not client visible
39767 :return: Nothing
39768 """
39769 r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False)
39770 cfg.worker_q.put(r)
39771
39772 @dbus.service.method(
39773 dbus_interface=MANAGER_INTERFACE,
39774 in_signature='s', out_signature='i')
39775 def ExternalEvent(self, command):
39776
39777 # If a user didn't explicitly specify udev, we will turn it off now.
39778 if not cfg.args.use_udev:
39779 if udevwatch.remove():
39780 utils.log_debug("ExternalEvent received, disabling "
39781 "udev monitoring")
39782 # We are dependent on external events now to stay current!
39783 cfg.ee = True
39784 utils.log_debug("ExternalEvent %s" % command)
39785 cfg.event()
39786 return dbus.Int32(0)
39787
39788 @staticmethod
39789 def _pv_scan(activate, cache, device_path, major_minor, scan_options):
39790
39791 rc, out, err = cmdhandler.pv_scan(
39792 activate, cache, device_path,
39793 major_minor, scan_options)
39794
39795 if rc == 0:
39796 # This could potentially change the state quite a bit, so lets
39797 # update everything to be safe
39798 cfg.load()
39799 return '/'
39800 else:
39801 raise dbus.exceptions.DBusException(
39802 MANAGER_INTERFACE,
39803 'Exit code %s, stderr = %s' % (str(rc), err))
39804
39805 @dbus.service.method(
39806 dbus_interface=MANAGER_INTERFACE,
39807 in_signature='bbasa(ii)ia{sv}',
39808 out_signature='o',
39809 async_callbacks=('cb', 'cbe'))
39810 def PvScan(self, activate, cache, device_paths, major_minors,
39811 tmo, scan_options, cb, cbe):
39812 """
39813 Scan all supported LVM block devices in the system for physical volumes
39814 NOTE: major_minors & device_paths only usable when cache == True
39815 :param activate: If True, activate any newly found LVs
39816 :param cache: If True, update lvmetad
39817 :param device_paths: Array of device paths or empty
39818 :param major_minors: Array of structures (major,minor)
39819 :param tmo: Timeout for operation
39820 :param scan_options: Additional options to pvscan
39821 :param cb: Not visible in API (used for async. callback)
39822 :param cbe: Not visible in API (used for async. error callback)
39823 :return: '/' if operation done, else job path
39824 """
39825 for d in device_paths:
39826 utils.validate_device_path(MANAGER_INTERFACE, d)
39827
39828 r = RequestEntry(
39829 tmo, Manager._pv_scan,
39830 (activate, cache, device_paths, major_minors,
39831 scan_options), cb, cbe, False)
39832 cfg.worker_q.put(r)
39833
39834 @property
39835 def lvm_id(self):
39836 """
39837 Intended to be overridden by classes that inherit
39838 """
39839 return str(id(self))
39840
39841 @property
39842 def Uuid(self):
39843 """
39844 Intended to be overridden by classes that inherit
39845 """
39846 import uuid
39847 return uuid.uuid1()
39848\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/utils.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000034245\013062740170\0022037\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
39849#
39850# This copyrighted material is made available to anyone wishing to use,
39851# modify, copy, or redistribute it subject to the terms and conditions
39852# of the GNU General Public License v.2.
39853#
39854# You should have received a copy of the GNU General Public License
39855# along with this program. If not, see <http://www.gnu.org/licenses/>.
39856
39857import xml.etree.ElementTree as Et
39858import sys
39859import inspect
39860import ctypes
39861import os
39862import string
39863import datetime
39864
39865import dbus
39866from lvmdbusd import cfg
39867# noinspection PyUnresolvedReferences
39868from gi.repository import GLib
39869import threading
39870
39871
39872STDOUT_TTY = os.isatty(sys.stdout.fileno())
39873
39874
39875def rtype(dbus_type):
39876 """
39877 Decorator making sure that the decorated function returns a value of
39878 specified type.
39879 :param dbus_type: The specific dbus type to return value as
39880 """
39881
39882 def decorator(fn):
39883 def decorated(*args, **kwargs):
39884 return dbus_type(fn(*args, **kwargs))
39885
39886 return decorated
39887
39888 return decorator
39889
39890
39891# Field is expected to be a number, handle the corner cases when parsing
39892@rtype(dbus.UInt64)
39893def n(v):
39894 if not v:
39895 return 0
39896 return int(float(v))
39897
39898
39899@rtype(dbus.UInt32)
39900def n32(v):
39901 if not v:
39902 return 0
39903 return int(float(v))
39904
39905
39906# noinspection PyProtectedMember
39907def init_class_from_arguments(obj_instance):
39908 for k, v in list(sys._getframe(1).f_locals.items()):
39909 if k != 'self':
39910 nt = k
39911
39912 # If the current attribute has a value, but the incoming does
39913 # not, don't overwrite it. Otherwise the default values on the
39914 # property decorator don't work as expected.
39915 cur = getattr(obj_instance, nt, v)
39916
39917 # print 'Init class %s = %s' % (nt, str(v))
39918 if not (cur and len(str(cur)) and (v is None or len(str(v))) == 0):
39919 setattr(obj_instance, nt, v)
39920
39921
39922def get_properties(f):
39923 """
39924 Walks through an object instance or it's parent class(es) and determines
39925 which attributes are properties and if they were created to be used for
39926 dbus.
39927 :param f: Object to inspect
39928 :return: A dictionary of tuples with each tuple being:
39929 0 = An array of dicts with the keys being: p_t, p_name,
39930 p_access(type, name, access)
39931 1 = Hash of property names and current value
39932 """
39933 interfaces = dict()
39934
39935 for c in inspect.getmro(f.__class__):
39936
39937 h = vars(c)
39938 for p, value in h.items():
39939 if isinstance(value, property):
39940 # We found a property, see if it has a metadata type
39941 key = attribute_type_name(p)
39942 if key in h:
39943 interface = h[key][1]
39944
39945 if interface not in interfaces:
39946 interfaces[interface] = ([], {})
39947
39948 access = ''
39949 if getattr(f.__class__, p).fget:
39950 access += 'read'
39951 if getattr(f.__class__, p).fset:
39952 access += 'write'
39953
39954 interfaces[interface][0].append(
39955 dict(
39956 p_t=getattr(f, key)[0],
39957 p_name=p,
39958 p_access=access))
39959
39960 interfaces[interface][1][p] = getattr(f, p)
39961
39962 return interfaces
39963
39964
39965def get_object_property_diff(o_prop, n_prop):
39966 """
39967 Walk through each object properties and report what has changed and with
39968 the new values
39969 :param o_prop: Old keys/values
39970 :param n_prop: New keys/values
39971 :return: hash of properties that have changed and their new value
39972 """
39973 rc = {}
39974
39975 for intf_k, intf_v in o_prop.items():
39976 for k, v in list(intf_v[1].items()):
39977 # print('Comparing %s:%s to %s:%s' %
39978 # (k, o_prop[intf_k][1][k], k, str(n_prop[intf_k][1][k])))
39979 if o_prop[intf_k][1][k] != n_prop[intf_k][1][k]:
39980 new_value = n_prop[intf_k][1][k]
39981
39982 if intf_k not in rc:
39983 rc[intf_k] = dict()
39984
39985 rc[intf_k][k] = new_value
39986 return rc
39987
39988
39989def add_properties(xml, interface, props):
39990 """
39991 Given xml that describes the interface, add property values to the XML
39992 for the specified interface.
39993 :param xml: XML to edit
39994 :param interface: Interface to add the properties too
39995 :param props: Output from get_properties
39996 :return: updated XML string
39997 """
39998 if props:
39999 root = Et.fromstring(xml)
40000 interface_element = None
40001
40002 # Check to see if interface is present
40003 for c in root:
40004 if c.attrib['name'] == interface:
40005 interface_element = c
40006 break
40007
40008 # Interface is not present, lets create it so we have something to
40009 # attach the properties too
40010 if interface_element is None:
40011 interface_element = Et.Element("interface", name=interface)
40012 root.append(interface_element)
40013
40014 # Add the properties
40015 for p in props:
40016 temp = '<property type="%s" name="%s" access="%s"/>\n' % \
40017 (p['p_t'], p['p_name'], p['p_access'])
40018 interface_element.append(Et.fromstring(temp))
40019
40020 return Et.tostring(root, encoding='utf8')
40021 return xml
40022
40023
40024def attribute_type_name(name):
40025 """
40026 Given the property name, return string of the attribute type
40027 :param name:
40028 :return:
40029 """
40030 return "_%s_meta" % name
40031
40032
40033_type_map = dict(
40034 s=dbus.String,
40035 o=dbus.ObjectPath,
40036 t=dbus.UInt64,
40037 x=dbus.Int64,
40038 u=dbus.UInt32,
40039 i=dbus.Int32,
40040 n=dbus.Int16,
40041 q=dbus.UInt16,
40042 d=dbus.Double,
40043 y=dbus.Byte,
40044 b=dbus.Boolean)
40045
40046
40047def _pass_through(v):
40048 """
40049 If we have something which is not a simple type we return the original
40050 value un-wrapped.
40051 :param v:
40052 :return:
40053 """
40054 return v
40055
40056
40057def _dbus_type(t, value):
40058 return _type_map.get(t, _pass_through)(value)
40059
40060
40061def dbus_property(interface_name, name, dbus_type, doc=None):
40062 """
40063 Creates the get/set properties for the given name. It assumes that the
40064 actual attribute is '_' + name and the attribute metadata is stuffed in
40065 _name_type.
40066
40067 There is probably a better way todo this.
40068 :param interface_name: Dbus interface this property is associated with
40069 :param name: Name of property
40070 :param dbus_type: dbus string type eg. s,t,i,x
40071 :param doc: Python __doc__ for the property
40072 :return:
40073 """
40074 attribute_name = '_' + name
40075
40076 def getter(self):
40077 t = getattr(self, attribute_name + '_meta')[0]
40078 return _dbus_type(t, getattr(self.state, attribute_name[1:]))
40079
40080 prop = property(getter, None, None, doc)
40081
40082 def decorator(cls):
40083 setattr(cls, attribute_name + '_meta', (dbus_type, interface_name))
40084 setattr(cls, name, prop)
40085 return cls
40086
40087 return decorator
40088
40089
40090def parse_tags(tags):
40091 if len(tags):
40092 if ',' in tags:
40093 return tags.split(',')
40094 return dbus.Array(sorted([tags]), signature='s')
40095 return dbus.Array([], signature='s')
40096
40097
40098def _common_log(msg, *attributes):
40099 cfg.stdout_lock.acquire()
40100 tid = ctypes.CDLL('libc.so.6').syscall(186)
40101
40102 if STDOUT_TTY:
40103 msg = "%s: %d:%d - %s" % \
40104 (datetime.datetime.now().strftime("%b %d %H:%M:%S.%f"),
40105 os.getpid(), tid, msg)
40106
40107 else:
40108 msg = "%d:%d - %s" % (os.getpid(), tid, msg)
40109
40110 if STDOUT_TTY and attributes:
40111 print(color(msg, *attributes))
40112 else:
40113 print(msg)
40114
40115 cfg.stdout_lock.release()
40116 sys.stdout.flush()
40117
40118
40119# Serializes access to stdout to prevent interleaved output
40120# @param msg Message to output to stdout
40121# @return None
40122def log_debug(msg, *attributes):
40123 if cfg.args and cfg.args.debug:
40124 _common_log(msg, *attributes)
40125
40126
40127def log_error(msg, *attributes):
40128 _common_log(msg, *attributes)
40129
40130
40131# noinspection PyUnusedLocal
40132def handler(signum, frame):
40133 cfg.run.value = 0
40134 log_debug('Signal handler called with signal %d' % signum)
40135 if cfg.loop is not None:
40136 cfg.loop.quit()
40137
40138
40139def pv_obj_path_generate():
40140 return cfg.PV_OBJ_PATH + "/%d" % next(cfg.pv_id)
40141
40142
40143def vg_obj_path_generate():
40144 return cfg.VG_OBJ_PATH + "/%d" % next(cfg.vg_id)
40145
40146
40147def lv_object_path_method(name, meta):
40148 if name[0] == '[':
40149 return _hidden_lv_obj_path_generate
40150 elif meta[0][0] == 't':
40151 return _thin_pool_obj_path_generate
40152 elif meta[0][0] == 'C' and 'pool' in meta[1]:
40153 return _cache_pool_obj_path_generate
40154
40155 return _lv_obj_path_generate
40156
40157
40158# Note: None of the individual LV path generate functions should be called
40159# directly, they should only be dispatched through lv_object_path_method
40160
40161def _lv_obj_path_generate():
40162 return cfg.LV_OBJ_PATH + "/%d" % next(cfg.lv_id)
40163
40164
40165def _thin_pool_obj_path_generate():
40166 return cfg.THIN_POOL_PATH + "/%d" % next(cfg.thin_id)
40167
40168
40169def _cache_pool_obj_path_generate():
40170 return cfg.CACHE_POOL_PATH + "/%d" % next(cfg.cache_pool_id)
40171
40172
40173def _hidden_lv_obj_path_generate():
40174 return cfg.HIDDEN_LV_PATH + "/%d" % next(cfg.hidden_lv)
40175
40176
40177def job_obj_path_generate():
40178 return cfg.JOB_OBJ_PATH + "/%d" % next(cfg.job_id)
40179
40180
40181def color(text, *user_styles):
40182 styles = {
40183 # styles
40184 'reset': '\033[0m',
40185 'bold': '\033[01m',
40186 'disabled': '\033[02m',
40187 'underline': '\033[04m',
40188 'reverse': '\033[07m',
40189 'strike_through': '\033[09m',
40190 'invisible': '\033[08m',
40191 # text colors
40192 'fg_black': '\033[30m',
40193 'fg_red': '\033[31m',
40194 'fg_green': '\033[32m',
40195 'fg_orange': '\033[33m',
40196 'fg_blue': '\033[34m',
40197 'fg_purple': '\033[35m',
40198 'fg_cyan': '\033[36m',
40199 'fg_light_grey': '\033[37m',
40200 'fg_dark_grey': '\033[90m',
40201 'fg_light_red': '\033[91m',
40202 'fg_light_green': '\033[92m',
40203 'fg_yellow': '\033[93m',
40204 'fg_light_blue': '\033[94m',
40205 'fg_pink': '\033[95m',
40206 'fg_light_cyan': '\033[96m',
40207 # background colors
40208 'bg_black': '\033[40m',
40209 'bg_red': '\033[41m',
40210 'bg_green': '\033[42m',
40211 'bg_orange': '\033[43m',
40212 'bg_blue': '\033[44m',
40213 'bg_purple': '\033[45m',
40214 'bg_cyan': '\033[46m',
40215 'bg_light_grey': '\033[47m'
40216 }
40217
40218 color_text = ''
40219 for style in user_styles:
40220 try:
40221 color_text += styles[style]
40222 except KeyError:
40223 return 'def color: parameter {} does not exist'.format(style)
40224 color_text += text
40225 return '\033[0m{0}\033[0m'.format(color_text)
40226
40227
40228def pv_range_append(cmd, device, start, end):
40229 if (start, end) == (0, 0):
40230 cmd.append(device)
40231 else:
40232 if start != 0 and end == 0:
40233 cmd.append("%s:%d-" % (device, start))
40234 else:
40235 cmd.append(
40236 "%s:%d-%d" %
40237 (device, start, end))
40238
40239
40240def pv_dest_ranges(cmd, pv_dest_range_list):
40241 if len(pv_dest_range_list):
40242 for i in pv_dest_range_list:
40243 pv_range_append(cmd, *i)
40244
40245
40246def round_size(size_bytes):
40247 bs = 512
40248 remainder = size_bytes % bs
40249 if not remainder:
40250 return size_bytes
40251 return size_bytes + bs - remainder
40252
40253
40254_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
40255_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
40256
40257_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
40258_ALLOWABLE_VG_LV_CH_SET = set(_ALLOWABLE_VG_LV_CH)
40259_LV_NAME_RESERVED = ("_cdata", "_cmeta", "_corig", "_mimage", "_mlog",
40260 "_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin")
40261
40262# Tags can have the characters, based on the code
40263# a-zA-Z0-9._-+/=!:&#
40264_ALLOWABLE_TAG_CH = string.ascii_letters + string.digits + "._-+/=!:&#"
40265_ALLOWABLE_TAG_CH_SET = set(_ALLOWABLE_TAG_CH)
40266
40267
40268def _allowable_tag(tag_name):
40269 # LVM should impose a length restriction
40270 return set(tag_name) <= _ALLOWABLE_TAG_CH_SET
40271
40272
40273def _allowable_vg_name(vg_name):
40274 if vg_name is None:
40275 raise ValueError("VG name is None or empty")
40276
40277 vg_len = len(vg_name)
40278 if vg_len == 0 or vg_len > 127:
40279 raise ValueError("VG name (%s) length (%d) not in the domain 1..127" %
40280 (vg_name, vg_len))
40281
40282 if not set(vg_name) <= _ALLOWABLE_VG_LV_CH_SET:
40283 raise ValueError("VG name (%s) contains invalid character, "
40284 "allowable set(%s)" % (vg_name, _ALLOWABLE_VG_LV_CH))
40285
40286 if vg_name == "." or vg_name == "..":
40287 raise ValueError('VG name (%s) cannot be "." or ".."' % (vg_name))
40288
40289
40290def _allowable_lv_name(vg_name, lv_name):
40291
40292 if lv_name is None:
40293 raise ValueError("LV name is None or empty")
40294
40295 lv_len = len(lv_name)
40296
40297 # This length is derived from empirical testing
40298 if lv_len == 0 or (len(vg_name) + lv_len) > 125:
40299 raise ValueError("LV name (%s) length (%d) + VG name length "
40300 "not in the domain 1..125" % (lv_name, lv_len))
40301
40302 if not set(lv_name) <= _ALLOWABLE_VG_LV_CH_SET:
40303 raise ValueError("LV name (%s) contains invalid character, "
40304 "allowable (%s)" % (lv_name, _ALLOWABLE_VG_LV_CH))
40305
40306 if any(x in lv_name for x in _LV_NAME_RESERVED):
40307 raise ValueError("LV name (%s) contains a reserved word, "
40308 "reserved set(%s)" % (lv_name, str(_LV_NAME_RESERVED)))
40309
40310 if lv_name.startswith("snapshot") or lv_name.startswith("pvmove"):
40311 raise ValueError("LV name (%s) starts with a reserved word, "
40312 "reserved set(%s)" % (lv_name, str(["snapshot", "pvmove"])))
40313
40314 if lv_name[0] == '-':
40315 raise ValueError("LV name (%s) cannot start with a '-' "
40316 "character" % lv_name)
40317
40318
40319def validate_device_path(interface, device):
40320 if not set(device) <= _ALLOWABLE_CH_SET:
40321 raise dbus.exceptions.DBusException(
40322 interface, 'Device path (%s) has invalid characters, '
40323 'allowable (%s)' % (device, _ALLOWABLE_CH))
40324
40325
40326def validate_vg_name(interface, vg_name):
40327 try:
40328 _allowable_vg_name(vg_name)
40329 except ValueError as ve:
40330 raise dbus.exceptions.DBusException(
40331 interface, str(ve))
40332
40333
40334def validate_lv_name(interface, vg_name, lv_name):
40335 try:
40336 _allowable_lv_name(vg_name, lv_name)
40337 except ValueError as ve:
40338 raise dbus.exceptions.DBusException(
40339 interface, str(ve))
40340
40341
40342def validate_tag(interface, tag):
40343 if not _allowable_tag(tag):
40344 raise dbus.exceptions.DBusException(
40345 interface, 'tag (%s) contains invalid character, allowable set(%s)'
40346 % (tag, _ALLOWABLE_TAG_CH))
40347
40348
40349# The methods below which start with mt_* are used to execute the desired code
40350# on the the main thread of execution to alleviate any issues the dbus-python
40351# library with regards to multi-threaded access. Essentially, we are trying to
40352# ensure all dbus library interaction is done from the same thread!
40353
40354
40355def _async_result(call_back, results):
40356 log_debug('Results = %s' % str(results))
40357 call_back(results)
40358
40359
40360# Return result in main thread
40361def mt_async_result(call_back, results):
40362 GLib.idle_add(_async_result, call_back, results)
40363
40364
40365# Take the supplied function and run it on the main thread and not wait for
40366# a result!
40367def mt_run_no_wait(function, param):
40368 GLib.idle_add(function, param)
40369
40370# Run the supplied function and arguments on the main thread and wait for them
40371# to complete while allowing the ability to get the return value too.
40372#
40373# Example:
40374# result = MThreadRunner(foo, arg1, arg2).done()
40375#
40376class MThreadRunner(object):
40377
40378 @staticmethod
40379 def runner(obj):
40380 # noinspection PyProtectedMember
40381 obj._run()
40382 with obj.cond:
40383 obj.function_complete = True
40384 obj.cond.notify_all()
40385
40386 def __init__(self, function, *args):
40387 self.f = function
40388 self.rc = None
40389 self.args = args
40390 self.function_complete = False
40391 self.cond = threading.Condition(threading.Lock())
40392
40393 def done(self):
40394 GLib.idle_add(MThreadRunner.runner, self)
40395 with self.cond:
40396 if not self.function_complete:
40397 self.cond.wait()
40398 return self.rc
40399
40400 def _run(self):
40401 if len(self.args):
40402 self.rc = self.f(*self.args)
40403 else:
40404 self.rc = self.f()
40405
40406
40407def _remove_objects(dbus_objects_rm):
40408 for o in dbus_objects_rm:
40409 cfg.om.remove_object(o, emit_signal=True)
40410
40411
40412# Remove dbus objects from main thread
40413def mt_remove_dbus_objects(objs):
40414 MThreadRunner(_remove_objects, objs).done()
40415\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/__init__.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000634\013062740170\0022431\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40416#
40417# This copyrighted material is made available to anyone wishing to use,
40418# modify, copy, or redistribute it subject to the terms and conditions
40419# of the GNU General Public License v.2.
40420#
40421# You should have received a copy of the GNU General Public License
40422# along with this program. If not, see <http://www.gnu.org/licenses/>.
40423
40424from .main import main
40425\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/fetch.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010265\013062740170\0021764\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40426#
40427# This copyrighted material is made available to anyone wishing to use,
40428# modify, copy, or redistribute it subject to the terms and conditions
40429# of the GNU General Public License v.2.
40430#
40431# You should have received a copy of the GNU General Public License
40432# along with this program. If not, see <http://www.gnu.org/licenses/>.
40433
40434from .pv import load_pvs
40435from .vg import load_vgs
40436from .lv import load_lvs
40437from . import cfg
40438from .utils import MThreadRunner, log_debug, log_error
40439import threading
40440import queue
40441import traceback
40442
40443
40444def _main_thread_load(refresh=True, emit_signal=True):
40445 num_total_changes = 0
40446
40447 num_total_changes += load_pvs(
40448 refresh=refresh,
40449 emit_signal=emit_signal,
40450 cache_refresh=False)[1]
40451 num_total_changes += load_vgs(
40452 refresh=refresh,
40453 emit_signal=emit_signal,
40454 cache_refresh=False)[1]
40455 num_total_changes += load_lvs(
40456 refresh=refresh,
40457 emit_signal=emit_signal,
40458 cache_refresh=False)[1]
40459
40460 return num_total_changes
40461
40462
40463def load(refresh=True, emit_signal=True, cache_refresh=True, log=True,
40464 need_main_thread=True):
40465 # Go through and load all the PVs, VGs and LVs
40466 if cache_refresh:
40467 cfg.db.refresh(log)
40468
40469 if need_main_thread:
40470 rc = MThreadRunner(_main_thread_load, refresh, emit_signal).done()
40471 else:
40472 rc = _main_thread_load(refresh, emit_signal)
40473
40474 return rc
40475
40476
40477# Even though lvm can handle multiple changes concurrently it really doesn't
40478# make sense to make a 1-1 fetch of data for each change of lvm because when
40479# we fetch the data once all previous changes are reflected.
40480class StateUpdate(object):
40481
40482 class UpdateRequest(object):
40483
40484 def __init__(self, refresh, emit_signal, cache_refresh, log,
40485 need_main_thread):
40486 self.is_done = False
40487 self.refresh = refresh
40488 self.emit_signal = emit_signal
40489 self.cache_refresh = cache_refresh
40490 self.log = log
40491 self.need_main_thread = need_main_thread
40492 self.result = None
40493 self.cond = threading.Condition(threading.Lock())
40494
40495 def done(self):
40496 with self.cond:
40497 if not self.is_done:
40498 self.cond.wait()
40499 return self.result
40500
40501 def set_result(self, result):
40502 with self.cond:
40503 self.result = result
40504 self.is_done = True
40505 self.cond.notify_all()
40506
40507 @staticmethod
40508 def update_thread(obj):
40509 while cfg.run.value != 0:
40510 # noinspection PyBroadException
40511 try:
40512 queued_requests = []
40513 refresh = True
40514 emit_signal = True
40515 cache_refresh = True
40516 log = True
40517 need_main_thread = True
40518
40519 with obj.lock:
40520 wait = not obj.deferred
40521 obj.deferred = False
40522
40523 if wait:
40524 queued_requests.append(obj.queue.get(True, 2))
40525
40526 # Ok we have one or the deferred queue has some,
40527 # check if any others
40528 try:
40529 while True:
40530 queued_requests.append(obj.queue.get(False))
40531
40532 except queue.Empty:
40533 pass
40534
40535 if len(queued_requests) > 1:
40536 log_debug("Processing %d updates!" % len(queued_requests),
40537 'bg_black', 'fg_light_green')
40538
40539 # We have what we can, run the update with the needed options
40540 for i in queued_requests:
40541 if not i.refresh:
40542 refresh = False
40543 if not i.emit_signal:
40544 emit_signal = False
40545 if not i.cache_refresh:
40546 cache_refresh = False
40547 if not i.log:
40548 log = False
40549 if not i.need_main_thread:
40550 need_main_thread = False
40551
40552 num_changes = load(refresh, emit_signal, cache_refresh, log,
40553 need_main_thread)
40554 # Update is done, let everyone know!
40555 for i in queued_requests:
40556 i.set_result(num_changes)
40557
40558 except queue.Empty:
40559 pass
40560 except Exception:
40561 st = traceback.format_exc()
40562 log_error("update_thread exception: \n%s" % st)
40563
40564 def __init__(self):
40565 self.lock = threading.RLock()
40566 self.queue = queue.Queue()
40567 self.deferred = False
40568
40569 # Do initial load
40570 load(refresh=False, emit_signal=False, need_main_thread=False)
40571
40572 self.thread = threading.Thread(target=StateUpdate.update_thread,
40573 args=(self,))
40574
40575 def load(self, refresh=True, emit_signal=True, cache_refresh=True,
40576 log=True, need_main_thread=True):
40577 # Place this request on the queue and wait for it to be completed
40578 req = StateUpdate.UpdateRequest(refresh, emit_signal, cache_refresh,
40579 log, need_main_thread)
40580 self.queue.put(req)
40581 return req.done()
40582
40583 def event(self):
40584 with self.lock:
40585 self.deferred = True
40586\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/path.py.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000637\013062740170\0022236\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40587#
40588# This copyrighted material is made available to anyone wishing to use,
40589# modify, copy, or redistribute it subject to the terms and conditions
40590# of the GNU General Public License v.2.
40591#
40592# You should have received a copy of the GNU General Public License
40593# along with this program. If not, see <http://www.gnu.org/licenses/>.
40594
40595LVM_BINARY = "@LVM_PATH@"
40596\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/loader.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005155\013062740170\0022143\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40597#
40598# This copyrighted material is made available to anyone wishing to use,
40599# modify, copy, or redistribute it subject to the terms and conditions
40600# of the GNU General Public License v.2.
40601#
40602# You should have received a copy of the GNU General Public License
40603# along with this program. If not, see <http://www.gnu.org/licenses/>.
40604
40605from . import cfg
40606
40607
40608def _compare_construction(o_state, new_state):
40609 # We need to check to see if the objects would get constructed
40610 # the same
40611 existing_ctor, existing_path = o_state.creation_signature()
40612 new_ctor, new_path = new_state.creation_signature()
40613
40614 # print("%s == %s and %s == %s" % (str(existing_ctor), str(new_ctor),
40615 # str(existing_path), str(new_path)))
40616
40617 return ((existing_ctor == new_ctor) and (existing_path == new_path))
40618
40619
40620def common(retrieve, o_type, search_keys,
40621 object_path, refresh, emit_signal, cache_refresh):
40622 num_changes = 0
40623 existing_paths = []
40624 rc = []
40625
40626 if search_keys:
40627 assert isinstance(search_keys, list)
40628
40629 if cache_refresh:
40630 cfg.db.refresh()
40631
40632 objects = retrieve(search_keys, cache_refresh=False)
40633
40634 # If we are doing a refresh we need to know what we have in memory, what's
40635 # in lvm and add those that are new and remove those that are gone!
40636 if refresh:
40637 existing_paths = cfg.om.object_paths_by_type(o_type)
40638
40639 for o in objects:
40640 # Assume we need to add this one to dbus, unless we are refreshing
40641 # and it's already present
40642 return_object = True
40643
40644 if refresh:
40645 # We are refreshing all the PVs from LVM, if this one exists
40646 # we need to refresh our state.
40647 dbus_object = cfg.om.get_object_by_uuid_lvm_id(*o.identifiers())
40648
40649 if dbus_object:
40650 del existing_paths[dbus_object.dbus_object_path()]
40651
40652 # If the old object state and new object state wouldn't be
40653 # created with the same path and same object constructor we
40654 # need to remove the old object and construct the new one
40655 # instead!
40656 if not _compare_construction(dbus_object.state, o):
40657 # Remove existing and construct new one
40658 cfg.om.remove_object(dbus_object, emit_signal)
40659 dbus_object = o.create_dbus_object(None)
40660 cfg.om.register_object(dbus_object, emit_signal)
40661 num_changes += 1
40662 else:
40663 num_changes += dbus_object.refresh(object_state=o)
40664 return_object = False
40665
40666 if return_object:
40667 dbus_object = o.create_dbus_object(object_path)
40668 cfg.om.register_object(dbus_object, emit_signal)
40669 rc.append(dbus_object)
40670
40671 object_path = None
40672
40673 if refresh:
40674 for k in list(existing_paths.keys()):
40675 cfg.om.remove_object(cfg.om.get_object_by_path(k), True)
40676 num_changes += 1
40677
40678 num_changes += len(rc)
40679
40680 return rc, num_changes
40681\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/automatedproperties.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013167\013062740170\0024777\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40682#
40683# This copyrighted material is made available to anyone wishing to use,
40684# modify, copy, or redistribute it subject to the terms and conditions
40685# of the GNU General Public License v.2.
40686#
40687# You should have received a copy of the GNU General Public License
40688# along with this program. If not, see <http://www.gnu.org/licenses/>.
40689
40690import dbus
40691import dbus.service
40692from . import cfg
40693from .utils import get_properties, add_properties, get_object_property_diff, \
40694 log_debug
40695from .state import State
40696
40697
40698# noinspection PyPep8Naming,PyUnresolvedReferences
40699class AutomatedProperties(dbus.service.Object):
40700 """
40701 This class implements the needed interfaces for:
40702 org.freedesktop.DBus.Properties
40703
40704 Other classes inherit from it to get the same behavior
40705 """
40706
40707 def __init__(self, object_path, search_method=None):
40708 dbus.service.Object.__init__(self, cfg.bus, object_path)
40709 self._ap_interface = []
40710 self._ap_o_path = object_path
40711 self._ap_search_method = search_method
40712 self.state = None
40713
40714 def dbus_object_path(self):
40715 return self._ap_o_path
40716
40717 def emit_data(self):
40718 props = {}
40719
40720 for i in self.interface():
40721 props[i] = self.GetAll(i)
40722
40723 return self._ap_o_path, props
40724
40725 def set_interface(self, interface):
40726 """
40727 With inheritance we can't easily tell what interfaces a class provides
40728 so we will have each class that implements an interface tell the
40729 base AutomatedProperties what it is they do provide. This is kind of
40730 clunky and perhaps we can figure out a better way to do this later.
40731 :param interface: An interface the object supports
40732 :return:
40733 """
40734 if interface not in self._ap_interface:
40735 self._ap_interface.append(interface)
40736
40737 # noinspection PyUnusedLocal
40738 def interface(self, all_interfaces=False):
40739 if all_interfaces:
40740 cpy = list(self._ap_interface)
40741 cpy.extend(
40742 ["org.freedesktop.DBus.Introspectable",
40743 "org.freedesktop.DBus.Properties"])
40744 return cpy
40745
40746 return self._ap_interface
40747
40748 # Properties
40749 # noinspection PyUnusedLocal
40750 @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
40751 in_signature='ss', out_signature='v')
40752 def Get(self, interface_name, property_name):
40753 value = getattr(self, property_name)
40754 # Note: If we get an exception in this handler we won't know about it,
40755 # only the side effect of no returned value!
40756 log_debug('Get (%s), type (%s), value(%s)' %
40757 (property_name, str(type(value)), str(value)))
40758 return value
40759
40760 @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
40761 in_signature='s', out_signature='a{sv}')
40762 def GetAll(self, interface_name):
40763 if interface_name in self.interface(True):
40764 # Using introspection, lets build this dynamically
40765 properties = get_properties(self)
40766 if interface_name in properties:
40767 return properties[interface_name][1]
40768 return {}
40769 raise dbus.exceptions.DBusException(
40770 self._ap_interface,
40771 'The object %s does not implement the %s interface'
40772 % (self.__class__, interface_name))
40773
40774 @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
40775 in_signature='ssv')
40776 def Set(self, interface_name, property_name, new_value):
40777 setattr(self, property_name, new_value)
40778 self.PropertiesChanged(interface_name,
40779 {property_name: new_value}, [])
40780
40781 # As dbus-python does not support introspection for properties we will
40782 # get the autogenerated xml and then add our wanted properties to it.
40783 @dbus.service.method(dbus_interface=dbus.INTROSPECTABLE_IFACE,
40784 out_signature='s')
40785 def Introspect(self):
40786 r = dbus.service.Object.Introspect(self, self._ap_o_path, cfg.bus)
40787 # Look at the properties in the class
40788 props = get_properties(self)
40789
40790 for int_f, v in props.items():
40791 r = add_properties(r, int_f, v[0])
40792
40793 return r
40794
40795 @dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE,
40796 signature='sa{sv}as')
40797 def PropertiesChanged(self, interface_name, changed_properties,
40798 invalidated_properties):
40799 log_debug(('SIGNAL: PropertiesChanged(%s, %s, %s, %s)' %
40800 (str(self._ap_o_path), str(interface_name),
40801 str(changed_properties), str(invalidated_properties))))
40802
40803 def refresh(self, search_key=None, object_state=None):
40804 """
40805 Take the values (properties) of an object and update them with what
40806 lvm currently has. You can either fetch the new ones or supply the
40807 new state to be updated with
40808 :param search_key: The value to use to search for
40809 :param object_state: Use this as the new object state
40810 """
40811 num_changed = 0
40812
40813 # If we can't do a lookup, bail now, this happens if we blindly walk
40814 # through all dbus objects as some don't have a search method, like
40815 # 'Manager' object.
40816 if not self._ap_search_method:
40817 return
40818
40819 search = self.lvm_id
40820 if search_key:
40821 search = search_key
40822
40823 # Either we have the new object state or we need to go fetch it
40824 if object_state:
40825 new_state = object_state
40826 else:
40827 new_state = self._ap_search_method([search])[0]
40828 assert isinstance(new_state, State)
40829
40830 assert new_state
40831
40832 # When we refresh an object the object identifiers might have changed
40833 # because LVM allows the user to change them (name & uuid), thus if
40834 # they have changed we need to update the object manager so that
40835 # look-ups will happen correctly
40836 old_id = self.state.identifiers()
40837 new_id = new_state.identifiers()
40838 if old_id[0] != new_id[0] or old_id[1] != new_id[1]:
40839 cfg.om.lookup_update(self, new_id[0], new_id[1])
40840
40841 # Grab the properties values, then replace the state of the object
40842 # and retrieve the new values.
40843 o_prop = get_properties(self)
40844 self.state = new_state
40845 n_prop = get_properties(self)
40846
40847 changed = get_object_property_diff(o_prop, n_prop)
40848
40849 if changed:
40850 for int_f, v in changed.items():
40851 self.PropertiesChanged(int_f, v, [])
40852 num_changed += 1
40853 return num_changed
40854\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/main.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011540\013062740170\0021614\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
40855#
40856# This copyrighted material is made available to anyone wishing to use,
40857# modify, copy, or redistribute it subject to the terms and conditions
40858# of the GNU General Public License v.2.
40859#
40860# You should have received a copy of the GNU General Public License
40861# along with this program. If not, see <http://www.gnu.org/licenses/>.
40862
40863from . import cfg
40864from . import objectmanager
40865from . import utils
40866from .cfg import BUS_NAME, BASE_INTERFACE, BASE_OBJ_PATH, MANAGER_OBJ_PATH
40867import threading
40868from . import cmdhandler
40869import time
40870import signal
40871import dbus
40872import dbus.mainloop.glib
40873from . import lvmdb
40874# noinspection PyUnresolvedReferences
40875from gi.repository import GLib
40876from .fetch import StateUpdate
40877from .manager import Manager
40878import traceback
40879import queue
40880from . import udevwatch
40881from .utils import log_debug, log_error
40882import argparse
40883import os
40884import sys
40885from .cmdhandler import LvmFlightRecorder
40886
40887
40888class Lvm(objectmanager.ObjectManager):
40889 def __init__(self, object_path):
40890 super(Lvm, self).__init__(object_path, BASE_INTERFACE)
40891
40892
40893def process_request():
40894 while cfg.run.value != 0:
40895 # noinspection PyBroadException
40896 try:
40897 req = cfg.worker_q.get(True, 5)
40898 log_debug(
40899 "Running method: %s with args %s" %
40900 (str(req.method), str(req.arguments)))
40901 req.run_cmd()
40902 log_debug("Method complete ")
40903 except queue.Empty:
40904 pass
40905 except Exception:
40906 st = traceback.format_exc()
40907 utils.log_error("process_request exception: \n%s" % st)
40908
40909
40910def check_bb_size(value):
40911 v = int(value)
40912 if v < 0:
40913 raise argparse.ArgumentTypeError(
40914 "positive integers only ('%s' invalid)" % value)
40915 return v
40916
40917
40918def main():
40919 start = time.time()
40920 # Add simple command line handling
40921 parser = argparse.ArgumentParser()
40922 parser.add_argument(
40923 "--udev", action='store_true',
40924 help="Use udev for updating state",
40925 default=False,
40926 dest='use_udev')
40927 parser.add_argument(
40928 "--debug", action='store_true',
40929 help="Dump debug messages", default=False,
40930 dest='debug')
40931 parser.add_argument(
40932 "--nojson", action='store_false',
40933 help="Do not use LVM JSON output (disables lvmshell)", default=True,
40934 dest='use_json')
40935 parser.add_argument(
40936 "--lvmshell", action='store_true',
40937 help="Use the lvm shell, not fork & exec lvm",
40938 default=False,
40939 dest='use_lvm_shell')
40940 parser.add_argument(
40941 "--blackboxsize",
40942 help="Size of the black box flight recorder, 0 to disable",
40943 default=10,
40944 type=check_bb_size,
40945 dest='bb_size')
40946
40947 use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
40948
40949 # Ensure that we get consistent output for parsing stdout/stderr
40950 os.environ["LC_ALL"] = "C"
40951
40952 cfg.args = parser.parse_args()
40953
40954 # We create a flight recorder in cmdhandler too, but we replace it here
40955 # as the user may be specifying a different size. The default one in
40956 # cmdhandler is for when we are running other code with a different main.
40957 cfg.blackbox = LvmFlightRecorder(cfg.args.bb_size)
40958
40959 if cfg.args.use_lvm_shell and not cfg.args.use_json:
40960 log_error("You cannot specify --lvmshell and --nojson")
40961 sys.exit(1)
40962
40963 # List of threads that we start up
40964 thread_list = []
40965
40966 # Install signal handlers
40967 for s in [signal.SIGHUP, signal.SIGINT]:
40968 try:
40969 signal.signal(s, utils.handler)
40970 except RuntimeError:
40971 pass
40972
40973 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
40974 dbus.mainloop.glib.threads_init()
40975
40976 cmdhandler.set_execution(cfg.args.use_lvm_shell)
40977
40978 if use_session:
40979 cfg.bus = dbus.SessionBus()
40980 else:
40981 cfg.bus = dbus.SystemBus()
40982 # The base name variable needs to exist for things to work.
40983 # noinspection PyUnusedLocal
40984 base_name = dbus.service.BusName(BUS_NAME, cfg.bus)
40985 cfg.om = Lvm(BASE_OBJ_PATH)
40986 cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
40987
40988 cfg.db = lvmdb.DataStore(cfg.args.use_json)
40989
40990 # Using a thread to process requests, we cannot hang the dbus library
40991 # thread that is handling the dbus interface
40992 thread_list.append(threading.Thread(target=process_request))
40993
40994 # Have a single thread handling updating lvm and the dbus model so we
40995 # don't have multiple threads doing this as the same time
40996 updater = StateUpdate()
40997 thread_list.append(updater.thread)
40998
40999 cfg.load = updater.load
41000 cfg.event = updater.event
41001
41002 cfg.loop = GLib.MainLoop()
41003
41004 for thread in thread_list:
41005 thread.damon = True
41006 thread.start()
41007
41008 # Add udev watching
41009 if cfg.args.use_udev:
41010 log_debug('Utilizing udev to trigger updates')
41011
41012 # In all cases we are going to monitor for udev until we get an
41013 # ExternalEvent. In the case where we get an external event and the user
41014 # didn't specify --udev we will stop monitoring udev
41015 udevwatch.add()
41016
41017 end = time.time()
41018 log_debug(
41019 'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
41020 (end - start, cmdhandler.total_time, cmdhandler.total_count),
41021 'bg_black', 'fg_light_green')
41022
41023 try:
41024 if cfg.run.value != 0:
41025 cfg.loop.run()
41026 udevwatch.remove()
41027
41028 for thread in thread_list:
41029 thread.join()
41030 except KeyboardInterrupt:
41031 utils.handler(signal.SIGINT, None)
41032 return 0
41033\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/lv.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000064721\013062740170\0021322\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
41034#
41035# This copyrighted material is made available to anyone wishing to use,
41036# modify, copy, or redistribute it subject to the terms and conditions
41037# of the GNU General Public License v.2.
41038#
41039# You should have received a copy of the GNU General Public License
41040# along with this program. If not, see <http://www.gnu.org/licenses/>.
41041
41042from .automatedproperties import AutomatedProperties
41043
41044from . import utils
41045from .utils import vg_obj_path_generate
41046import dbus
41047from . import cmdhandler
41048from . import cfg
41049from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
41050 LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED
41051from .request import RequestEntry
41052from .utils import n, n32
41053from .loader import common
41054from .state import State
41055from . import background
41056from .utils import round_size, mt_remove_dbus_objects
41057from .job import JobState
41058
41059
41060# Try and build a key for a LV, so that we sort the LVs with least dependencies
41061# first. This may be error prone because of the flexibility LVM
41062# provides and what you can stack.
41063def get_key(i):
41064
41065 name = i['lv_name']
41066 parent = i['lv_parent']
41067 pool = i['pool_lv']
41068 a1 = ""
41069 a2 = ""
41070
41071 if name[0] == '[':
41072 a1 = '#'
41073
41074 # We have a parent
41075 if parent:
41076 # Check if parent is hidden
41077 if parent[0] == '[':
41078 a2 = '##'
41079 else:
41080 a2 = '#'
41081
41082 # If a LV has a pool, then it should be sorted/loaded after the pool
41083 # lv, unless it's a hidden too, then after other hidden, but before visible
41084 if pool:
41085 if pool[0] != '[':
41086 a2 += '~'
41087 else:
41088 a1 = '$' + a1
41089
41090 return "%s%s%s" % (a1, a2, name)
41091
41092
41093# noinspection PyUnusedLocal
41094def lvs_state_retrieve(selection, cache_refresh=True):
41095 rc = []
41096
41097 if cache_refresh:
41098 cfg.db.refresh()
41099
41100 # When building up the model, it's best to process LVs with the least
41101 # dependencies to those that are dependant upon other LVs. Otherwise, when
41102 # we are trying to gather information we could be in a position where we
41103 # don't have information available yet.
41104 lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
41105
41106 for l in lvs:
41107 rc.append(LvState(
41108 l['lv_uuid'], l['lv_name'],
41109 l['lv_path'], n(l['lv_size']),
41110 l['vg_name'],
41111 l['vg_uuid'], l['pool_lv_uuid'],
41112 l['pool_lv'], l['origin_uuid'], l['origin'],
41113 n32(l['data_percent']), l['lv_attr'],
41114 l['lv_tags'], l['lv_active'], l['data_lv'],
41115 l['metadata_lv'], l['segtype'], l['lv_role'],
41116 l['lv_layout'],
41117 n32(l['snap_percent']),
41118 n32(l['metadata_percent']),
41119 n32(l['copy_percent']),
41120 n32(l['sync_percent']),
41121 n(l['lv_metadata_size']),
41122 l['move_pv'],
41123 l['move_pv_uuid']))
41124 return rc
41125
41126
41127def load_lvs(lv_name=None, object_path=None, refresh=False, emit_signal=False,
41128 cache_refresh=True):
41129 # noinspection PyUnresolvedReferences
41130 return common(
41131 lvs_state_retrieve,
41132 (LvCommon, Lv, LvThinPool, LvSnapShot),
41133 lv_name, object_path, refresh, emit_signal, cache_refresh)
41134
41135
41136# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
41137class LvState(State):
41138 @staticmethod
41139 def _pv_devices(uuid):
41140 rc = []
41141 for pv in sorted(cfg.db.lv_contained_pv(uuid)):
41142 (pv_uuid, pv_name, pv_segs) = pv
41143 pv_obj = cfg.om.get_object_path_by_uuid_lvm_id(pv_uuid, pv_name)
41144
41145 segs_decorate = []
41146 for i in pv_segs:
41147 segs_decorate.append((dbus.UInt64(i[0]),
41148 dbus.UInt64(i[1]),
41149 dbus.String(i[2])))
41150
41151 rc.append((dbus.ObjectPath(pv_obj), segs_decorate))
41152
41153 return dbus.Array(rc, signature="(oa(tts))")
41154
41155 def vg_name_lookup(self):
41156 return cfg.om.get_object_by_path(self.Vg).Name
41157
41158 @property
41159 def lvm_id(self):
41160 return "%s/%s" % (self.vg_name_lookup(), self.Name)
41161
41162 def identifiers(self):
41163 return (self.Uuid, self.lvm_id)
41164
41165 def _get_hidden_lv(self):
41166 rc = dbus.Array([], "o")
41167
41168 vg_name = self.vg_name_lookup()
41169
41170 for l in cfg.db.hidden_lvs(self.Uuid):
41171 full_name = "%s/%s" % (vg_name, l[1])
41172 op = cfg.om.get_object_path_by_uuid_lvm_id(l[0], full_name)
41173 assert op
41174 rc.append(dbus.ObjectPath(op))
41175 return rc
41176
41177 def __init__(self, Uuid, Name, Path, SizeBytes,
41178 vg_name, vg_uuid, pool_lv_uuid, PoolLv,
41179 origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
41180 data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
41181 MetaDataPercent, CopyPercent, SyncPercent, MetaDataSizeBytes,
41182 move_pv, move_pv_uuid):
41183 utils.init_class_from_arguments(self)
41184
41185 # The segtypes is possibly an array with potentially dupes or a single
41186 # value
41187 self._segs = dbus.Array([], signature='s')
41188 if not isinstance(segtypes, list):
41189 self._segs.append(dbus.String(segtypes))
41190 else:
41191 self._segs.extend([dbus.String(x) for x in set(segtypes)])
41192
41193 self.Vg = cfg.om.get_object_path_by_uuid_lvm_id(
41194 vg_uuid, vg_name, vg_obj_path_generate)
41195
41196 self.Devices = LvState._pv_devices(self.Uuid)
41197
41198 if PoolLv:
41199 gen = utils.lv_object_path_method(Name, (Attr, layout, role))
41200
41201 self.PoolLv = cfg.om.get_object_path_by_uuid_lvm_id(
41202 pool_lv_uuid, '%s/%s' % (vg_name, PoolLv), gen)
41203 else:
41204 self.PoolLv = '/'
41205
41206 if OriginLv:
41207 self.OriginLv = \
41208 cfg.om.get_object_path_by_uuid_lvm_id(
41209 origin_uuid, '%s/%s' % (vg_name, OriginLv),
41210 vg_obj_path_generate)
41211 else:
41212 self.OriginLv = '/'
41213
41214 self.HiddenLvs = self._get_hidden_lv()
41215
41216 @property
41217 def SegType(self):
41218 return self._segs
41219
41220 def _object_path_create(self):
41221 return utils.lv_object_path_method(
41222 self.Name, (self.Attr, self.layout, self.role))
41223
41224 def _object_type_create(self):
41225 if self.Attr[0] == 't':
41226 return LvThinPool
41227 elif self.Attr[0] == 'C':
41228 if 'pool' in self.layout:
41229 return LvCachePool
41230 else:
41231 return LvCacheLv
41232 elif self.Name[0] == '[':
41233 return LvCommon
41234 elif self.OriginLv != '/':
41235 return LvSnapShot
41236 else:
41237 return Lv
41238
41239 def create_dbus_object(self, path):
41240 if not path:
41241 path = cfg.om.get_object_path_by_uuid_lvm_id(
41242 self.Uuid, self.lvm_id, self._object_path_create())
41243
41244 obj_ctor = self._object_type_create()
41245 return obj_ctor(path, self)
41246
41247 def creation_signature(self):
41248 klass = self._object_type_create()
41249 path_method = self._object_path_create()
41250 return (klass, path_method)
41251
41252
41253# noinspection PyPep8Naming
41254@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
41255@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
41256@utils.dbus_property(LV_COMMON_INTERFACE, 'Path', 's')
41257@utils.dbus_property(LV_COMMON_INTERFACE, 'SizeBytes', 't')
41258@utils.dbus_property(LV_COMMON_INTERFACE, 'SegType', 'as')
41259@utils.dbus_property(LV_COMMON_INTERFACE, 'Vg', 'o')
41260@utils.dbus_property(LV_COMMON_INTERFACE, 'OriginLv', 'o')
41261@utils.dbus_property(LV_COMMON_INTERFACE, 'PoolLv', 'o')
41262@utils.dbus_property(LV_COMMON_INTERFACE, 'Devices', "a(oa(tts))")
41263@utils.dbus_property(LV_COMMON_INTERFACE, 'HiddenLvs', "ao")
41264@utils.dbus_property(LV_COMMON_INTERFACE, 'Attr', 's')
41265@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
41266@utils.dbus_property(LV_COMMON_INTERFACE, 'SnapPercent', 'u')
41267@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
41268@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataPercent', 'u')
41269@utils.dbus_property(LV_COMMON_INTERFACE, 'CopyPercent', 'u')
41270@utils.dbus_property(LV_COMMON_INTERFACE, 'SyncPercent', 'u')
41271@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataSizeBytes', 't')
41272class LvCommon(AutomatedProperties):
41273 _Tags_meta = ("as", LV_COMMON_INTERFACE)
41274 _Roles_meta = ("as", LV_COMMON_INTERFACE)
41275 _IsThinVolume_meta = ("b", LV_COMMON_INTERFACE)
41276 _IsThinPool_meta = ("b", LV_COMMON_INTERFACE)
41277 _Active_meta = ("b", LV_COMMON_INTERFACE)
41278 _VolumeType_meta = ("(ss)", LV_COMMON_INTERFACE)
41279 _Permissions_meta = ("(ss)", LV_COMMON_INTERFACE)
41280 _AllocationPolicy_meta = ("(ss)", LV_COMMON_INTERFACE)
41281 _State_meta = ("(ss)", LV_COMMON_INTERFACE)
41282 _TargetType_meta = ("(ss)", LV_COMMON_INTERFACE)
41283 _Health_meta = ("(ss)", LV_COMMON_INTERFACE)
41284 _FixedMinor_meta = ('b', LV_COMMON_INTERFACE)
41285 _ZeroBlocks_meta = ('b', LV_COMMON_INTERFACE)
41286 _SkipActivation_meta = ('b', LV_COMMON_INTERFACE)
41287 _MovePv_meta = ('o', LV_COMMON_INTERFACE)
41288
41289 def _get_move_pv(self):
41290 path = None
41291
41292 # It's likely that the move_pv is empty
41293 if self.state.move_pv_uuid and self.state.move_pv:
41294 path = cfg.om.get_object_path_by_uuid_lvm_id(
41295 self.state.move_pv_uuid, self.state.move_pv)
41296 if not path:
41297 path = '/'
41298 return path
41299
41300 # noinspection PyUnusedLocal,PyPep8Naming
41301 def __init__(self, object_path, object_state):
41302 super(LvCommon, self).__init__(object_path, lvs_state_retrieve)
41303 self.set_interface(LV_COMMON_INTERFACE)
41304 self.state = object_state
41305 self._move_pv = self._get_move_pv()
41306
41307 @property
41308 def VolumeType(self):
41309 type_map = {'C': 'Cache', 'm': 'mirrored',
41310 'M': 'Mirrored without initial sync', 'o': 'origin',
41311 'O': 'Origin with merging snapshot', 'r': 'raid',
41312 'R': 'Raid without initial sync', 's': 'snapshot',
41313 'S': 'merging Snapshot', 'p': 'pvmove',
41314 'v': 'virtual', 'i': 'mirror or raid image',
41315 'I': 'mirror or raid Image out-of-sync',
41316 'l': 'mirror log device', 'c': 'under conversion',
41317 'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
41318 'e': 'raid or pool metadata or pool metadata spare',
41319 '-': 'Unspecified'}
41320 return dbus.Struct((self.state.Attr[0], type_map[self.state.Attr[0]]),
41321 signature="as")
41322
41323 @property
41324 def Permissions(self):
41325 type_map = {'w': 'writable', 'r': 'read-only',
41326 'R': 'Read-only activation of non-read-only volume',
41327 '-': 'Unspecified'}
41328 return dbus.Struct((self.state.Attr[1], type_map[self.state.Attr[1]]),
41329 signature="(ss)")
41330
41331 @property
41332 def AllocationPolicy(self):
41333 type_map = {'a': 'anywhere', 'A': 'anywhere locked',
41334 'c': 'contiguous', 'C': 'contiguous locked',
41335 'i': 'inherited', 'I': 'inherited locked',
41336 'l': 'cling', 'L': 'cling locked',
41337 'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
41338 return dbus.Struct((self.state.Attr[2], type_map[self.state.Attr[2]]),
41339 signature="(ss)")
41340
41341 @property
41342 def FixedMinor(self):
41343 return dbus.Boolean(self.state.Attr[3] == 'm')
41344
41345 @property
41346 def State(self):
41347 type_map = {'a': 'active', 's': 'suspended', 'I': 'Invalid snapshot',
41348 'S': 'invalid Suspended snapshot',
41349 'm': 'snapshot merge failed',
41350 'M': 'suspended snapshot (M)erge failed',
41351 'd': 'mapped device present without tables',
41352 'i': 'mapped device present with inactive table',
41353 'X': 'unknown', '-': 'Unspecified'}
41354 return dbus.Struct((self.state.Attr[4], type_map[self.state.Attr[4]]),
41355 signature="(ss)")
41356
41357 @property
41358 def TargetType(self):
41359 type_map = {'C': 'Cache', 'm': 'mirror', 'r': 'raid',
41360 's': 'snapshot', 't': 'thin', 'u': 'unknown',
41361 'v': 'virtual', '-': 'Unspecified'}
41362 return dbus.Struct((self.state.Attr[6], type_map[self.state.Attr[6]]),
41363 signature="(ss)")
41364
41365 @property
41366 def ZeroBlocks(self):
41367 return dbus.Boolean(self.state.Attr[7] == 'z')
41368
41369 @property
41370 def Health(self):
41371 type_map = {'p': 'partial', 'r': 'refresh',
41372 'm': 'mismatches', 'w': 'writemostly',
41373 'X': 'X unknown', '-': 'Unspecified'}
41374 return dbus.Struct((self.state.Attr[8], type_map[self.state.Attr[8]]),
41375 signature="(ss)")
41376
41377 @property
41378 def SkipActivation(self):
41379 return dbus.Boolean(self.state.Attr[9] == 'k')
41380
41381 def vg_name_lookup(self):
41382 return self.state.vg_name_lookup()
41383
41384 def lv_full_name(self):
41385 return "%s/%s" % (self.state.vg_name_lookup(), self.state.Name)
41386
41387 @property
41388 def identifiers(self):
41389 return self.state.identifiers
41390
41391 @property
41392 def Tags(self):
41393 return utils.parse_tags(self.state.Tags)
41394
41395 @property
41396 def Roles(self):
41397 return utils.parse_tags(self.state.role)
41398
41399 @property
41400 def lvm_id(self):
41401 return self.state.lvm_id
41402
41403 @property
41404 def IsThinVolume(self):
41405 return dbus.Boolean(self.state.Attr[0] == 'V')
41406
41407 @property
41408 def IsThinPool(self):
41409 return dbus.Boolean(self.state.Attr[0] == 't')
41410
41411 @property
41412 def Active(self):
41413 return dbus.Boolean(self.state.active == "active")
41414
41415 @property
41416 def MovePv(self):
41417 return dbus.ObjectPath(self._move_pv)
41418
41419
41420# noinspection PyPep8Naming
41421class Lv(LvCommon):
41422 def _fetch_hidden(self, name):
41423
41424 # The name is vg/name
41425 full_name = "%s/%s" % (self.vg_name_lookup(), name)
41426 return cfg.om.get_object_path_by_lvm_id(full_name)
41427
41428 def _get_data_meta(self):
41429
41430 # Get the data
41431 return (self._fetch_hidden(self.state.data_lv),
41432 self._fetch_hidden(self.state.metadata_lv))
41433
41434 # noinspection PyUnusedLocal,PyPep8Naming
41435 def __init__(self, object_path, object_state):
41436 super(Lv, self).__init__(object_path, object_state)
41437 self.set_interface(LV_INTERFACE)
41438 self.state = object_state
41439
41440 @staticmethod
41441 def _remove(lv_uuid, lv_name, remove_options):
41442 # Make sure we have a dbus object representing it
41443 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41444
41445 if dbo:
41446 # Remove the LV, if successful then remove from the model
41447 rc, out, err = cmdhandler.lv_remove(lv_name, remove_options)
41448
41449 if rc == 0:
41450 cfg.load()
41451 else:
41452 # Need to work on error handling, need consistent
41453 raise dbus.exceptions.DBusException(
41454 LV_INTERFACE,
41455 'Exit code %s, stderr = %s' % (str(rc), err))
41456 else:
41457 raise dbus.exceptions.DBusException(
41458 LV_INTERFACE,
41459 'LV with uuid %s and name %s not present!' %
41460 (lv_uuid, lv_name))
41461 return '/'
41462
41463 @dbus.service.method(
41464 dbus_interface=LV_INTERFACE,
41465 in_signature='ia{sv}',
41466 out_signature='o',
41467 async_callbacks=('cb', 'cbe'))
41468 def Remove(self, tmo, remove_options, cb, cbe):
41469 r = RequestEntry(
41470 tmo, Lv._remove,
41471 (self.Uuid, self.lvm_id, remove_options),
41472 cb, cbe, False)
41473 cfg.worker_q.put(r)
41474
41475 @staticmethod
41476 def _rename(lv_uuid, lv_name, new_name, rename_options):
41477 # Make sure we have a dbus object representing it
41478 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41479
41480 if dbo:
41481 # Rename the logical volume
41482 rc, out, err = cmdhandler.lv_rename(lv_name, new_name,
41483 rename_options)
41484 if rc == 0:
41485 cfg.load()
41486 else:
41487 # Need to work on error handling, need consistent
41488 raise dbus.exceptions.DBusException(
41489 LV_INTERFACE,
41490 'Exit code %s, stderr = %s' % (str(rc), err))
41491 else:
41492 raise dbus.exceptions.DBusException(
41493 LV_INTERFACE,
41494 'LV with uuid %s and name %s not present!' %
41495 (lv_uuid, lv_name))
41496 return '/'
41497
41498 @dbus.service.method(
41499 dbus_interface=LV_INTERFACE,
41500 in_signature='sia{sv}',
41501 out_signature='o',
41502 async_callbacks=('cb', 'cbe'))
41503 def Rename(self, name, tmo, rename_options, cb, cbe):
41504 utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)
41505
41506 r = RequestEntry(
41507 tmo, Lv._rename,
41508 (self.Uuid, self.lvm_id, name, rename_options),
41509 cb, cbe, False)
41510 cfg.worker_q.put(r)
41511
41512 @dbus.service.method(
41513 dbus_interface=LV_INTERFACE,
41514 in_signature='o(tt)a(ott)ia{sv}',
41515 out_signature='o',
41516 async_callbacks=('cb', 'cbe'))
41517 def Move(self, pv_src_obj, pv_source_range,
41518 pv_dests_and_ranges,
41519 tmo, move_options, cb, cbe):
41520
41521 job_state = JobState()
41522
41523 r = RequestEntry(
41524 tmo, background.move,
41525 (LV_INTERFACE, self.lvm_id, pv_src_obj, pv_source_range,
41526 pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
41527 job_state)
41528
41529 background.cmd_runner(r)
41530
41531 @staticmethod
41532 def _snap_shot(lv_uuid, lv_name, name, optional_size,
41533 snapshot_options):
41534 # Make sure we have a dbus object representing it
41535 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41536
41537 if dbo:
41538 # If you specify a size you get a 'thick' snapshot even if
41539 # it is a thin lv
41540 if not dbo.IsThinVolume:
41541 if optional_size == 0:
41542 space = dbo.SizeBytes / 80
41543 remainder = space % 512
41544 optional_size = space + 512 - remainder
41545
41546 rc, out, err = cmdhandler.vg_lv_snapshot(
41547 lv_name, snapshot_options, name, optional_size)
41548 if rc == 0:
41549 cfg.load()
41550 full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
41551 return cfg.om.get_object_path_by_lvm_id(full_name)
41552 else:
41553 raise dbus.exceptions.DBusException(
41554 LV_INTERFACE,
41555 'Exit code %s, stderr = %s' % (str(rc), err))
41556 else:
41557 raise dbus.exceptions.DBusException(
41558 LV_INTERFACE,
41559 'LV with uuid %s and name %s not present!' %
41560 (lv_uuid, lv_name))
41561
41562 @dbus.service.method(
41563 dbus_interface=LV_INTERFACE,
41564 in_signature='stia{sv}',
41565 out_signature='(oo)',
41566 async_callbacks=('cb', 'cbe'))
41567 def Snapshot(self, name, optional_size, tmo,
41568 snapshot_options, cb, cbe):
41569
41570 utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)
41571
41572 r = RequestEntry(
41573 tmo, Lv._snap_shot,
41574 (self.Uuid, self.lvm_id, name,
41575 optional_size, snapshot_options), cb, cbe)
41576 cfg.worker_q.put(r)
41577
41578 @staticmethod
41579 def _resize(lv_uuid, lv_name, new_size_bytes, pv_dests_and_ranges,
41580 resize_options):
41581 # Make sure we have a dbus object representing it
41582 pv_dests = []
41583 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41584
41585 if dbo:
41586 # If we have PVs, verify them
41587 if len(pv_dests_and_ranges):
41588 for pr in pv_dests_and_ranges:
41589 pv_dbus_obj = cfg.om.get_object_by_path(pr[0])
41590 if not pv_dbus_obj:
41591 raise dbus.exceptions.DBusException(
41592 LV_INTERFACE,
41593 'PV Destination (%s) not found' % pr[0])
41594
41595 pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
41596
41597 size_change = new_size_bytes - dbo.SizeBytes
41598
41599 rc, out, err = cmdhandler.lv_resize(dbo.lvm_id, size_change,
41600 pv_dests, resize_options)
41601
41602 if rc == 0:
41603 # Refresh what's changed
41604 cfg.load()
41605 return "/"
41606 else:
41607 raise dbus.exceptions.DBusException(
41608 LV_INTERFACE,
41609 'Exit code %s, stderr = %s' % (str(rc), err))
41610 else:
41611 raise dbus.exceptions.DBusException(
41612 LV_INTERFACE,
41613 'LV with uuid %s and name %s not present!' %
41614 (lv_uuid, lv_name))
41615
41616 @dbus.service.method(
41617 dbus_interface=LV_INTERFACE,
41618 in_signature='ta(ott)ia{sv}',
41619 out_signature='o',
41620 async_callbacks=('cb', 'cbe'))
41621 def Resize(self, new_size_bytes, pv_dests_and_ranges, tmo,
41622 resize_options, cb, cbe):
41623 """
41624 Resize a LV
41625 :param new_size_bytes: The requested final size in bytes
41626 :param pv_dests_and_ranges: An array of pv object paths and src &
41627 dst. segment ranges
41628 :param tmo: -1 to wait forever, 0 to return job immediately, else
41629 number of seconds to wait for operation to complete
41630 before getting a job
41631 :param resize_options: key/value hash of options
41632 :param cb: Used by framework not client facing API
41633 :param cbe: Used by framework not client facing API
41634 :return: '/' if complete, else job object path
41635 """
41636 r = RequestEntry(
41637 tmo, Lv._resize,
41638 (self.Uuid, self.lvm_id, round_size(new_size_bytes),
41639 pv_dests_and_ranges,
41640 resize_options), cb, cbe, return_tuple=False)
41641 cfg.worker_q.put(r)
41642
41643 @staticmethod
41644 def _lv_activate_deactivate(uuid, lv_name, activate, control_flags,
41645 options):
41646 # Make sure we have a dbus object representing it
41647 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)
41648
41649 if dbo:
41650 rc, out, err = cmdhandler.activate_deactivate(
41651 'lvchange', lv_name, activate, control_flags, options)
41652 if rc == 0:
41653 dbo.refresh()
41654 return '/'
41655 else:
41656 raise dbus.exceptions.DBusException(
41657 LV_INTERFACE,
41658 'Exit code %s, stderr = %s' % (str(rc), err))
41659 else:
41660 raise dbus.exceptions.DBusException(
41661 LV_INTERFACE,
41662 'LV with uuid %s and name %s not present!' %
41663 (uuid, lv_name))
41664
41665 @dbus.service.method(
41666 dbus_interface=LV_INTERFACE,
41667 in_signature='tia{sv}',
41668 out_signature='o',
41669 async_callbacks=('cb', 'cbe'))
41670 def Activate(self, control_flags, tmo, activate_options, cb, cbe):
41671 r = RequestEntry(
41672 tmo, Lv._lv_activate_deactivate,
41673 (self.state.Uuid, self.state.lvm_id, True,
41674 control_flags, activate_options),
41675 cb, cbe, return_tuple=False)
41676 cfg.worker_q.put(r)
41677
41678 # noinspection PyProtectedMember
41679 @dbus.service.method(
41680 dbus_interface=LV_INTERFACE,
41681 in_signature='tia{sv}',
41682 out_signature='o',
41683 async_callbacks=('cb', 'cbe'))
41684 def Deactivate(self, control_flags, tmo, activate_options, cb, cbe):
41685 r = RequestEntry(
41686 tmo, Lv._lv_activate_deactivate,
41687 (self.state.Uuid, self.state.lvm_id, False,
41688 control_flags, activate_options),
41689 cb, cbe, return_tuple=False)
41690 cfg.worker_q.put(r)
41691
41692 @staticmethod
41693 def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options):
41694 # Make sure we have a dbus object representing it
41695 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)
41696
41697 if dbo:
41698
41699 rc, out, err = cmdhandler.lv_tag(
41700 lv_name, tags_add, tags_del, tag_options)
41701 if rc == 0:
41702 dbo.refresh()
41703 return '/'
41704 else:
41705 raise dbus.exceptions.DBusException(
41706 LV_INTERFACE,
41707 'Exit code %s, stderr = %s' % (str(rc), err))
41708
41709 else:
41710 raise dbus.exceptions.DBusException(
41711 LV_INTERFACE,
41712 'LV with uuid %s and name %s not present!' %
41713 (uuid, lv_name))
41714
41715 @dbus.service.method(
41716 dbus_interface=LV_INTERFACE,
41717 in_signature='asia{sv}',
41718 out_signature='o',
41719 async_callbacks=('cb', 'cbe'))
41720 def TagsAdd(self, tags, tmo, tag_options, cb, cbe):
41721
41722 for t in tags:
41723 utils.validate_tag(LV_INTERFACE, t)
41724
41725 r = RequestEntry(
41726 tmo, Lv._add_rm_tags,
41727 (self.state.Uuid, self.state.lvm_id,
41728 tags, None, tag_options),
41729 cb, cbe, return_tuple=False)
41730 cfg.worker_q.put(r)
41731
41732 @dbus.service.method(
41733 dbus_interface=LV_INTERFACE,
41734 in_signature='asia{sv}',
41735 out_signature='o',
41736 async_callbacks=('cb', 'cbe'))
41737 def TagsDel(self, tags, tmo, tag_options, cb, cbe):
41738
41739 for t in tags:
41740 utils.validate_tag(LV_INTERFACE, t)
41741
41742 r = RequestEntry(
41743 tmo, Lv._add_rm_tags,
41744 (self.state.Uuid, self.state.lvm_id,
41745 None, tags, tag_options),
41746 cb, cbe, return_tuple=False)
41747 cfg.worker_q.put(r)
41748
41749
41750# noinspection PyPep8Naming
41751class LvThinPool(Lv):
41752 _DataLv_meta = ("o", THIN_POOL_INTERFACE)
41753 _MetaDataLv_meta = ("o", THIN_POOL_INTERFACE)
41754
41755 def __init__(self, object_path, object_state):
41756 super(LvThinPool, self).__init__(object_path, object_state)
41757 self.set_interface(THIN_POOL_INTERFACE)
41758 self._data_lv, self._metadata_lv = self._get_data_meta()
41759
41760 @property
41761 def DataLv(self):
41762 return dbus.ObjectPath(self._data_lv)
41763
41764 @property
41765 def MetaDataLv(self):
41766 return dbus.ObjectPath(self._metadata_lv)
41767
41768 @staticmethod
41769 def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
41770 # Make sure we have a dbus object representing it
41771 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41772
41773 if dbo:
41774 rc, out, err = cmdhandler.lv_lv_create(
41775 lv_name, create_options, name, size_bytes)
41776 if rc == 0:
41777 full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
41778 cfg.load()
41779 return cfg.om.get_object_path_by_lvm_id(full_name)
41780 else:
41781 raise dbus.exceptions.DBusException(
41782 LV_INTERFACE,
41783 'Exit code %s, stderr = %s' % (str(rc), err))
41784 else:
41785 raise dbus.exceptions.DBusException(
41786 LV_INTERFACE,
41787 'LV with uuid %s and name %s not present!' %
41788 (lv_uuid, lv_name))
41789
41790 @dbus.service.method(
41791 dbus_interface=THIN_POOL_INTERFACE,
41792 in_signature='stia{sv}',
41793 out_signature='(oo)',
41794 async_callbacks=('cb', 'cbe'))
41795 def LvCreate(self, name, size_bytes, tmo, create_options, cb, cbe):
41796 utils.validate_lv_name(THIN_POOL_INTERFACE, self.vg_name_lookup(), name)
41797
41798 r = RequestEntry(
41799 tmo, LvThinPool._lv_create,
41800 (self.Uuid, self.lvm_id, name,
41801 round_size(size_bytes), create_options), cb, cbe)
41802 cfg.worker_q.put(r)
41803
41804
41805# noinspection PyPep8Naming
41806class LvCachePool(Lv):
41807 _DataLv_meta = ("o", CACHE_POOL_INTERFACE)
41808 _MetaDataLv_meta = ("o", CACHE_POOL_INTERFACE)
41809
41810 def __init__(self, object_path, object_state):
41811 super(LvCachePool, self).__init__(object_path, object_state)
41812 self.set_interface(CACHE_POOL_INTERFACE)
41813 self._data_lv, self._metadata_lv = self._get_data_meta()
41814
41815 @property
41816 def DataLv(self):
41817 return dbus.ObjectPath(self._data_lv)
41818
41819 @property
41820 def MetaDataLv(self):
41821 return dbus.ObjectPath(self._metadata_lv)
41822
41823 @staticmethod
41824 def _cache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
41825
41826 # Make sure we have a dbus object representing cache pool
41827 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41828
41829 # Make sure we have dbus object representing lv to cache
41830 lv_to_cache = cfg.om.get_object_by_path(lv_object_path)
41831
41832 if dbo and lv_to_cache:
41833 fcn = lv_to_cache.lv_full_name()
41834 rc, out, err = cmdhandler.lv_cache_lv(
41835 dbo.lv_full_name(), fcn, cache_options)
41836 if rc == 0:
41837 # When we cache an LV, the cache pool and the lv that is getting
41838 # cached need to be removed from the object manager and
41839 # re-created as their interfaces have changed!
41840 mt_remove_dbus_objects((dbo, lv_to_cache))
41841 cfg.load()
41842
41843 lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
41844
41845 else:
41846 raise dbus.exceptions.DBusException(
41847 LV_INTERFACE,
41848 'Exit code %s, stderr = %s' % (str(rc), err))
41849 else:
41850 msg = ""
41851 if not dbo:
41852 dbo += 'CachePool LV with uuid %s and name %s not present!' % \
41853 (lv_uuid, lv_name)
41854
41855 if not lv_to_cache:
41856 dbo += 'LV to cache with object path %s not present!' % \
41857 (lv_object_path)
41858
41859 raise dbus.exceptions.DBusException(LV_INTERFACE, msg)
41860 return lv_converted
41861
41862 @dbus.service.method(
41863 dbus_interface=CACHE_POOL_INTERFACE,
41864 in_signature='oia{sv}',
41865 out_signature='(oo)',
41866 async_callbacks=('cb', 'cbe'))
41867 def CacheLv(self, lv_object, tmo, cache_options, cb, cbe):
41868 r = RequestEntry(
41869 tmo, LvCachePool._cache_lv,
41870 (self.Uuid, self.lvm_id, lv_object,
41871 cache_options), cb, cbe)
41872 cfg.worker_q.put(r)
41873
41874
41875# noinspection PyPep8Naming
41876class LvCacheLv(Lv):
41877 _CachePool_meta = ("o", LV_CACHED)
41878
41879 def __init__(self, object_path, object_state):
41880 super(LvCacheLv, self).__init__(object_path, object_state)
41881 self.set_interface(LV_CACHED)
41882
41883 @property
41884 def CachePool(self):
41885 return dbus.ObjectPath(self.state.PoolLv)
41886
41887 @staticmethod
41888 def _detach_lv(lv_uuid, lv_name, detach_options, destroy_cache):
41889 # Make sure we have a dbus object representing cache pool
41890 dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
41891
41892 if dbo:
41893
41894 # Get current cache name
41895 cache_pool = cfg.om.get_object_by_path(dbo.CachePool)
41896
41897 rc, out, err = cmdhandler.lv_detach_cache(
41898 dbo.lv_full_name(), detach_options, destroy_cache)
41899 if rc == 0:
41900 # The cache pool gets removed as hidden and put back to
41901 # visible, so lets delete
41902 mt_remove_dbus_objects((cache_pool, dbo))
41903 cfg.load()
41904
41905 uncached_lv_path = cfg.om.get_object_path_by_lvm_id(lv_name)
41906 else:
41907 raise dbus.exceptions.DBusException(
41908 LV_INTERFACE,
41909 'Exit code %s, stderr = %s' % (str(rc), err))
41910 else:
41911 raise dbus.exceptions.DBusException(
41912 LV_INTERFACE,
41913 'LV with uuid %s and name %s not present!' %
41914 (lv_uuid, lv_name))
41915 return uncached_lv_path
41916
41917 @dbus.service.method(
41918 dbus_interface=LV_CACHED,
41919 in_signature='bia{sv}',
41920 out_signature='(oo)',
41921 async_callbacks=('cb', 'cbe'))
41922 def DetachCachePool(self, destroy_cache, tmo, detach_options, cb, cbe):
41923 r = RequestEntry(
41924 tmo, LvCacheLv._detach_lv,
41925 (self.Uuid, self.lvm_id, detach_options,
41926 destroy_cache), cb, cbe)
41927 cfg.worker_q.put(r)
41928
41929
41930# noinspection PyPep8Naming
41931class LvSnapShot(Lv):
41932 def __init__(self, object_path, object_state):
41933 super(LvSnapShot, self).__init__(object_path, object_state)
41934 self.set_interface(SNAPSHOT_INTERFACE)
41935
41936 @dbus.service.method(
41937 dbus_interface=SNAPSHOT_INTERFACE,
41938 in_signature='ia{sv}',
41939 out_signature='o',
41940 async_callbacks=('cb', 'cbe'))
41941 def Merge(self, tmo, merge_options, cb, cbe):
41942 job_state = JobState()
41943
41944 r = RequestEntry(tmo, background.merge,
41945 (SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
41946 merge_options, job_state), cb, cbe, False,
41947 job_state)
41948 background.cmd_runner(r)
41949\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/pv.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000020152\013062740170\0021314\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
41950#
41951# This copyrighted material is made available to anyone wishing to use,
41952# modify, copy, or redistribute it subject to the terms and conditions
41953# of the GNU General Public License v.2.
41954#
41955# You should have received a copy of the GNU General Public License
41956# along with this program. If not, see <http://www.gnu.org/licenses/>.
41957
41958from .automatedproperties import AutomatedProperties
41959from . import utils
41960from . import cfg
41961import dbus
41962from .cfg import PV_INTERFACE
41963from . import cmdhandler
41964from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
41965 lv_object_path_method
41966from .loader import common
41967from .request import RequestEntry
41968from .state import State
41969from .utils import round_size
41970
41971
41972# noinspection PyUnusedLocal
41973def pvs_state_retrieve(selection, cache_refresh=True):
41974 rc = []
41975
41976 if cache_refresh:
41977 cfg.db.refresh()
41978
41979 for p in cfg.db.fetch_pvs(selection):
41980 rc.append(
41981 PvState(
41982 p["pv_name"], p["pv_uuid"], p["pv_name"],
41983 p["pv_fmt"], n(p["pv_size"]), n(p["pv_free"]),
41984 n(p["pv_used"]), n(p["dev_size"]), n(p["pv_mda_size"]),
41985 n(p["pv_mda_free"]), int(p["pv_ba_start"]),
41986 n(p["pv_ba_size"]), n(p["pe_start"]),
41987 int(p["pv_pe_count"]), int(p["pv_pe_alloc_count"]),
41988 p["pv_attr"], p["pv_tags"], p["vg_name"], p["vg_uuid"]))
41989 return rc
41990
41991
41992def load_pvs(device=None, object_path=None, refresh=False, emit_signal=False,
41993 cache_refresh=True):
41994 return common(
41995 pvs_state_retrieve, (Pv,), device, object_path, refresh,
41996 emit_signal, cache_refresh)
41997
41998
41999# noinspection PyUnresolvedReferences
42000class PvState(State):
42001 @property
42002 def lvm_id(self):
42003 return self.lvm_path
42004
42005 def _lv_object_list(self, vg_name):
42006 rc = []
42007 if vg_name:
42008 for lv in sorted(cfg.db.pv_contained_lv(self.lvm_id)):
42009 lv_uuid, lv_name, meta, segs = lv
42010 full_name = "%s/%s" % (vg_name, lv_name)
42011
42012 path_create = lv_object_path_method(lv_name, meta)
42013 lv_path = cfg.om.get_object_path_by_uuid_lvm_id(
42014 lv_uuid, full_name, path_create)
42015
42016 rc.append((lv_path, segs))
42017 return rc
42018
42019 # noinspection PyUnusedLocal,PyPep8Naming
42020 def __init__(self, lvm_path, Uuid, Name,
42021 Fmt, SizeBytes, FreeBytes, UsedBytes, DevSizeBytes,
42022 MdaSizeBytes, MdaFreeBytes, BaStart, BaSizeBytes,
42023 PeStart, PeCount, PeAllocCount, attr, Tags, vg_name,
42024 vg_uuid):
42025 utils.init_class_from_arguments(self)
42026 self.pe_segments = cfg.db.pv_pe_segments(Uuid)
42027
42028 self.lv = self._lv_object_list(vg_name)
42029
42030 if vg_name:
42031 self.vg_path = cfg.om.get_object_path_by_uuid_lvm_id(
42032 vg_uuid, vg_name, vg_obj_path_generate)
42033 else:
42034 self.vg_path = '/'
42035
42036 def identifiers(self):
42037 return (self.Uuid, self.lvm_path)
42038
42039 def create_dbus_object(self, path):
42040 if not path:
42041 path = cfg.om.get_object_path_by_uuid_lvm_id(self.Uuid, self.Name,
42042 pv_obj_path_generate)
42043 return Pv(path, self)
42044
42045 # noinspection PyMethodMayBeStatic
42046 def creation_signature(self):
42047 return (Pv, pv_obj_path_generate)
42048
42049
42050# noinspection PyPep8Naming
42051@utils.dbus_property(PV_INTERFACE, 'Uuid', 's') # PV UUID/pv_uuid
42052@utils.dbus_property(PV_INTERFACE, 'Name', 's') # PV/pv_name
42053@utils.dbus_property(PV_INTERFACE, 'Fmt', 's') # Fmt/pv_fmt
42054@utils.dbus_property(PV_INTERFACE, 'SizeBytes', 't') # PSize/pv_size
42055@utils.dbus_property(PV_INTERFACE, 'FreeBytes', 't') # PFree/pv_free
42056@utils.dbus_property(PV_INTERFACE, 'UsedBytes', 't') # Used/pv_used
42057@utils.dbus_property(PV_INTERFACE, 'DevSizeBytes', 't') # DevSize/dev_size
42058@utils.dbus_property(PV_INTERFACE, 'MdaSizeBytes', 't') # PMdaSize/pv_mda_size
42059@utils.dbus_property(PV_INTERFACE, 'MdaFreeBytes', 't') # PMdaFree/pv_mda_free
42060@utils.dbus_property(PV_INTERFACE, 'BaStart', 't') # BA start/pv_ba_start
42061@utils.dbus_property(PV_INTERFACE, 'BaSizeBytes', 't') # BA size/pv_ba_size
42062@utils.dbus_property(PV_INTERFACE, 'PeStart', 't') # 1st PE/pe_start
42063@utils.dbus_property(PV_INTERFACE, 'PeCount', 't') # PE/pv_pe_count
42064@utils.dbus_property(PV_INTERFACE, 'PeAllocCount', 't') # PE Allocation count
42065class Pv(AutomatedProperties):
42066 # For properties that we need custom handlers we need these, otherwise
42067 # we won't get our introspection data
42068 _Tags_meta = ("as", PV_INTERFACE)
42069 _PeSegments_meta = ("a(tt)", PV_INTERFACE)
42070 _Exportable_meta = ("b", PV_INTERFACE)
42071 _Allocatable_meta = ("b", PV_INTERFACE)
42072 _Missing_meta = ("b", PV_INTERFACE)
42073 _Lv_meta = ("a(oa(tts))", PV_INTERFACE)
42074 _Vg_meta = ("o", PV_INTERFACE)
42075
42076 # noinspection PyUnusedLocal,PyPep8Naming
42077 def __init__(self, object_path, state_obj):
42078 super(Pv, self).__init__(object_path, pvs_state_retrieve)
42079 self.set_interface(PV_INTERFACE)
42080 self.state = state_obj
42081
42082 @staticmethod
42083 def _remove(pv_uuid, pv_name, remove_options):
42084 # Remove the PV, if successful then remove from the model
42085 # Make sure we have a dbus object representing it
42086 dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
42087
42088 if dbo:
42089 rc, out, err = cmdhandler.pv_remove(pv_name, remove_options)
42090 if rc == 0:
42091 cfg.load()
42092 else:
42093 # Need to work on error handling, need consistent
42094 raise dbus.exceptions.DBusException(
42095 PV_INTERFACE,
42096 'Exit code %s, stderr = %s' % (str(rc), err))
42097 else:
42098 raise dbus.exceptions.DBusException(
42099 PV_INTERFACE,
42100 'PV with uuid %s and name %s not present!' %
42101 (pv_uuid, pv_name))
42102 return '/'
42103
42104 @dbus.service.method(
42105 dbus_interface=PV_INTERFACE,
42106 in_signature='ia{sv}',
42107 out_signature='o',
42108 async_callbacks=('cb', 'cbe'))
42109 def Remove(self, tmo, remove_options, cb, cbe):
42110 r = RequestEntry(
42111 tmo, Pv._remove,
42112 (self.Uuid, self.lvm_id, remove_options),
42113 cb, cbe, return_tuple=False)
42114 cfg.worker_q.put(r)
42115
42116 @staticmethod
42117 def _resize(pv_uuid, pv_name, new_size_bytes, resize_options):
42118 # Make sure we have a dbus object representing it
42119 dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
42120
42121 if dbo:
42122 rc, out, err = cmdhandler.pv_resize(pv_name, new_size_bytes,
42123 resize_options)
42124 if rc == 0:
42125 cfg.load()
42126 else:
42127 raise dbus.exceptions.DBusException(
42128 PV_INTERFACE,
42129 'Exit code %s, stderr = %s' % (str(rc), err))
42130 else:
42131 raise dbus.exceptions.DBusException(
42132 PV_INTERFACE,
42133 'PV with uuid %s and name %s not present!' %
42134 (pv_uuid, pv_name))
42135 return '/'
42136
42137 @dbus.service.method(
42138 dbus_interface=PV_INTERFACE,
42139 in_signature='tia{sv}',
42140 out_signature='o',
42141 async_callbacks=('cb', 'cbe'))
42142 def ReSize(self, new_size_bytes, tmo, resize_options, cb, cbe):
42143 r = RequestEntry(
42144 tmo, Pv._resize,
42145 (self.Uuid, self.lvm_id, round_size(new_size_bytes),
42146 resize_options), cb, cbe, False)
42147 cfg.worker_q.put(r)
42148
42149 @staticmethod
42150 def _allocation_enabled(pv_uuid, pv_name, yes_no, allocation_options):
42151 # Make sure we have a dbus object representing it
42152 dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
42153
42154 if dbo:
42155 rc, out, err = cmdhandler.pv_allocatable(
42156 pv_name, yes_no, allocation_options)
42157 if rc == 0:
42158 cfg.load()
42159 else:
42160 raise dbus.exceptions.DBusException(
42161 PV_INTERFACE, 'Exit code %s, stderr = %s' % (str(rc), err))
42162 else:
42163 raise dbus.exceptions.DBusException(
42164 PV_INTERFACE,
42165 'PV with uuid %s and name %s not present!' %
42166 (pv_uuid, pv_name))
42167 return '/'
42168
42169 @dbus.service.method(
42170 dbus_interface=PV_INTERFACE,
42171 in_signature='bia{sv}',
42172 out_signature='o',
42173 async_callbacks=('cb', 'cbe'))
42174 def AllocationEnabled(self, yes, tmo, allocation_options, cb, cbe):
42175 r = RequestEntry(
42176 tmo, Pv._allocation_enabled,
42177 (self.Uuid, self.lvm_id,
42178 yes, allocation_options),
42179 cb, cbe, False)
42180 cfg.worker_q.put(r)
42181
42182 @property
42183 def Tags(self):
42184 return utils.parse_tags(self.state.Tags)
42185
42186 @property
42187 def PeSegments(self):
42188 if len(self.state.pe_segments):
42189 return dbus.Array(self.state.pe_segments, signature='(tt)')
42190 return dbus.Array([], '(tt)')
42191
42192 @property
42193 def Exportable(self):
42194 return dbus.Boolean(self.state.attr[1] == 'x')
42195
42196 @property
42197 def Allocatable(self):
42198 return dbus.Boolean(self.state.attr[0] == 'a')
42199
42200 @property
42201 def Missing(self):
42202 return dbus.Boolean(self.state.attr[2] == 'm')
42203
42204 def object_path(self):
42205 return self._object_path
42206
42207 @property
42208 def lvm_id(self):
42209 return self.state.lvm_id
42210
42211 @property
42212 def identifiers(self):
42213 return self.state.identifiers()
42214
42215 @property
42216 def Lv(self):
42217 return dbus.Array(self.state.lv, signature="(oa(tts))")
42218
42219 @property
42220 def Vg(self):
42221 return dbus.ObjectPath(self.state.vg_path)
42222\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/vg.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000066752\013062740170\0021323\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
42223#
42224# This copyrighted material is made available to anyone wishing to use,
42225# modify, copy, or redistribute it subject to the terms and conditions
42226# of the GNU General Public License v.2.
42227#
42228# You should have received a copy of the GNU General Public License
42229# along with this program. If not, see <http://www.gnu.org/licenses/>.
42230
42231from .automatedproperties import AutomatedProperties
42232
42233from . import utils
42234from .utils import pv_obj_path_generate, vg_obj_path_generate, n
42235import dbus
42236from . import cfg
42237from .cfg import VG_INTERFACE
42238from . import cmdhandler
42239from .request import RequestEntry
42240from .loader import common
42241from .state import State
42242from . import background
42243from .utils import round_size, mt_remove_dbus_objects
42244from .job import JobState
42245
42246
42247# noinspection PyUnusedLocal
42248def vgs_state_retrieve(selection, cache_refresh=True):
42249 rc = []
42250
42251 if cache_refresh:
42252 cfg.db.refresh()
42253
42254 for v in cfg.db.fetch_vgs(selection):
42255 rc.append(
42256 VgState(
42257 v['vg_uuid'], v['vg_name'], v['vg_fmt'], n(v['vg_size']),
42258 n(v['vg_free']), v['vg_sysid'], n(v['vg_extent_size']),
42259 n(v['vg_extent_count']), n(v['vg_free_count']),
42260 v['vg_profile'], n(v['max_lv']), n(v['max_pv']),
42261 n(v['pv_count']), n(v['lv_count']), n(v['snap_count']),
42262 n(v['vg_seqno']), n(v['vg_mda_count']),
42263 n(v['vg_mda_free']), n(v['vg_mda_size']),
42264 n(v['vg_mda_used_count']), v['vg_attr'], v['vg_tags']))
42265 return rc
42266
42267
42268def load_vgs(vg_specific=None, object_path=None, refresh=False,
42269 emit_signal=False, cache_refresh=True):
42270 return common(vgs_state_retrieve, (Vg,), vg_specific, object_path, refresh,
42271 emit_signal, cache_refresh)
42272
42273
42274# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
42275class VgState(State):
42276 @property
42277 def lvm_id(self):
42278 return self.Name
42279
42280 def identifiers(self):
42281 return (self.Uuid, self.Name)
42282
42283 def _lv_paths_build(self):
42284 rc = []
42285 for lv in cfg.db.lvs_in_vg(self.Uuid):
42286 (lv_name, meta, lv_uuid) = lv
42287 full_name = "%s/%s" % (self.Name, lv_name)
42288
42289 gen = utils.lv_object_path_method(lv_name, meta)
42290
42291 lv_path = cfg.om.get_object_path_by_uuid_lvm_id(
42292 lv_uuid, full_name, gen)
42293 rc.append(lv_path)
42294 return dbus.Array(rc, signature='o')
42295
42296 def _pv_paths_build(self):
42297 rc = []
42298 for p in cfg.db.pvs_in_vg(self.Uuid):
42299 (pv_name, pv_uuid) = p
42300 rc.append(cfg.om.get_object_path_by_uuid_lvm_id(
42301 pv_uuid, pv_name, pv_obj_path_generate))
42302 return rc
42303
42304 def __init__(self, Uuid, Name, Fmt,
42305 SizeBytes, FreeBytes, SysId, ExtentSizeBytes,
42306 ExtentCount, FreeCount, Profile, MaxLv, MaxPv, PvCount,
42307 LvCount, SnapCount, Seqno, MdaCount, MdaFree,
42308 MdaSizeBytes, MdaUsedCount, attr, tags):
42309 utils.init_class_from_arguments(self)
42310 self.Pvs = self._pv_paths_build()
42311 self.Lvs = self._lv_paths_build()
42312
42313 def create_dbus_object(self, path):
42314 if not path:
42315 path = cfg.om.get_object_path_by_uuid_lvm_id(
42316 self.Uuid, self.Name, vg_obj_path_generate)
42317 return Vg(path, self)
42318
42319 # noinspection PyMethodMayBeStatic
42320 def creation_signature(self):
42321 return (Vg, vg_obj_path_generate)
42322
42323
42324# noinspection PyPep8Naming
42325@utils.dbus_property(VG_INTERFACE, 'Uuid', 's')
42326@utils.dbus_property(VG_INTERFACE, 'Name', 's')
42327@utils.dbus_property(VG_INTERFACE, 'Fmt', 's')
42328@utils.dbus_property(VG_INTERFACE, 'SizeBytes', 't', 0)
42329@utils.dbus_property(VG_INTERFACE, 'FreeBytes', 't', 0)
42330@utils.dbus_property(VG_INTERFACE, 'SysId', 's')
42331@utils.dbus_property(VG_INTERFACE, 'ExtentSizeBytes', 't')
42332@utils.dbus_property(VG_INTERFACE, 'ExtentCount', 't')
42333@utils.dbus_property(VG_INTERFACE, 'FreeCount', 't')
42334@utils.dbus_property(VG_INTERFACE, 'Profile', 's')
42335@utils.dbus_property(VG_INTERFACE, 'MaxLv', 't')
42336@utils.dbus_property(VG_INTERFACE, 'MaxPv', 't')
42337@utils.dbus_property(VG_INTERFACE, 'PvCount', 't')
42338@utils.dbus_property(VG_INTERFACE, 'LvCount', 't')
42339@utils.dbus_property(VG_INTERFACE, 'SnapCount', 't')
42340@utils.dbus_property(VG_INTERFACE, 'Seqno', 't')
42341@utils.dbus_property(VG_INTERFACE, 'MdaCount', 't')
42342@utils.dbus_property(VG_INTERFACE, 'MdaFree', 't')
42343@utils.dbus_property(VG_INTERFACE, 'MdaSizeBytes', 't')
42344@utils.dbus_property(VG_INTERFACE, 'MdaUsedCount', 't')
42345class Vg(AutomatedProperties):
42346 _Tags_meta = ("as", VG_INTERFACE)
42347 _Pvs_meta = ("ao", VG_INTERFACE)
42348 _Lvs_meta = ("ao", VG_INTERFACE)
42349 _Writeable_meta = ("b", VG_INTERFACE)
42350 _Readable_meta = ("b", VG_INTERFACE)
42351 _Resizeable_meta = ("b", VG_INTERFACE)
42352 _Exportable_meta = ('b', VG_INTERFACE)
42353 _Partial_meta = ('b', VG_INTERFACE)
42354 _AllocContiguous_meta = ('b', VG_INTERFACE)
42355 _AllocCling_meta = ('b', VG_INTERFACE)
42356 _AllocNormal_meta = ('b', VG_INTERFACE)
42357 _AllocAnywhere_meta = ('b', VG_INTERFACE)
42358 _Clustered_meta = ('b', VG_INTERFACE)
42359
42360 # noinspection PyUnusedLocal,PyPep8Naming
42361 def __init__(self, object_path, object_state):
42362 super(Vg, self).__init__(object_path, vgs_state_retrieve)
42363 self.set_interface(VG_INTERFACE)
42364 self._object_path = object_path
42365 self.state = object_state
42366
42367 @staticmethod
42368 def fetch_new_lv(vg_name, lv_name):
42369 cfg.load()
42370 return cfg.om.get_object_path_by_lvm_id("%s/%s" % (vg_name, lv_name))
42371
42372 @staticmethod
42373 def _rename(uuid, vg_name, new_name, rename_options):
42374 # Make sure we have a dbus object representing it
42375 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42376
42377 if dbo:
42378 rc, out, err = cmdhandler.vg_rename(vg_name, new_name,
42379 rename_options)
42380 if rc == 0:
42381 cfg.load()
42382 else:
42383 # Need to work on error handling, need consistent
42384 raise dbus.exceptions.DBusException(
42385 VG_INTERFACE,
42386 'Exit code %s, stderr = %s' % (str(rc), err))
42387 else:
42388 raise dbus.exceptions.DBusException(
42389 VG_INTERFACE,
42390 'VG with uuid %s and name %s not present!' %
42391 (uuid, vg_name))
42392 return '/'
42393
42394 @dbus.service.method(
42395 dbus_interface=VG_INTERFACE,
42396 in_signature='sia{sv}', out_signature='o',
42397 async_callbacks=('cb', 'cbe'))
42398 def Rename(self, name, tmo, rename_options, cb, cbe):
42399 utils.validate_vg_name(VG_INTERFACE, name)
42400 r = RequestEntry(tmo, Vg._rename,
42401 (self.state.Uuid, self.state.lvm_id, name,
42402 rename_options), cb, cbe, False)
42403 cfg.worker_q.put(r)
42404
42405 @staticmethod
42406 def _remove(uuid, vg_name, remove_options):
42407 # Make sure we have a dbus object representing it
42408 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42409
42410 if dbo:
42411 # Remove the VG, if successful then remove from the model
42412 rc, out, err = cmdhandler.vg_remove(vg_name, remove_options)
42413
42414 if rc == 0:
42415 cfg.load()
42416 else:
42417 # Need to work on error handling, need consistent
42418 raise dbus.exceptions.DBusException(
42419 VG_INTERFACE,
42420 'Exit code %s, stderr = %s' % (str(rc), err))
42421 else:
42422 raise dbus.exceptions.DBusException(
42423 VG_INTERFACE,
42424 'VG with uuid %s and name %s not present!' %
42425 (uuid, vg_name))
42426 return '/'
42427
42428 @dbus.service.method(
42429 dbus_interface=VG_INTERFACE,
42430 in_signature='ia{sv}', out_signature='o',
42431 async_callbacks=('cb', 'cbe'))
42432 def Remove(self, tmo, remove_options, cb, cbe):
42433 r = RequestEntry(tmo, Vg._remove,
42434 (self.state.Uuid, self.state.lvm_id, remove_options),
42435 cb, cbe, False)
42436 cfg.worker_q.put(r)
42437
42438 @staticmethod
42439 def _change(uuid, vg_name, change_options):
42440 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42441
42442 if dbo:
42443 rc, out, err = cmdhandler.vg_change(change_options, vg_name)
42444
42445 # To use an example with d-feet (Method input)
42446 # {"activate": __import__('gi.repository.GLib', globals(),
42447 # locals(), ['Variant']).Variant("s", "n")}
42448
42449 if rc == 0:
42450 cfg.load()
42451 else:
42452 raise dbus.exceptions.DBusException(
42453 VG_INTERFACE,
42454 'Exit code %s, stderr = %s' % (str(rc), err))
42455 else:
42456 raise dbus.exceptions.DBusException(
42457 VG_INTERFACE,
42458 'VG with uuid %s and name %s not present!' %
42459 (uuid, vg_name))
42460 return '/'
42461
42462 # TODO: This should be broken into a number of different methods
42463 # instead of having one method that takes a hash for parameters. Some of
42464 # the changes that vgchange does works on entire system, not just a
42465 # specfic vg, thus that should be in the Manager interface.
42466 @dbus.service.method(
42467 dbus_interface=VG_INTERFACE,
42468 in_signature='ia{sv}',
42469 out_signature='o',
42470 async_callbacks=('cb', 'cbe'))
42471 def Change(self, tmo, change_options, cb, cbe):
42472 r = RequestEntry(tmo, Vg._change,
42473 (self.state.Uuid, self.state.lvm_id, change_options),
42474 cb, cbe, False)
42475 cfg.worker_q.put(r)
42476
42477 @staticmethod
42478 def _reduce(uuid, vg_name, missing, pv_object_paths, reduce_options):
42479 # Make sure we have a dbus object representing it
42480 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42481
42482 if dbo:
42483 pv_devices = []
42484
42485 # If pv_object_paths is not empty, then get the device paths
42486 if pv_object_paths and len(pv_object_paths) > 0:
42487 for pv_op in pv_object_paths:
42488 pv = cfg.om.get_object_by_path(pv_op)
42489 if pv:
42490 pv_devices.append(pv.lvm_id)
42491 else:
42492 raise dbus.exceptions.DBusException(
42493 VG_INTERFACE,
42494 'PV Object path not found = %s!' % pv_op)
42495
42496 rc, out, err = cmdhandler.vg_reduce(vg_name, missing, pv_devices,
42497 reduce_options)
42498 if rc == 0:
42499 cfg.load()
42500 else:
42501 raise dbus.exceptions.DBusException(
42502 VG_INTERFACE, 'Exit code %s, stderr = %s' % (str(rc), err))
42503 else:
42504 raise dbus.exceptions.DBusException(
42505 VG_INTERFACE,
42506 'VG with uuid %s and name %s not present!' %
42507 (uuid, vg_name))
42508 return '/'
42509
42510 @dbus.service.method(
42511 dbus_interface=VG_INTERFACE,
42512 in_signature='baoia{sv}',
42513 out_signature='o',
42514 async_callbacks=('cb', 'cbe'))
42515 def Reduce(self, missing, pv_object_paths, tmo, reduce_options, cb, cbe):
42516 r = RequestEntry(tmo, Vg._reduce,
42517 (self.state.Uuid, self.state.lvm_id, missing,
42518 pv_object_paths, reduce_options), cb, cbe, False)
42519 cfg.worker_q.put(r)
42520
42521 @staticmethod
42522 def _extend(uuid, vg_name, pv_object_paths, extend_options):
42523 # Make sure we have a dbus object representing it
42524 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42525
42526 if dbo:
42527 extend_devices = []
42528
42529 for i in pv_object_paths:
42530 pv = cfg.om.get_object_by_path(i)
42531 if pv:
42532 extend_devices.append(pv.lvm_id)
42533 else:
42534 raise dbus.exceptions.DBusException(
42535 VG_INTERFACE, 'PV Object path not found = %s!' % i)
42536
42537 if len(extend_devices):
42538 rc, out, err = cmdhandler.vg_extend(vg_name, extend_devices,
42539 extend_options)
42540 if rc == 0:
42541 cfg.load()
42542 else:
42543 raise dbus.exceptions.DBusException(
42544 VG_INTERFACE,
42545 'Exit code %s, stderr = %s' % (str(rc), err))
42546 else:
42547 raise dbus.exceptions.DBusException(
42548 VG_INTERFACE, 'No pv_object_paths provided!')
42549 else:
42550 raise dbus.exceptions.DBusException(
42551 VG_INTERFACE,
42552 'VG with uuid %s and name %s not present!' %
42553 (uuid, vg_name))
42554 return '/'
42555
42556 @dbus.service.method(
42557 dbus_interface=VG_INTERFACE,
42558 in_signature='aoia{sv}', out_signature='o',
42559 async_callbacks=('cb', 'cbe'))
42560 def Extend(self, pv_object_paths, tmo, extend_options, cb, cbe):
42561 r = RequestEntry(tmo, Vg._extend,
42562 (self.state.Uuid, self.state.lvm_id, pv_object_paths,
42563 extend_options),
42564 cb, cbe, False)
42565 cfg.worker_q.put(r)
42566
42567 @dbus.service.method(
42568 dbus_interface=VG_INTERFACE,
42569 in_signature='o(tt)a(ott)ia{sv}',
42570 out_signature='o',
42571 async_callbacks=('cb', 'cbe'))
42572 def Move(self, pv_src_obj, pv_source_range, pv_dests_and_ranges,
42573 tmo, move_options, cb, cbe):
42574
42575 job_state = JobState()
42576
42577 r = RequestEntry(
42578 tmo, background.move,
42579 (VG_INTERFACE, None, pv_src_obj, pv_source_range,
42580 pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
42581 job_state)
42582
42583 cfg.worker_q.put(r)
42584
42585 @staticmethod
42586 def _lv_create(uuid, vg_name, name, size_bytes, pv_dests_and_ranges,
42587 create_options):
42588 # Make sure we have a dbus object representing it
42589 pv_dests = []
42590 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42591
42592 if dbo:
42593 if len(pv_dests_and_ranges):
42594 for pr in pv_dests_and_ranges:
42595 pv_dbus_obj = cfg.om.get_object_by_path(pr[0])
42596 if not pv_dbus_obj:
42597 raise dbus.exceptions.DBusException(
42598 VG_INTERFACE,
42599 'PV Destination (%s) not found' % pr[0])
42600
42601 pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
42602
42603 rc, out, err = cmdhandler.vg_lv_create(
42604 vg_name, create_options, name, size_bytes, pv_dests)
42605
42606 if rc == 0:
42607 return Vg.fetch_new_lv(vg_name, name)
42608 else:
42609 raise dbus.exceptions.DBusException(
42610 VG_INTERFACE,
42611 'Exit code %s, stderr = %s' % (str(rc), err))
42612 else:
42613 raise dbus.exceptions.DBusException(
42614 VG_INTERFACE,
42615 'VG with uuid %s and name %s not present!' %
42616 (uuid, vg_name))
42617
42618 @dbus.service.method(
42619 dbus_interface=VG_INTERFACE,
42620 in_signature='sta(ott)ia{sv}',
42621 out_signature='(oo)',
42622 async_callbacks=('cb', 'cbe'))
42623 def LvCreate(self, name, size_bytes, pv_dests_and_ranges,
42624 tmo, create_options, cb, cbe):
42625 """
42626 This one it for the advanced users that want to roll their own
42627 :param name: Name of the LV
42628 :param size_bytes: Size of LV in bytes
42629 :param pv_dests_and_ranges: Optional array of PV object paths and
42630 ranges
42631 :param tmo: -1 == Wait forever, 0 == return job immediately, > 0 ==
42632 willing to wait that number of seconds before
42633 getting a job
42634 :param create_options: hash of key/value pairs
42635 :param cb: Internal, not accessible by dbus API user
42636 :param cbe: Internal, not accessible by dbus API user
42637 :return: (oo) First object path is newly created object, second is
42638 job object path if created. Each == '/' when it doesn't
42639 apply.
42640 """
42641 utils.validate_lv_name(VG_INTERFACE, self.Name, name)
42642 r = RequestEntry(tmo, Vg._lv_create,
42643 (self.state.Uuid, self.state.lvm_id,
42644 name, round_size(size_bytes), pv_dests_and_ranges,
42645 create_options), cb, cbe)
42646 cfg.worker_q.put(r)
42647
42648 @staticmethod
42649 def _lv_create_linear(uuid, vg_name, name, size_bytes,
42650 thin_pool, create_options):
42651 # Make sure we have a dbus object representing it
42652 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42653
42654 if dbo:
42655 rc, out, err = cmdhandler.vg_lv_create_linear(
42656 vg_name, create_options, name, size_bytes, thin_pool)
42657
42658 if rc == 0:
42659 created_lv = Vg.fetch_new_lv(vg_name, name)
42660 else:
42661 raise dbus.exceptions.DBusException(
42662 VG_INTERFACE,
42663 'Exit code %s, stderr = %s' % (str(rc), err))
42664 else:
42665 raise dbus.exceptions.DBusException(
42666 VG_INTERFACE,
42667 'VG with uuid %s and name %s not present!' %
42668 (uuid, vg_name))
42669
42670 return created_lv
42671
42672 @dbus.service.method(
42673 dbus_interface=VG_INTERFACE,
42674 in_signature='stbia{sv}',
42675 out_signature='(oo)',
42676 async_callbacks=('cb', 'cbe'))
42677 def LvCreateLinear(self, name, size_bytes,
42678 thin_pool, tmo, create_options, cb, cbe):
42679 utils.validate_lv_name(VG_INTERFACE, self.Name, name)
42680 r = RequestEntry(tmo, Vg._lv_create_linear,
42681 (self.state.Uuid, self.state.lvm_id,
42682 name, round_size(size_bytes), thin_pool,
42683 create_options), cb, cbe)
42684 cfg.worker_q.put(r)
42685
42686 @staticmethod
42687 def _lv_create_striped(uuid, vg_name, name, size_bytes, num_stripes,
42688 stripe_size_kb, thin_pool, create_options):
42689 # Make sure we have a dbus object representing it
42690 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42691
42692 if dbo:
42693 rc, out, err = cmdhandler.vg_lv_create_striped(
42694 vg_name, create_options, name, size_bytes,
42695 num_stripes, stripe_size_kb, thin_pool)
42696 if rc == 0:
42697 created_lv = Vg.fetch_new_lv(vg_name, name)
42698 else:
42699 raise dbus.exceptions.DBusException(
42700 VG_INTERFACE,
42701 'Exit code %s, stderr = %s' % (str(rc), err))
42702 else:
42703 raise dbus.exceptions.DBusException(
42704 VG_INTERFACE, 'VG with uuid %s and name %s not present!' %
42705 (uuid, vg_name))
42706
42707 return created_lv
42708
42709 @dbus.service.method(
42710 dbus_interface=VG_INTERFACE,
42711 in_signature='stuubia{sv}',
42712 out_signature='(oo)',
42713 async_callbacks=('cb', 'cbe'))
42714 def LvCreateStriped(self, name, size_bytes, num_stripes,
42715 stripe_size_kb, thin_pool, tmo, create_options,
42716 cb, cbe):
42717 utils.validate_lv_name(VG_INTERFACE, self.Name, name)
42718 r = RequestEntry(
42719 tmo, Vg._lv_create_striped,
42720 (self.state.Uuid, self.state.lvm_id, name,
42721 round_size(size_bytes), num_stripes, stripe_size_kb,
42722 thin_pool, create_options),
42723 cb, cbe)
42724 cfg.worker_q.put(r)
42725
42726 @staticmethod
42727 def _lv_create_mirror(uuid, vg_name, name, size_bytes,
42728 num_copies, create_options):
42729 # Make sure we have a dbus object representing it
42730 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42731
42732 if dbo:
42733 rc, out, err = cmdhandler.vg_lv_create_mirror(
42734 vg_name, create_options, name, size_bytes, num_copies)
42735 if rc == 0:
42736 created_lv = Vg.fetch_new_lv(vg_name, name)
42737 else:
42738 raise dbus.exceptions.DBusException(
42739 VG_INTERFACE,
42740 'Exit code %s, stderr = %s' % (str(rc), err))
42741
42742 else:
42743 raise dbus.exceptions.DBusException(
42744 VG_INTERFACE,
42745 'VG with uuid %s and name %s not present!' %
42746 (uuid, vg_name))
42747
42748 return created_lv
42749
42750 @dbus.service.method(
42751 dbus_interface=VG_INTERFACE,
42752 in_signature='stuia{sv}',
42753 out_signature='(oo)',
42754 async_callbacks=('cb', 'cbe'))
42755 def LvCreateMirror(self, name, size_bytes, num_copies,
42756 tmo, create_options, cb, cbe):
42757 utils.validate_lv_name(VG_INTERFACE, self.Name, name)
42758 r = RequestEntry(
42759 tmo, Vg._lv_create_mirror,
42760 (self.state.Uuid, self.state.lvm_id, name,
42761 round_size(size_bytes), num_copies,
42762 create_options), cb, cbe)
42763 cfg.worker_q.put(r)
42764
42765 @staticmethod
42766 def _lv_create_raid(uuid, vg_name, name, raid_type, size_bytes,
42767 num_stripes, stripe_size_kb, create_options):
42768 # Make sure we have a dbus object representing it
42769 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42770
42771 if dbo:
42772 rc, out, err = cmdhandler.vg_lv_create_raid(
42773 vg_name, create_options, name, raid_type, size_bytes,
42774 num_stripes, stripe_size_kb)
42775 if rc == 0:
42776 created_lv = Vg.fetch_new_lv(vg_name, name)
42777 else:
42778 raise dbus.exceptions.DBusException(
42779 VG_INTERFACE,
42780 'Exit code %s, stderr = %s' % (str(rc), err))
42781
42782 else:
42783 raise dbus.exceptions.DBusException(
42784 VG_INTERFACE,
42785 'VG with uuid %s and name %s not present!' %
42786 (uuid, vg_name))
42787
42788 return created_lv
42789
42790 @dbus.service.method(
42791 dbus_interface=VG_INTERFACE,
42792 in_signature='sstuuia{sv}',
42793 out_signature='(oo)',
42794 async_callbacks=('cb', 'cbe'))
42795 def LvCreateRaid(self, name, raid_type, size_bytes,
42796 num_stripes, stripe_size_kb, tmo,
42797 create_options, cb, cbe):
42798 utils.validate_lv_name(VG_INTERFACE, self.Name, name)
42799 r = RequestEntry(tmo, Vg._lv_create_raid,
42800 (self.state.Uuid, self.state.lvm_id, name,
42801 raid_type, round_size(size_bytes), num_stripes,
42802 stripe_size_kb, create_options), cb, cbe)
42803 cfg.worker_q.put(r)
42804
42805 @staticmethod
42806 def _create_pool(uuid, vg_name, meta_data_lv, data_lv,
42807 create_options, create_method):
42808 # Make sure we have a dbus object representing it
42809 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42810
42811 # Retrieve the full names for the metadata and data lv
42812 md = cfg.om.get_object_by_path(meta_data_lv)
42813 data = cfg.om.get_object_by_path(data_lv)
42814
42815 if dbo and md and data:
42816
42817 new_name = data.Name
42818
42819 rc, out, err = create_method(
42820 md.lv_full_name(), data.lv_full_name(), create_options)
42821 if rc == 0:
42822 mt_remove_dbus_objects((md, data))
42823 cache_pool_lv = Vg.fetch_new_lv(vg_name, new_name)
42824 else:
42825 raise dbus.exceptions.DBusException(
42826 VG_INTERFACE,
42827 'Exit code %s, stderr = %s' % (str(rc), err))
42828
42829 else:
42830 msg = ""
42831
42832 if not dbo:
42833 msg += 'VG with uuid %s and name %s not present!' % \
42834 (uuid, vg_name)
42835
42836 if not md:
42837 msg += 'Meta data LV with object path %s not present!' % \
42838 (meta_data_lv)
42839
42840 if not data_lv:
42841 msg += 'Data LV with object path %s not present!' % \
42842 (meta_data_lv)
42843
42844 raise dbus.exceptions.DBusException(VG_INTERFACE, msg)
42845
42846 return cache_pool_lv
42847
42848 @dbus.service.method(
42849 dbus_interface=VG_INTERFACE,
42850 in_signature='ooia{sv}',
42851 out_signature='(oo)',
42852 async_callbacks=('cb', 'cbe'))
42853 def CreateCachePool(self, meta_data_lv, data_lv, tmo, create_options,
42854 cb, cbe):
42855 r = RequestEntry(
42856 tmo, Vg._create_pool,
42857 (self.state.Uuid, self.state.lvm_id, meta_data_lv,
42858 data_lv, create_options, cmdhandler.vg_create_cache_pool), cb, cbe)
42859 cfg.worker_q.put(r)
42860
42861 @dbus.service.method(
42862 dbus_interface=VG_INTERFACE,
42863 in_signature='ooia{sv}',
42864 out_signature='(oo)',
42865 async_callbacks=('cb', 'cbe'))
42866 def CreateThinPool(self, meta_data_lv, data_lv, tmo, create_options,
42867 cb, cbe):
42868 r = RequestEntry(
42869 tmo, Vg._create_pool,
42870 (self.state.Uuid, self.state.lvm_id, meta_data_lv,
42871 data_lv, create_options, cmdhandler.vg_create_thin_pool), cb, cbe)
42872 cfg.worker_q.put(r)
42873
42874 @staticmethod
42875 def _pv_add_rm_tags(uuid, vg_name, pv_object_paths, tags_add,
42876 tags_del, tag_options):
42877 pv_devices = []
42878
42879 # Make sure we have a dbus object representing it
42880 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42881
42882 if dbo:
42883 # Check for existence of pv object paths
42884 for p in pv_object_paths:
42885 pv = cfg.om.get_object_by_path(p)
42886 if pv:
42887 pv_devices.append(pv.Name)
42888 else:
42889 raise dbus.exceptions.DBusException(
42890 VG_INTERFACE, 'PV object path = %s not found' % p)
42891
42892 rc, out, err = cmdhandler.pv_tag(
42893 pv_devices, tags_add, tags_del, tag_options)
42894 if rc == 0:
42895 cfg.load()
42896 return '/'
42897 else:
42898 raise dbus.exceptions.DBusException(
42899 VG_INTERFACE,
42900 'Exit code %s, stderr = %s' % (str(rc), err))
42901
42902 else:
42903 raise dbus.exceptions.DBusException(
42904 VG_INTERFACE,
42905 'VG with uuid %s and name %s not present!' %
42906 (uuid, vg_name))
42907
42908 @dbus.service.method(
42909 dbus_interface=VG_INTERFACE,
42910 in_signature='aoasia{sv}',
42911 out_signature='o',
42912 async_callbacks=('cb', 'cbe'))
42913 def PvTagsAdd(self, pvs, tags, tmo, tag_options, cb, cbe):
42914
42915 for t in tags:
42916 utils.validate_tag(VG_INTERFACE, t)
42917
42918 r = RequestEntry(tmo, Vg._pv_add_rm_tags,
42919 (self.state.Uuid, self.state.lvm_id,
42920 pvs, tags, None, tag_options),
42921 cb, cbe, return_tuple=False)
42922 cfg.worker_q.put(r)
42923
42924 @dbus.service.method(
42925 dbus_interface=VG_INTERFACE,
42926 in_signature='aoasia{sv}',
42927 out_signature='o',
42928 async_callbacks=('cb', 'cbe'))
42929 def PvTagsDel(self, pvs, tags, tmo, tag_options, cb, cbe):
42930
42931 for t in tags:
42932 utils.validate_tag(VG_INTERFACE, t)
42933
42934 r = RequestEntry(
42935 tmo, Vg._pv_add_rm_tags,
42936 (self.state.Uuid, self.state.lvm_id,
42937 pvs, None, tags, tag_options),
42938 cb, cbe, return_tuple=False)
42939 cfg.worker_q.put(r)
42940
42941 @staticmethod
42942 def _vg_add_rm_tags(uuid, vg_name, tags_add, tags_del, tag_options):
42943 # Make sure we have a dbus object representing it
42944 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
42945
42946 if dbo:
42947
42948 rc, out, err = cmdhandler.vg_tag(
42949 vg_name, tags_add, tags_del, tag_options)
42950 if rc == 0:
42951 dbo.refresh()
42952 return '/'
42953 else:
42954 raise dbus.exceptions.DBusException(
42955 VG_INTERFACE,
42956 'Exit code %s, stderr = %s' % (str(rc), err))
42957
42958 else:
42959 raise dbus.exceptions.DBusException(
42960 VG_INTERFACE,
42961 'VG with uuid %s and name %s not present!' %
42962 (uuid, vg_name))
42963
42964 @dbus.service.method(
42965 dbus_interface=VG_INTERFACE,
42966 in_signature='asia{sv}',
42967 out_signature='o',
42968 async_callbacks=('cb', 'cbe'))
42969 def TagsAdd(self, tags, tmo, tag_options, cb, cbe):
42970
42971 for t in tags:
42972 utils.validate_tag(VG_INTERFACE, t)
42973
42974 r = RequestEntry(tmo, Vg._vg_add_rm_tags,
42975 (self.state.Uuid, self.state.lvm_id,
42976 tags, None, tag_options),
42977 cb, cbe, return_tuple=False)
42978 cfg.worker_q.put(r)
42979
42980 @dbus.service.method(
42981 dbus_interface=VG_INTERFACE,
42982 in_signature='asia{sv}',
42983 out_signature='o',
42984 async_callbacks=('cb', 'cbe'))
42985 def TagsDel(self, tags, tmo, tag_options, cb, cbe):
42986
42987 for t in tags:
42988 utils.validate_tag(VG_INTERFACE, t)
42989
42990 r = RequestEntry(tmo, Vg._vg_add_rm_tags,
42991 (self.state.Uuid, self.state.lvm_id,
42992 None, tags, tag_options),
42993 cb, cbe, return_tuple=False)
42994 cfg.worker_q.put(r)
42995
42996 @staticmethod
42997 def _vg_change_set(uuid, vg_name, method, value, options):
42998 # Make sure we have a dbus object representing it
42999 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
43000
43001 if dbo:
43002 rc, out, err = method(vg_name, value, options)
43003 if rc == 0:
43004 dbo.refresh()
43005 return '/'
43006 else:
43007 raise dbus.exceptions.DBusException(
43008 VG_INTERFACE,
43009 'Exit code %s, stderr = %s' % (str(rc), err))
43010
43011 else:
43012 raise dbus.exceptions.DBusException(
43013 VG_INTERFACE,
43014 'VG with uuid %s and name %s not present!' %
43015 (uuid, vg_name))
43016
43017 @dbus.service.method(
43018 dbus_interface=VG_INTERFACE,
43019 in_signature='sia{sv}',
43020 out_signature='o',
43021 async_callbacks=('cb', 'cbe'))
43022 def AllocationPolicySet(self, policy, tmo, policy_options, cb, cbe):
43023 r = RequestEntry(tmo, Vg._vg_change_set,
43024 (self.state.Uuid, self.state.lvm_id,
43025 cmdhandler.vg_allocation_policy,
43026 policy, policy_options),
43027 cb, cbe, return_tuple=False)
43028 cfg.worker_q.put(r)
43029
43030 @dbus.service.method(
43031 dbus_interface=VG_INTERFACE,
43032 in_signature='tia{sv}',
43033 out_signature='o',
43034 async_callbacks=('cb', 'cbe'))
43035 def MaxPvSet(self, number, tmo, max_options, cb, cbe):
43036 r = RequestEntry(tmo, Vg._vg_change_set,
43037 (self.state.Uuid, self.state.lvm_id,
43038 cmdhandler.vg_max_pv, number, max_options),
43039 cb, cbe, return_tuple=False)
43040 cfg.worker_q.put(r)
43041
43042 @dbus.service.method(
43043 dbus_interface=VG_INTERFACE,
43044 in_signature='ia{sv}',
43045 out_signature='o',
43046 async_callbacks=('cb', 'cbe'))
43047 def UuidGenerate(self, tmo, options, cb, cbe):
43048 r = RequestEntry(tmo, Vg._vg_change_set,
43049 (self.state.Uuid, self.state.lvm_id,
43050 cmdhandler.vg_uuid_gen, None, options),
43051 cb, cbe, return_tuple=False)
43052 cfg.worker_q.put(r)
43053
43054 def _attribute(self, pos, ch):
43055 return dbus.Boolean(self.state.attr[pos] == ch)
43056
43057 @dbus.service.method(
43058 dbus_interface=VG_INTERFACE,
43059 in_signature='tia{sv}',
43060 out_signature='o',
43061 async_callbacks=('cb', 'cbe'))
43062 def MaxLvSet(self, number, tmo, max_options, cb, cbe):
43063 r = RequestEntry(tmo, Vg._vg_change_set,
43064 (self.state.Uuid, self.state.lvm_id,
43065 cmdhandler.vg_max_lv, number, max_options),
43066 cb, cbe, return_tuple=False)
43067 cfg.worker_q.put(r)
43068
43069 @staticmethod
43070 def _vg_activate_deactivate(uuid, vg_name, activate, control_flags,
43071 options):
43072 # Make sure we have a dbus object representing it
43073 dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, vg_name)
43074
43075 if dbo:
43076 rc, out, err = cmdhandler.activate_deactivate(
43077 'vgchange', vg_name, activate, control_flags, options)
43078 if rc == 0:
43079 cfg.load()
43080 return '/'
43081 else:
43082 raise dbus.exceptions.DBusException(
43083 VG_INTERFACE,
43084 'Exit code %s, stderr = %s' % (str(rc), err))
43085 else:
43086 raise dbus.exceptions.DBusException(
43087 VG_INTERFACE,
43088 'VG with uuid %s and name %s not present!' %
43089 (uuid, vg_name))
43090
43091 @dbus.service.method(
43092 dbus_interface=VG_INTERFACE,
43093 in_signature='tia{sv}',
43094 out_signature='o',
43095 async_callbacks=('cb', 'cbe'))
43096 def Activate(self, control_flags, tmo, activate_options, cb, cbe):
43097 r = RequestEntry(tmo, Vg._vg_activate_deactivate,
43098 (self.state.Uuid, self.state.lvm_id, True,
43099 control_flags, activate_options),
43100 cb, cbe, return_tuple=False)
43101 cfg.worker_q.put(r)
43102
43103 @dbus.service.method(
43104 dbus_interface=VG_INTERFACE,
43105 in_signature='tia{sv}',
43106 out_signature='o',
43107 async_callbacks=('cb', 'cbe'))
43108 def Deactivate(self, control_flags, tmo, activate_options, cb, cbe):
43109 r = RequestEntry(tmo, Vg._vg_activate_deactivate,
43110 (self.state.Uuid, self.state.lvm_id, False,
43111 control_flags, activate_options),
43112 cb, cbe, return_tuple=False)
43113 cfg.worker_q.put(r)
43114
43115 @property
43116 def Tags(self):
43117 return utils.parse_tags(self.state.tags)
43118
43119 @property
43120 def Pvs(self):
43121 return dbus.Array(self.state.Pvs, signature='o')
43122
43123 @property
43124 def Lvs(self):
43125 return dbus.Array(self.state.Lvs, signature='o')
43126
43127 @property
43128 def lvm_id(self):
43129 return self.state.lvm_id
43130
43131 @property
43132 def Writeable(self):
43133 return self._attribute(0, 'w')
43134
43135 @property
43136 def Readable(self):
43137 return self._attribute(0, 'r')
43138
43139 @property
43140 def Resizeable(self):
43141 return self._attribute(1, 'z')
43142
43143 @property
43144 def Exportable(self):
43145 return self._attribute(2, 'x')
43146
43147 @property
43148 def Partial(self):
43149 return self._attribute(3, 'p')
43150
43151 @property
43152 def AllocContiguous(self):
43153 return self._attribute(4, 'c')
43154
43155 @property
43156 def AllocCling(self):
43157 return self._attribute(4, 'l')
43158
43159 @property
43160 def AllocNormal(self):
43161 return self._attribute(4, 'n')
43162
43163 @property
43164 def AllocAnywhere(self):
43165 return self._attribute(4, 'a')
43166
43167 @property
43168 def Clustered(self):
43169 return self._attribute(5, 'c')
43170\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/objectmanager.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000026463\013062740170\0023503\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
43171#
43172# This copyrighted material is made available to anyone wishing to use,
43173# modify, copy, or redistribute it subject to the terms and conditions
43174# of the GNU General Public License v.2.
43175#
43176# You should have received a copy of the GNU General Public License
43177# along with this program. If not, see <http://www.gnu.org/licenses/>.
43178
43179import sys
43180import threading
43181import traceback
43182import dbus
43183import os
43184import copy
43185from . import cfg
43186from .utils import log_debug, pv_obj_path_generate, log_error
43187from .automatedproperties import AutomatedProperties
43188
43189
43190# noinspection PyPep8Naming
43191class ObjectManager(AutomatedProperties):
43192 """
43193 Implements the org.freedesktop.DBus.ObjectManager interface
43194 """
43195
43196 def __init__(self, object_path, interface):
43197 super(ObjectManager, self).__init__(object_path, interface)
43198 self.set_interface(interface)
43199 self._ap_o_path = object_path
43200 self._objects = {}
43201 self._id_to_object_path = {}
43202 self.rlock = threading.RLock()
43203
43204 @dbus.service.method(
43205 dbus_interface="org.freedesktop.DBus.ObjectManager",
43206 out_signature='a{oa{sa{sv}}}')
43207 def GetManagedObjects(self):
43208 with self.rlock:
43209 rc = {}
43210 try:
43211 for k, v in list(self._objects.items()):
43212 path, props = v[0].emit_data()
43213 rc[path] = props
43214 except Exception:
43215 traceback.print_exc(file=sys.stdout)
43216 sys.exit(1)
43217 return rc
43218
43219 def locked(self):
43220 """
43221 If some external code need to run across a number of different
43222 calls into ObjectManager while blocking others they can use this method
43223 to lock others out.
43224 :return:
43225 """
43226 return ObjectManagerLock(self.rlock)
43227
43228 @dbus.service.signal(
43229 dbus_interface="org.freedesktop.DBus.ObjectManager",
43230 signature='oa{sa{sv}}')
43231 def InterfacesAdded(self, object_path, int_name_prop_dict):
43232 log_debug(
43233 ('SIGNAL: InterfacesAdded(%s, %s)' %
43234 (str(object_path), str(int_name_prop_dict))))
43235
43236 @dbus.service.signal(
43237 dbus_interface="org.freedesktop.DBus.ObjectManager",
43238 signature='oas')
43239 def InterfacesRemoved(self, object_path, interface_list):
43240 log_debug(('SIGNAL: InterfacesRemoved(%s, %s)' %
43241 (str(object_path), str(interface_list))))
43242
43243 def validate_lookups(self):
43244 with self.rlock:
43245 tmp_lookups = copy.deepcopy(self._id_to_object_path)
43246
43247 # iterate over all we know, removing from the copy. If all is well
43248 # we will have zero items left over
43249 for path, md in self._objects.items():
43250 obj, lvm_id, uuid = md
43251
43252 if lvm_id:
43253 assert path == tmp_lookups[lvm_id]
43254 del tmp_lookups[lvm_id]
43255
43256 if uuid:
43257 assert path == tmp_lookups[uuid]
43258 del tmp_lookups[uuid]
43259
43260 rc = len(tmp_lookups)
43261 if rc:
43262 # Error condition
43263 log_error("_id_to_object_path has extraneous lookups!")
43264 for key, path in tmp_lookups.items():
43265 log_error("Key= %s, path= %s" % (key, path))
43266 return rc
43267
43268 def _lookup_add(self, obj, path, lvm_id, uuid):
43269 """
43270 Store information about what we added to the caches so that we
43271 can remove it cleanly
43272 :param obj: The dbus object we are storing
43273 :param lvm_id: The lvm id for the asset
43274 :param uuid: The uuid for the asset
43275 :return:
43276 """
43277 # Note: Only called internally, lock implied
43278
43279 # We could have a temp entry from the forward creation of a path
43280 self._lookup_remove(path)
43281
43282 self._objects[path] = (obj, lvm_id, uuid)
43283
43284 # Make sure we have one or the other
43285 assert lvm_id or uuid
43286
43287 if lvm_id:
43288 self._id_to_object_path[lvm_id] = path
43289
43290 if uuid:
43291 self._id_to_object_path[uuid] = path
43292
43293 def _lookup_remove(self, obj_path):
43294 # Note: Only called internally, lock implied
43295 if obj_path in self._objects:
43296 (obj, lvm_id, uuid) = self._objects[obj_path]
43297
43298 if lvm_id in self._id_to_object_path:
43299 del self._id_to_object_path[lvm_id]
43300
43301 if uuid in self._id_to_object_path:
43302 del self._id_to_object_path[uuid]
43303
43304 del self._objects[obj_path]
43305
43306 def lookup_update(self, dbus_obj, new_uuid, new_lvm_id):
43307 with self.rlock:
43308 obj_path = dbus_obj.dbus_object_path()
43309 self._lookup_remove(obj_path)
43310 self._lookup_add(
43311 dbus_obj, obj_path,
43312 new_lvm_id, new_uuid)
43313
43314 def object_paths_by_type(self, o_type):
43315 with self.rlock:
43316 rc = {}
43317
43318 for k, v in list(self._objects.items()):
43319 if isinstance(v[0], o_type):
43320 rc[k] = True
43321 return rc
43322
43323 def register_object(self, dbus_object, emit_signal=False):
43324 """
43325 Given a dbus object add it to the collection
43326 :param dbus_object: Dbus object to register
43327 :param emit_signal: If true emit a signal for interfaces added
43328 """
43329 with self.rlock:
43330 path, props = dbus_object.emit_data()
43331
43332 # print('Registering object path %s for %s' %
43333 # (path, dbus_object.lvm_id))
43334
43335 # We want fast access to the object by a number of different ways
43336 # so we use multiple hashs with different keys
43337 self._lookup_add(dbus_object, path, dbus_object.lvm_id,
43338 dbus_object.Uuid)
43339
43340 if emit_signal:
43341 self.InterfacesAdded(path, props)
43342
43343 def remove_object(self, dbus_object, emit_signal=False):
43344 """
43345 Given a dbus object, remove it from the collection and remove it
43346 from the dbus framework as well
43347 :param dbus_object: Dbus object to remove
43348 :param emit_signal: If true emit the interfaces removed signal
43349 """
43350 with self.rlock:
43351 # Store off the object path and the interface first
43352 path = dbus_object.dbus_object_path()
43353 interfaces = dbus_object.interface()
43354
43355 # print 'UN-Registering object path %s for %s' % \
43356 # (path, dbus_object.lvm_id)
43357
43358 self._lookup_remove(path)
43359
43360 # Remove from dbus library
43361 dbus_object.remove_from_connection(cfg.bus, path)
43362
43363 # Optionally emit a signal
43364 if emit_signal:
43365 self.InterfacesRemoved(path, interfaces)
43366
43367 def get_object_by_path(self, path):
43368 """
43369 Given a dbus path return the object registered for it
43370 :param path: The dbus path
43371 :return: The object
43372 """
43373 with self.rlock:
43374 if path in self._objects:
43375 return self._objects[path][0]
43376 return None
43377
43378 def get_object_by_uuid_lvm_id(self, uuid, lvm_id):
43379 with self.rlock:
43380 return self.get_object_by_path(
43381 self.get_object_path_by_uuid_lvm_id(uuid, lvm_id))
43382
43383 def get_object_by_lvm_id(self, lvm_id):
43384 """
43385 Given an lvm identifier, return the object registered for it
43386 :param lvm_id: The lvm identifier
43387 """
43388 with self.rlock:
43389 if lvm_id in self._id_to_object_path:
43390 return self.get_object_by_path(self._id_to_object_path[lvm_id])
43391 return None
43392
43393 def get_object_path_by_lvm_id(self, lvm_id):
43394 """
43395 Given an lvm identifier, return the object path for it
43396 :param lvm_id: The lvm identifier
43397 :return: Object path or '/' if not found
43398 """
43399 with self.rlock:
43400 if lvm_id in self._id_to_object_path:
43401 return self._id_to_object_path[lvm_id]
43402 return '/'
43403
43404 def _uuid_verify(self, path, uuid, lvm_id):
43405 """
43406 Ensure uuid is present for a successful lvm_id lookup
43407 NOTE: Internal call, assumes under object manager lock
43408 :param path: Path to object we looked up
43409 :param uuid: lvm uuid to verify
43410 :param lvm_id: lvm_id used to find object
43411 :return: None
43412 """
43413 # This gets called when we found an object based on lvm_id, ensure
43414 # uuid is correct too, as they can change. There is no durable
43415 # non-changeable name in lvm
43416 if lvm_id != uuid:
43417 if uuid and uuid not in self._id_to_object_path:
43418 obj = self.get_object_by_path(path)
43419 self._lookup_add(obj, path, lvm_id, uuid)
43420
43421 def _lvm_id_verify(self, path, uuid, lvm_id):
43422 """
43423 Ensure lvm_id is present for a successful uuid lookup
43424 NOTE: Internal call, assumes under object manager lock
43425 :param path: Path to object we looked up
43426 :param uuid: uuid used to find object
43427 :param lvm_id: lvm_id to verify
43428 :return: None
43429 """
43430 # This gets called when we found an object based on uuid, ensure
43431 # lvm_id is correct too, as they can change. There is no durable
43432 # non-changeable name in lvm
43433 if lvm_id != uuid:
43434 if lvm_id and lvm_id not in self._id_to_object_path:
43435 obj = self.get_object_by_path(path)
43436 self._lookup_add(obj, path, lvm_id, uuid)
43437
43438 def _id_lookup(self, the_id):
43439 path = None
43440
43441 if the_id:
43442 # The _id_to_object_path contains hash keys for everything, so
43443 # uuid and lvm_id
43444 if the_id in self._id_to_object_path:
43445 path = self._id_to_object_path[the_id]
43446 else:
43447 if "/" in the_id:
43448 if the_id.startswith('/'):
43449 # We could have a pv device path lookup that failed,
43450 # lets try canonical form and try again.
43451 canonical = os.path.realpath(the_id)
43452 if canonical in self._id_to_object_path:
43453 path = self._id_to_object_path[canonical]
43454 else:
43455 vg, lv = the_id.split("/", 1)
43456 int_lvm_id = vg + "/" + ("[%s]" % lv)
43457 if int_lvm_id in self._id_to_object_path:
43458 path = self._id_to_object_path[int_lvm_id]
43459 return path
43460
43461 def get_object_path_by_uuid_lvm_id(self, uuid, lvm_id, path_create=None):
43462 """
43463 For a given lvm asset return the dbus object path registered for it.
43464 This method first looks up by uuid and then by lvm_id. You
43465 can search by just one by setting uuid == lvm_id (uuid or lvm_id).
43466 If the object is not found and path_create is a not None, the
43467 path_create function will be called to create a new object path and
43468 register it with the object manager for the specified uuid & lvm_id.
43469 Note: If path create is not None, uuid and lvm_id cannot be equal
43470 :param uuid: The uuid for the lvm object we are searching for
43471 :param lvm_id: The lvm name (eg. pv device path, vg name, lv full name)
43472 :param path_create: If not None, create the path using this function if
43473 we fail to find the object by uuid or lvm_id.
43474 :returns None if lvm asset not found and path_create == None otherwise
43475 a valid dbus object path
43476 """
43477 with self.rlock:
43478 assert lvm_id
43479 assert uuid
43480
43481 if path_create:
43482 assert uuid != lvm_id
43483
43484 # Check for Manager.LookUpByLvmId query, we cannot
43485 # check/verify/update the uuid and lvm_id lookups so don't!
43486 if uuid == lvm_id:
43487 path = self._id_lookup(lvm_id)
43488 else:
43489 # We have a uuid and a lvm_id we can do sanity checks to ensure
43490 # that they are consistent
43491
43492 # If a PV is missing it's device path is '[unknown]' or some
43493 # other text derivation of unknown. When we find that a PV is
43494 # missing we will clear out the lvm_id as it's likely not unique
43495 # and thus not useful and potentially harmful for lookups.
43496 if path_create == pv_obj_path_generate and \
43497 cfg.db.pv_missing(uuid):
43498 lvm_id = None
43499
43500 # Lets check for the uuid first
43501 path = self._id_lookup(uuid)
43502 if path:
43503 # Verify the lvm_id is sane
43504 self._lvm_id_verify(path, uuid, lvm_id)
43505 else:
43506 # Unable to find by UUID, lets lookup by lvm_id
43507 path = self._id_lookup(lvm_id)
43508 if path:
43509 # Verify the uuid is sane
43510 self._uuid_verify(path, uuid, lvm_id)
43511 else:
43512 # We have exhausted all lookups, let's create if we can
43513 if path_create:
43514 path = path_create()
43515 self._lookup_add(None, path, lvm_id, uuid)
43516
43517 # print('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
43518 # (uuid, lvm_id, str(path_create), str(gen_new), path))
43519
43520 return path
43521
43522
43523class ObjectManagerLock(object):
43524 """
43525 The sole purpose of this class is to allow other code the ability to
43526 lock the object manager using a `with` statement, eg.
43527
43528 with cfg.om.locked():
43529 # Do stuff with object manager
43530
43531 This will ensure that the lock is always released (assuming this is done
43532 correctly)
43533 """
43534
43535 def __init__(self, recursive_lock):
43536 self._lock = recursive_lock
43537
43538 def __enter__(self):
43539 # Acquire lock
43540 self._lock.acquire()
43541
43542 # noinspection PyUnusedLocal
43543 def __exit__(self, e_type, e_value, e_traceback):
43544 # Release lock
43545 self._lock.release()
43546 self._lock = None
43547\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/cfg.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004503\013062740170\0021430\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
43548#
43549# This copyrighted material is made available to anyone wishing to use,
43550# modify, copy, or redistribute it subject to the terms and conditions
43551# of the GNU General Public License v.2.
43552#
43553# You should have received a copy of the GNU General Public License
43554# along with this program. If not, see <http://www.gnu.org/licenses/>.
43555
43556import os
43557import multiprocessing
43558import queue
43559import itertools
43560
43561from lvmdbusd import path
43562
43563LVM_CMD = os.getenv('LVM_BINARY', path.LVM_BINARY)
43564
43565# This is the global object manager
43566om = None
43567
43568# This is the global bus connection
43569bus = None
43570
43571# Command line args
43572args = None
43573
43574# Set to true if we are depending on external events for updates
43575ee = False
43576
43577# Shared state variable across all processes
43578run = multiprocessing.Value('i', 1)
43579
43580# If this is set to true, the current setup support lvm shell and we are
43581# running in that mode of operation
43582SHELL_IN_USE = None
43583
43584# Lock used by pprint
43585stdout_lock = multiprocessing.Lock()
43586
43587worker_q = queue.Queue()
43588
43589# Main event loop
43590loop = None
43591
43592BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1')
43593BASE_INTERFACE = 'com.redhat.lvmdbus1'
43594PV_INTERFACE = BASE_INTERFACE + '.Pv'
43595VG_INTERFACE = BASE_INTERFACE + '.Vg'
43596LV_INTERFACE = BASE_INTERFACE + '.Lv'
43597LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon'
43598THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool'
43599CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool'
43600LV_CACHED = BASE_INTERFACE + '.CachedLv'
43601SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot'
43602MANAGER_INTERFACE = BASE_INTERFACE + '.Manager'
43603JOB_INTERFACE = BASE_INTERFACE + '.Job'
43604
43605BASE_OBJ_PATH = '/' + BASE_INTERFACE.replace('.', '/')
43606PV_OBJ_PATH = BASE_OBJ_PATH + '/Pv'
43607VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg'
43608LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv'
43609THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool"
43610CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool"
43611HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv"
43612MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager'
43613JOB_OBJ_PATH = BASE_OBJ_PATH + '/Job'
43614
43615# Counters for object path generation
43616pv_id = itertools.count()
43617vg_id = itertools.count()
43618lv_id = itertools.count()
43619thin_id = itertools.count()
43620cache_pool_id = itertools.count()
43621job_id = itertools.count()
43622hidden_lv = itertools.count()
43623
43624# Used to prevent circular imports...
43625load = None
43626event = None
43627
43628# Global cached state
43629db = None
43630
43631# lvm flight recorder
43632blackbox = None
43633\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/lvmdbusd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000760\013062740170\0022066\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/usr/bin/env python3
43634
43635# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
43636#
43637# This copyrighted material is made available to anyone wishing to use,
43638# modify, copy, or redistribute it subject to the terms and conditions
43639# of the GNU General Public License v.2.
43640#
43641# You should have received a copy of the GNU General Public License
43642# along with this program. If not, see <http://www.gnu.org/licenses/>.
43643
43644import sys
43645from lvmdbusd import main
43646
43647if __name__ == '__main__':
43648 sys.exit(main())
43649\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/state.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001275\013062740170\0022014\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
43650#
43651# This copyrighted material is made available to anyone wishing to use,
43652# modify, copy, or redistribute it subject to the terms and conditions
43653# of the GNU General Public License v.2.
43654#
43655# You should have received a copy of the GNU General Public License
43656# along with this program. If not, see <http://www.gnu.org/licenses/>.
43657
43658from abc import ABCMeta, abstractmethod
43659
43660
43661class State(object, metaclass=ABCMeta):
43662 @abstractmethod
43663 def lvm_id(self):
43664 pass
43665
43666 @abstractmethod
43667 def identifiers(self):
43668 pass
43669
43670 @abstractmethod
43671 def create_dbus_object(self, path):
43672 pass
43673
43674 def __str__(self):
43675 return '*****\n' + str(self.__dict__) + '\n******\n'
43676\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/lvmdb.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000033277\013062740170\0022012\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/usr/bin/env python3
43677
43678# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
43679#
43680# This copyrighted material is made available to anyone wishing to use,
43681# modify, copy, or redistribute it subject to the terms and conditions
43682# of the GNU General Public License v.2.
43683#
43684# You should have received a copy of the GNU General Public License
43685# along with this program. If not, see <http://www.gnu.org/licenses/>.
43686
43687from collections import OrderedDict
43688
43689import pprint as prettyprint
43690import os
43691import sys
43692
43693from lvmdbusd import cmdhandler
43694from lvmdbusd.utils import log_debug, log_error
43695
43696
43697class DataStore(object):
43698 def __init__(self, usejson=True):
43699 self.pvs = {}
43700 self.vgs = {}
43701 self.lvs = {}
43702 self.pv_lvs = {}
43703 self.lv_pvs = {}
43704 self.lvs_hidden = {}
43705
43706 self.pv_path_to_uuid = {}
43707 self.vg_name_to_uuid = {}
43708 self.lv_full_name_to_uuid = {}
43709
43710 self.lvs_in_vgs = {}
43711 self.pvs_in_vgs = {}
43712
43713 # self.refresh()
43714 self.num_refreshes = 0
43715
43716 if usejson:
43717 self.json = cmdhandler.supports_json()
43718 else:
43719 self.json = usejson
43720
43721 @staticmethod
43722 def _insert_record(table, key, record, allowed_multiple):
43723 if key in table:
43724 existing = table[key]
43725
43726 for rec_k, rec_v in record.items():
43727 if rec_k in allowed_multiple:
43728 # This column name allows us to store multiple value for
43729 # each type
43730 if not isinstance(existing[rec_k], list):
43731 existing_value = existing[rec_k]
43732 existing[rec_k] = [existing_value, rec_v]
43733 else:
43734 existing[rec_k].append(rec_v)
43735 else:
43736 # If something is not expected to have changing values
43737 # lets ensure that
43738 if existing[rec_k] != rec_v:
43739 raise RuntimeError(
43740 "existing[%s]=%s != %s" %
43741 (rec_k, str(existing[rec_k]),
43742 str(rec_v)))
43743 else:
43744 table[key] = record
43745
43746 @staticmethod
43747 def _parse_pvs(_pvs):
43748 pvs = sorted(_pvs, key=lambda pk: pk['pv_name'])
43749
43750 c_pvs = OrderedDict()
43751 c_lookup = {}
43752 c_pvs_in_vgs = {}
43753
43754 for p in pvs:
43755 DataStore._insert_record(
43756 c_pvs, p['pv_uuid'], p,
43757 ['pvseg_start', 'pvseg_size', 'segtype'])
43758
43759 for p in c_pvs.values():
43760 # Capture which PVs are associated with which VG
43761 if p['vg_uuid'] not in c_pvs_in_vgs:
43762 c_pvs_in_vgs[p['vg_uuid']] = []
43763
43764 if p['vg_name']:
43765 c_pvs_in_vgs[p['vg_uuid']].append(
43766 (p['pv_name'], p['pv_uuid']))
43767
43768 # Lookup for translating between /dev/<name> and pv uuid
43769 c_lookup[p['pv_name']] = p['pv_uuid']
43770
43771 return c_pvs, c_lookup, c_pvs_in_vgs
43772
43773 @staticmethod
43774 def _parse_pvs_json(_all):
43775
43776 c_pvs = OrderedDict()
43777 c_lookup = {}
43778 c_pvs_in_vgs = {}
43779
43780 # Each item item in the report is a collection of information pertaining
43781 # to the vg
43782 for r in _all['report']:
43783 tmp_pv = []
43784
43785 # Get the pv data for this VG.
43786 if 'pv' in r:
43787 tmp_pv.extend(r['pv'])
43788
43789 # Sort them
43790 sorted_tmp_pv = sorted(tmp_pv, key=lambda pk: pk['pv_name'])
43791
43792 # Add them to result set
43793 for p in sorted_tmp_pv:
43794 c_pvs[p['pv_uuid']] = p
43795
43796 if 'pvseg' in r:
43797 for s in r['pvseg']:
43798 r = c_pvs[s['pv_uuid']]
43799 r.setdefault('pvseg_start', []).append(s['pvseg_start'])
43800 r.setdefault('pvseg_size', []).append(s['pvseg_size'])
43801 r.setdefault('segtype', []).append(s['segtype'])
43802
43803 # TODO: Remove this bug work around when we have orphan segs.
43804 for i in c_pvs.values():
43805 if 'pvseg_start' not in i:
43806 i['pvseg_start'] = '0'
43807 i['pvseg_size'] = i['pv_pe_count']
43808 i['segtype'] = 'free'
43809
43810 for p in c_pvs.values():
43811 # Capture which PVs are associated with which VG
43812 if p['vg_uuid'] not in c_pvs_in_vgs:
43813 c_pvs_in_vgs[p['vg_uuid']] = []
43814
43815 if p['vg_name']:
43816 c_pvs_in_vgs[p['vg_uuid']].append(
43817 (p['pv_name'], p['pv_uuid']))
43818
43819 # Lookup for translating between /dev/<name> and pv uuid
43820 c_lookup[p['pv_name']] = p['pv_uuid']
43821
43822 return c_pvs, c_lookup, c_pvs_in_vgs
43823
43824 @staticmethod
43825 def _parse_vgs(_vgs):
43826 vgs = sorted(_vgs, key=lambda vk: vk['vg_name'])
43827
43828 c_vgs = OrderedDict()
43829 c_lookup = {}
43830
43831 for i in vgs:
43832 c_lookup[i['vg_name']] = i['vg_uuid']
43833 DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
43834
43835 return c_vgs, c_lookup
43836
43837 @staticmethod
43838 def _parse_vgs_json(_all):
43839
43840 tmp_vg = []
43841 for r in _all['report']:
43842 # Get the pv data for this VG.
43843 if 'vg' in r:
43844 tmp_vg.extend(r['vg'])
43845
43846 # Sort for consistent output, however this is optional
43847 vgs = sorted(tmp_vg, key=lambda vk: vk['vg_name'])
43848
43849 c_vgs = OrderedDict()
43850 c_lookup = {}
43851
43852 for i in vgs:
43853 c_lookup[i['vg_name']] = i['vg_uuid']
43854 c_vgs[i['vg_uuid']] = i
43855
43856 return c_vgs, c_lookup
43857
43858 @staticmethod
43859 def _parse_lvs_common(c_lvs, c_lv_full_lookup):
43860
43861 c_lvs_in_vgs = OrderedDict()
43862 c_lvs_hidden = OrderedDict()
43863
43864 for i in c_lvs.values():
43865 if i['vg_uuid'] not in c_lvs_in_vgs:
43866 c_lvs_in_vgs[i['vg_uuid']] = []
43867
43868 c_lvs_in_vgs[
43869 i['vg_uuid']].append(
43870 (i['lv_name'],
43871 (i['lv_attr'], i['lv_layout'], i['lv_role']),
43872 i['lv_uuid']))
43873
43874 if i['lv_parent']:
43875 # Lookup what the parent refers too
43876 parent_name = i['lv_parent']
43877 full_parent_name = "%s/%s" % (i['vg_name'], parent_name)
43878 if full_parent_name not in c_lv_full_lookup:
43879 parent_name = '[%s]' % (parent_name)
43880 full_parent_name = "%s/%s" % (i['vg_name'], parent_name)
43881
43882 parent_uuid = c_lv_full_lookup[full_parent_name]
43883
43884 if parent_uuid not in c_lvs_hidden:
43885 c_lvs_hidden[parent_uuid] = []
43886
43887 c_lvs_hidden[parent_uuid].append(
43888 (i['lv_uuid'], i['lv_name']))
43889
43890 return c_lvs, c_lvs_in_vgs, c_lvs_hidden, c_lv_full_lookup
43891
43892 @staticmethod
43893 def _parse_lvs(_lvs):
43894 lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
43895
43896 c_lvs = OrderedDict()
43897 c_lv_full_lookup = OrderedDict()
43898
43899 for i in lvs:
43900 full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
43901 c_lv_full_lookup[full_name] = i['lv_uuid']
43902 DataStore._insert_record(
43903 c_lvs, i['lv_uuid'], i,
43904 ['seg_pe_ranges', 'segtype'])
43905
43906 return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
43907
43908 @staticmethod
43909 def _parse_lvs_json(_all):
43910
43911 c_lvs = OrderedDict()
43912 c_lv_full_lookup = {}
43913
43914 # Each item item in the report is a collection of information pertaining
43915 # to the vg
43916 for r in _all['report']:
43917 # Get the lv data for this VG.
43918 if 'lv' in r:
43919 # Add them to result set
43920 for i in r['lv']:
43921 full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
43922 c_lv_full_lookup[full_name] = i['lv_uuid']
43923 c_lvs[i['lv_uuid']] = i
43924
43925 # Add in the segment data
43926 if 'seg' in r:
43927 for s in r['seg']:
43928 r = c_lvs[s['lv_uuid']]
43929 r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges'])
43930 r.setdefault('segtype', []).append(s['segtype'])
43931
43932 return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
43933
43934 @staticmethod
43935 def _make_list(l):
43936 if not isinstance(l, list):
43937 l = [l]
43938 return l
43939
43940 @staticmethod
43941 def _parse_seg_entry(se, segtype):
43942 if se:
43943 # print("_parse_seg_entry %s %s" % (str(se), str(segtype)))
43944 device, segs = se.split(":")
43945 start, end = segs.split('-')
43946 return (device, (start, end), segtype)
43947 else:
43948 return ("", (), segtype)
43949
43950 @staticmethod
43951 def _build_segments(l, seg_types):
43952 rc = []
43953 l = DataStore._make_list(l)
43954 s = DataStore._make_list(seg_types)
43955
43956 assert len(l) == len(s)
43957 ls = list(zip(l, s))
43958
43959 for i in ls:
43960 if ' ' in i[0]:
43961 tmp = i[0].split(' ')
43962 for t in tmp:
43963 rc.append(DataStore._parse_seg_entry(t, i[1]))
43964 else:
43965 rc.append(DataStore._parse_seg_entry(*i))
43966 return rc
43967
43968 @staticmethod
43969 def _pv_device_lv_entry(table, pv_device, lv_uuid, meta, lv_attr,
43970 segment_info):
43971
43972 if pv_device not in table:
43973 table[pv_device] = {}
43974
43975 if lv_uuid not in table[pv_device]:
43976 table[pv_device][lv_uuid] = {}
43977 table[pv_device][lv_uuid]['segs'] = [segment_info]
43978 table[pv_device][lv_uuid]['name'] = meta
43979 table[pv_device][lv_uuid]['meta'] = lv_attr
43980 else:
43981 table[pv_device][lv_uuid]['segs'].append(segment_info)
43982
43983 @staticmethod
43984 def _pv_device_lv_format(pv_device_lvs):
43985 rc = {}
43986
43987 for pv_device, pd in pv_device_lvs.items():
43988 lvs = []
43989 for lv_uuid, ld in sorted(pd.items()):
43990 lvs.append((lv_uuid, ld['name'], ld['meta'], ld['segs']))
43991
43992 rc[pv_device] = lvs
43993 return rc
43994
43995 @staticmethod
43996 def _lvs_device_pv_entry(table, lv_uuid, pv_device, pv_uuid, segment_info):
43997 if lv_uuid not in table:
43998 table[lv_uuid] = {}
43999
44000 if pv_device not in table[lv_uuid]:
44001 table[lv_uuid][pv_device] = {}
44002 table[lv_uuid][pv_device]['segs'] = [segment_info]
44003 table[lv_uuid][pv_device]['pv_uuid'] = pv_uuid
44004 else:
44005 table[lv_uuid][pv_device]['segs'].append(segment_info)
44006
44007 @staticmethod
44008 def _lvs_device_pv_format(lvs_device_pvs):
44009 rc = {}
44010
44011 for lv_uuid, ld in lvs_device_pvs.items():
44012 pvs = []
44013 for pv_device, pd in sorted(ld.items()):
44014 pvs.append((pd['pv_uuid'], pv_device, pd['segs']))
44015
44016 rc[lv_uuid] = pvs
44017 return rc
44018
44019 def _parse_pv_in_lvs(self):
44020 pv_device_lvs = {} # What LVs are stored on a PV
44021 lvs_device_pv = {} # Where LV data is stored
44022
44023 for i in self.lvs.values():
44024 segs = self._build_segments(i['seg_pe_ranges'], i['segtype'])
44025 for s in segs:
44026 # We are referring to physical device
44027 if '/dev/' in s[0]:
44028 device, r, seg_type = s
44029
44030 DataStore._pv_device_lv_entry(
44031 pv_device_lvs, device, i['lv_uuid'], i['lv_name'],
44032 (i['lv_attr'], i['lv_layout'], i['lv_role']),
44033 (r[0], r[1], seg_type))
44034
44035 # (pv_name, pv_segs, pv_uuid)
44036 DataStore._lvs_device_pv_entry(
44037 lvs_device_pv, i['lv_uuid'], device,
44038 self.pv_path_to_uuid[device], (r[0], r[1], seg_type))
44039 else:
44040 # TODO Handle the case where the segments refer to a LV
44041 # and not a PV
44042 pass
44043 # print("Handle this %s %s %s" % (s[0], s[1], s[2]))
44044
44045 # Convert form to needed result for consumption
44046 pv_device_lvs_result = DataStore._pv_device_lv_format(pv_device_lvs)
44047 lvs_device_pv_result = DataStore._lvs_device_pv_format(lvs_device_pv)
44048
44049 return pv_device_lvs_result, lvs_device_pv_result
44050
44051 def refresh(self, log=True):
44052 """
44053 Go out and query lvm for the latest data in as few trips as possible
44054 :param log Add debug log entry/exit messages
44055 :return: None
44056 """
44057 self.num_refreshes += 1
44058 if log:
44059 log_debug("lvmdb - refresh entry")
44060
44061 # Grab everything first then parse it
44062 if self.json:
44063 # Do a single lvm retrieve for everything in json
44064 a = cmdhandler.lvm_full_report_json()
44065
44066 _pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
44067 _vgs, _vgs_lookup = self._parse_vgs_json(a)
44068 _lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
44069
44070 else:
44071 _raw_pvs = cmdhandler.pv_retrieve_with_segs()
44072 _raw_vgs = cmdhandler.vg_retrieve(None)
44073 _raw_lvs = cmdhandler.lv_retrieve_with_segments()
44074
44075 _pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
44076 _vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
44077 _lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
44078
44079 # Set all
44080 self.pvs = _pvs
44081 self.pv_path_to_uuid = _pvs_lookup
44082 self.vg_name_to_uuid = _vgs_lookup
44083 self.lv_full_name_to_uuid = _lvs_lookup
44084
44085 self.vgs = _vgs
44086 self.lvs = _lvs
44087 self.lvs_in_vgs = _lvs_in_vgs
44088 self.pvs_in_vgs = _pvs_in_vgs
44089 self.lvs_hidden = _lvs_hidden
44090
44091 # Create lookup table for which LV and segments are on each PV
44092 self.pv_lvs, self.lv_pvs = self._parse_pv_in_lvs()
44093
44094 if log:
44095 log_debug("lvmdb - refresh exit")
44096
44097 def fetch_pvs(self, pv_name):
44098 if not pv_name:
44099 return self.pvs.values()
44100 else:
44101 rc = []
44102 for s in pv_name:
44103 # Ths user could be using a symlink instead of the actual
44104 # block device, make sure we are using actual block device file
44105 # if the pv name isn't in the lookup
44106 if s not in self.pv_path_to_uuid:
44107 s = os.path.realpath(s)
44108 rc.append(self.pvs[self.pv_path_to_uuid[s]])
44109 return rc
44110
44111 def pv_missing(self, pv_uuid):
44112 if pv_uuid in self.pvs:
44113 if self.pvs[pv_uuid]['pv_missing'] == '':
44114 return False
44115 return True
44116
44117 def fetch_vgs(self, vg_name):
44118 if not vg_name:
44119 return self.vgs.values()
44120 else:
44121 rc = []
44122 for s in vg_name:
44123 rc.append(self.vgs[self.vg_name_to_uuid[s]])
44124 return rc
44125
44126 def fetch_lvs(self, lv_names):
44127 try:
44128 if not lv_names:
44129 return self.lvs.values()
44130 else:
44131 rc = []
44132 for s in lv_names:
44133 rc.append(self.lvs[self.lv_full_name_to_uuid[s]])
44134 return rc
44135 except KeyError as ke:
44136 log_error("Key %s not found!" % (str(lv_names)))
44137 log_error("lv name to uuid lookup")
44138 for keys in sorted(self.lv_full_name_to_uuid.keys()):
44139 log_error("%s" % (keys))
44140 log_error("lvs entries by uuid")
44141 for keys in sorted(self.lvs.keys()):
44142 log_error("%s" % (keys))
44143 raise ke
44144
44145 def pv_pe_segments(self, pv_uuid):
44146 pv = self.pvs[pv_uuid]
44147 return list(zip(pv['pvseg_start'], pv['pvseg_size']))
44148
44149 def pv_contained_lv(self, pv_device):
44150 rc = []
44151 if pv_device in self.pv_lvs:
44152 rc = self.pv_lvs[pv_device]
44153 return rc
44154
44155 def lv_contained_pv(self, lv_uuid):
44156 rc = []
44157 if lv_uuid in self.lv_pvs:
44158 rc = self.lv_pvs[lv_uuid]
44159 return rc
44160
44161 def lvs_in_vg(self, vg_uuid):
44162 # Return an array of
44163 # (lv_name, (lv_attr, lv_layout, lv_role), lv_uuid)
44164 rc = []
44165 if vg_uuid in self.lvs_in_vgs:
44166 rc = self.lvs_in_vgs[vg_uuid]
44167 return rc
44168
44169 def pvs_in_vg(self, vg_uuid):
44170 # Returns an array of (pv_name, pv_uuid)
44171 rc = []
44172 if vg_uuid in self.pvs_in_vgs:
44173 rc = self.pvs_in_vgs[vg_uuid]
44174 return rc
44175
44176 def hidden_lvs(self, lv_uuid):
44177 # For a specified LV, return a list of hidden lv_uuid, lv_name
44178 # for it
44179 rc = []
44180 if lv_uuid in self.lvs_hidden:
44181 rc = self.lvs_hidden[lv_uuid]
44182 return rc
44183
44184
44185if __name__ == "__main__":
44186 pp = prettyprint.PrettyPrinter(indent=4)
44187
44188 use_json = False
44189
44190 if len(sys.argv) != 1:
44191 print(len(sys.argv))
44192 use_json = True
44193
44194 ds = DataStore(use_json)
44195 ds.refresh()
44196
44197 print("PVS")
44198 for v in ds.pvs.values():
44199 pp.pprint(v)
44200 print('PV missing is %s' % ds.pv_missing(v['pv_uuid']))
44201
44202 print("VGS")
44203 for v in ds.vgs.values():
44204 pp.pprint(v)
44205
44206 print("LVS")
44207 for v in ds.lvs.values():
44208 pp.pprint(v)
44209
44210 print("LVS in VG")
44211 for k, v in ds.lvs_in_vgs.items():
44212 print("VG uuid = %s" % (k))
44213 pp.pprint(v)
44214
44215 print("pv_in_lvs")
44216 for k, v in ds.pv_lvs.items():
44217 print("PV %s contains LVS:" % (k))
44218 pp.pprint(v)
44219
44220 for k, v in ds.lv_pvs.items():
44221 print("LV device = %s" % (k))
44222 pp.pprint(v)
44223\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/request.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010056\013062740170\0022361\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
44224#
44225# This copyrighted material is made available to anyone wishing to use,
44226# modify, copy, or redistribute it subject to the terms and conditions
44227# of the GNU General Public License v.2.
44228#
44229# You should have received a copy of the GNU General Public License
44230# along with this program. If not, see <http://www.gnu.org/licenses/>.
44231
44232import threading
44233# noinspection PyUnresolvedReferences
44234from gi.repository import GLib
44235from .job import Job
44236from . import cfg
44237import traceback
44238from .utils import log_error, mt_async_result
44239
44240
44241class RequestEntry(object):
44242 def __init__(self, tmo, method, arguments, cb, cb_error,
44243 return_tuple=True, job_state=None):
44244 self.tmo = tmo
44245 self.method = method
44246 self.arguments = arguments
44247 self.cb = cb
44248 self.cb_error = cb_error
44249
44250 self.timer_id = -1
44251 self.lock = threading.RLock()
44252 self.done = False
44253 self._result = None
44254 self._job = None
44255 self._rc = 0
44256 self._rc_error = None
44257 self._return_tuple = return_tuple
44258 self._job_state = job_state
44259
44260 if self.tmo < 0:
44261 # Client is willing to block forever
44262 pass
44263 elif tmo == 0:
44264 self._return_job()
44265 else:
44266 self.timer_id = GLib.timeout_add_seconds(
44267 tmo, RequestEntry._request_timeout, self)
44268
44269 @staticmethod
44270 def _request_timeout(r):
44271 """
44272 Method which gets called when the timer runs out!
44273 :param r: RequestEntry which timed out
44274 :return: Nothing
44275 """
44276 r.timer_expired()
44277
44278 def _return_job(self):
44279 self._job = Job(self, self._job_state)
44280 cfg.om.register_object(self._job, True)
44281 if self._return_tuple:
44282 mt_async_result(self.cb, ('/', self._job.dbus_object_path()))
44283 else:
44284 mt_async_result(self.cb, self._job.dbus_object_path())
44285
44286 def run_cmd(self):
44287 try:
44288 result = self.method(*self.arguments)
44289 self.register_result(result)
44290 except Exception as e:
44291 # Use the request entry to return the result as the client may
44292 # have gotten a job by the time we hit an error
44293 # Lets get the stacktrace and set that to the error message
44294 st = traceback.format_exc()
44295 cfg.blackbox.dump()
44296 log_error("Exception returned to client: \n%s" % st)
44297 self.register_error(-1, str(e), e)
44298
44299 def is_done(self):
44300 with self.lock:
44301 rc = self.done
44302 return rc
44303
44304 def get_errors(self):
44305 with self.lock:
44306 return (self._rc, self._rc_error)
44307
44308 def result(self):
44309 with self.lock:
44310 if self.done:
44311 return self._result
44312 return '/'
44313
44314 def _reg_ending(self, result, error_rc=0, error_msg=None,
44315 error_exception=None):
44316 with self.lock:
44317 self.done = True
44318 if self.timer_id != -1:
44319 # Try to prevent the timer from firing
44320 GLib.source_remove(self.timer_id)
44321
44322 self._result = result
44323 self._rc = error_rc
44324 self._rc_error = error_msg
44325
44326 if not self._job:
44327 # We finished and there is no job, so return result or error
44328 # now!
44329 # Note: If we don't have a valid cb or cbe, this indicates a
44330 # request that doesn't need a response as we already returned
44331 # one before the request was processed.
44332 if error_rc == 0:
44333 if self.cb:
44334 if self._return_tuple:
44335 mt_async_result(self.cb, (result, '/'))
44336 else:
44337 mt_async_result(self.cb, result)
44338 else:
44339 if self.cb_error:
44340 if not error_exception:
44341 if not error_msg:
44342 error_exception = Exception(
44343 "An error occurred, but no reason was "
44344 "given, see service logs!")
44345 else:
44346 error_exception = Exception(error_msg)
44347
44348 mt_async_result(self.cb_error, error_exception)
44349 else:
44350 # We have a job and it's complete, indicate that it's done.
44351 self._job.Complete = True
44352 self._job = None
44353
44354 def register_error(self, error_rc, error_message, error_exception):
44355 self._reg_ending('/', error_rc, error_message, error_exception)
44356
44357 def register_result(self, result):
44358 self._reg_ending(result)
44359
44360 def timer_expired(self):
44361 with self.lock:
44362 # Set the timer back to -1 as we will get a warning if we try
44363 # to remove a timer that doesn't exist
44364 self.timer_id = -1
44365 if not self.done:
44366 # Create dbus job object and return path to caller
44367 self._return_job()
44368 else:
44369 # The job is done, we have nothing to do
44370 pass
44371
44372 return False
44373\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/cmdhandler.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000044274\013062740170\0023003\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
44374#
44375# This copyrighted material is made available to anyone wishing to use,
44376# modify, copy, or redistribute it subject to the terms and conditions
44377# of the GNU General Public License v.2.
44378#
44379# You should have received a copy of the GNU General Public License
44380# along with this program. If not, see <http://www.gnu.org/licenses/>.
44381
44382from subprocess import Popen, PIPE
44383import time
44384import threading
44385from itertools import chain
44386import collections
44387import traceback
44388import os
44389
44390from lvmdbusd import cfg
44391from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error
44392from lvmdbusd.lvm_shell_proxy import LVMShellProxy
44393
44394try:
44395 import simplejson as json
44396except ImportError:
44397 import json
44398
44399SEP = '{|}'
44400
44401total_time = 0.0
44402total_count = 0
44403
44404# We need to prevent different threads from using the same lvm shell
44405# at the same time.
44406cmd_lock = threading.RLock()
44407
44408
44409class LvmExecutionMeta(object):
44410
44411 def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
44412 self.start = start
44413 self.ended = ended
44414 self.cmd = cmd
44415 self.ec = ec
44416 self.stdout_txt = stdout_txt
44417 self.stderr_txt = stderr_txt
44418
44419 def __str__(self):
44420 return "EC= %d for %s\n" \
44421 "STARTED: %f, ENDED: %f\n" \
44422 "STDOUT=%s\n" \
44423 "STDERR=%s\n" % \
44424 (self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
44425 self.stderr_txt)
44426
44427
44428class LvmFlightRecorder(object):
44429
44430 def __init__(self, size=16):
44431 self.queue = collections.deque(maxlen=size)
44432
44433 def add(self, lvm_exec_meta):
44434 self.queue.append(lvm_exec_meta)
44435
44436 def dump(self):
44437 with cmd_lock:
44438 if len(self.queue):
44439 log_error("LVM dbus flight recorder START")
44440 for c in self.queue:
44441 log_error(str(c))
44442 log_error("LVM dbus flight recorder END")
44443
44444
44445cfg.blackbox = LvmFlightRecorder()
44446
44447
44448def _debug_c(cmd, exit_code, out):
44449 log_error('CMD= %s' % ' '.join(cmd))
44450 log_error(("EC= %d" % exit_code))
44451 log_error(("STDOUT=\n %s\n" % out[0]))
44452 log_error(("STDERR=\n %s\n" % out[1]))
44453
44454
44455def call_lvm(command, debug=False):
44456 """
44457 Call an executable and return a tuple of exitcode, stdout, stderr
44458 :param command: Command to execute
44459 :param debug: Dump debug to stdout
44460 """
44461 # print 'STACK:'
44462 # for line in traceback.format_stack():
44463 # print line.strip()
44464
44465 # Prepend the full lvm executable so that we can run different versions
44466 # in different locations on the same box
44467 command.insert(0, cfg.LVM_CMD)
44468
44469 process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
44470 env=os.environ)
44471 out = process.communicate()
44472
44473 stdout_text = bytes(out[0]).decode("utf-8")
44474 stderr_text = bytes(out[1]).decode("utf-8")
44475
44476 if debug or process.returncode != 0:
44477 _debug_c(command, process.returncode, (stdout_text, stderr_text))
44478
44479 return process.returncode, stdout_text, stderr_text
44480
44481# The actual method which gets called to invoke the lvm command, can vary
44482# from forking a new process to using lvm shell
44483_t_call = call_lvm
44484
44485
44486def _shell_cfg():
44487 global _t_call
44488 # noinspection PyBroadException
44489 try:
44490 lvm_shell = LVMShellProxy()
44491 _t_call = lvm_shell.call_lvm
44492 cfg.SHELL_IN_USE = lvm_shell
44493 return True
44494 except Exception:
44495 _t_call = call_lvm
44496 cfg.SHELL_IN_USE = None
44497 log_error(traceback.format_exc())
44498 log_error("Unable to utilize lvm shell, dropping back to fork & exec")
44499 return False
44500
44501
44502def set_execution(shell):
44503 global _t_call
44504 with cmd_lock:
44505 # If the user requested lvm shell and we are currently setup that
44506 # way, just return
44507 if cfg.SHELL_IN_USE and shell:
44508 return True
44509 else:
44510 if not shell and cfg.SHELL_IN_USE:
44511 cfg.SHELL_IN_USE.exit_shell()
44512 cfg.SHELL_IN_USE = None
44513
44514 _t_call = call_lvm
44515 if shell:
44516 if cfg.args.use_json:
44517 return _shell_cfg()
44518 else:
44519 return False
44520 return True
44521
44522
44523def time_wrapper(command, debug=False):
44524 global total_time
44525 global total_count
44526
44527 with cmd_lock:
44528 start = time.time()
44529 results = _t_call(command, debug)
44530 ended = time.time()
44531 total_time += (ended - start)
44532 total_count += 1
44533 cfg.blackbox.add(LvmExecutionMeta(start, ended, command, *results))
44534 return results
44535
44536
44537call = time_wrapper
44538
44539
44540# Default cmd
44541# Place default arguments for every command here.
44542def _dc(cmd, args):
44543 c = [cmd, '--noheading', '--separator', '%s' % SEP, '--nosuffix',
44544 '--unbuffered', '--units', 'b']
44545 c.extend(args)
44546 return c
44547
44548
44549def parse(out):
44550 rc = []
44551
44552 for line in out.split('\n'):
44553 # This line includes separators, so process them
44554 if SEP in line:
44555 elem = line.split(SEP)
44556 cleaned_elem = []
44557 for e in elem:
44558 e = e.strip()
44559 cleaned_elem.append(e)
44560
44561 if len(cleaned_elem) > 1:
44562 rc.append(cleaned_elem)
44563 else:
44564 t = line.strip()
44565 if len(t) > 0:
44566 rc.append(t)
44567 return rc
44568
44569
44570def parse_column_names(out, column_names):
44571 lines = parse(out)
44572 rc = []
44573
44574 for i in range(0, len(lines)):
44575 d = dict(list(zip(column_names, lines[i])))
44576 rc.append(d)
44577
44578 return rc
44579
44580
44581def options_to_cli_args(options):
44582 rc = []
44583 for k, v in list(dict(options).items()):
44584 if k.startswith("-"):
44585 rc.append(k)
44586 else:
44587 rc.append("--%s" % k)
44588 if v != "":
44589 rc.append(str(v))
44590 return rc
44591
44592
44593def pv_remove(device, remove_options):
44594 cmd = ['pvremove']
44595 cmd.extend(options_to_cli_args(remove_options))
44596 cmd.append(device)
44597 return call(cmd)
44598
44599
44600def _qt(tag_name):
44601 return '@%s' % tag_name
44602
44603
44604def _tag(operation, what, add, rm, tag_options):
44605 cmd = [operation]
44606 cmd.extend(options_to_cli_args(tag_options))
44607
44608 if isinstance(what, list):
44609 cmd.extend(what)
44610 else:
44611 cmd.append(what)
44612
44613 if add:
44614 cmd.extend(list(chain.from_iterable(
44615 ('--addtag', _qt(x)) for x in add)))
44616 if rm:
44617 cmd.extend(list(chain.from_iterable(
44618 ('--deltag', _qt(x)) for x in rm)))
44619
44620 return call(cmd, False)
44621
44622
44623def pv_tag(pv_devices, add, rm, tag_options):
44624 return _tag('pvchange', pv_devices, add, rm, tag_options)
44625
44626
44627def vg_tag(vg_name, add, rm, tag_options):
44628 return _tag('vgchange', vg_name, add, rm, tag_options)
44629
44630
44631def lv_tag(lv_name, add, rm, tag_options):
44632 return _tag('lvchange', lv_name, add, rm, tag_options)
44633
44634
44635def vg_rename(vg, new_name, rename_options):
44636 cmd = ['vgrename']
44637 cmd.extend(options_to_cli_args(rename_options))
44638 cmd.extend([vg, new_name])
44639 return call(cmd)
44640
44641
44642def vg_remove(vg_name, remove_options):
44643 cmd = ['vgremove']
44644 cmd.extend(options_to_cli_args(remove_options))
44645 cmd.extend(['-f', vg_name])
44646 return call(cmd)
44647
44648
44649def vg_lv_create(vg_name, create_options, name, size_bytes, pv_dests):
44650 cmd = ['lvcreate']
44651 cmd.extend(options_to_cli_args(create_options))
44652 cmd.extend(['--size', str(size_bytes) + 'B'])
44653 cmd.extend(['--name', name, vg_name])
44654 pv_dest_ranges(cmd, pv_dests)
44655 return call(cmd)
44656
44657
44658def vg_lv_snapshot(vg_name, snapshot_options, name, size_bytes):
44659 cmd = ['lvcreate']
44660 cmd.extend(options_to_cli_args(snapshot_options))
44661 cmd.extend(["-s"])
44662
44663 if size_bytes != 0:
44664 cmd.extend(['--size', str(size_bytes) + 'B'])
44665
44666 cmd.extend(['--name', name, vg_name])
44667 return call(cmd)
44668
44669
44670def vg_lv_create_linear(vg_name, create_options, name, size_bytes, thin_pool):
44671 cmd = ['lvcreate']
44672 cmd.extend(options_to_cli_args(create_options))
44673
44674 if not thin_pool:
44675 cmd.extend(['--size', str(size_bytes) + 'B'])
44676 else:
44677 cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
44678 cmd.extend(['--name', name, vg_name])
44679 return call(cmd)
44680
44681
44682def vg_lv_create_striped(vg_name, create_options, name, size_bytes,
44683 num_stripes, stripe_size_kb, thin_pool):
44684 cmd = ['lvcreate']
44685 cmd.extend(options_to_cli_args(create_options))
44686
44687 if not thin_pool:
44688 cmd.extend(['--size', str(size_bytes) + 'B'])
44689 else:
44690 cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
44691
44692 cmd.extend(['--stripes', str(num_stripes)])
44693
44694 if stripe_size_kb != 0:
44695 cmd.extend(['--stripesize', str(stripe_size_kb)])
44696
44697 cmd.extend(['--name', name, vg_name])
44698 return call(cmd)
44699
44700
44701def _vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
44702 num_stripes, stripe_size_kb):
44703 cmd = ['lvcreate']
44704
44705 cmd.extend(options_to_cli_args(create_options))
44706
44707 cmd.extend(['--type', raid_type])
44708 cmd.extend(['--size', str(size_bytes) + 'B'])
44709
44710 if num_stripes != 0:
44711 cmd.extend(['--stripes', str(num_stripes)])
44712
44713 if stripe_size_kb != 0:
44714 cmd.extend(['--stripesize', str(stripe_size_kb)])
44715
44716 cmd.extend(['--name', name, vg_name])
44717 return call(cmd)
44718
44719
44720def vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
44721 num_stripes, stripe_size_kb):
44722 cmd = ['lvcreate']
44723 cmd.extend(options_to_cli_args(create_options))
44724
44725 return _vg_lv_create_raid(vg_name, create_options, name, raid_type,
44726 size_bytes, num_stripes, stripe_size_kb)
44727
44728
44729def vg_lv_create_mirror(
44730 vg_name, create_options, name, size_bytes, num_copies):
44731 cmd = ['lvcreate']
44732 cmd.extend(options_to_cli_args(create_options))
44733
44734 cmd.extend(['--type', 'mirror'])
44735 cmd.extend(['--mirrors', str(num_copies)])
44736 cmd.extend(['--size', str(size_bytes) + 'B'])
44737 cmd.extend(['--name', name, vg_name])
44738 return call(cmd)
44739
44740
44741def vg_create_cache_pool(md_full_name, data_full_name, create_options):
44742 cmd = ['lvconvert']
44743 cmd.extend(options_to_cli_args(create_options))
44744 cmd.extend(['--type', 'cache-pool', '--force', '-y',
44745 '--poolmetadata', md_full_name, data_full_name])
44746 return call(cmd)
44747
44748
44749def vg_create_thin_pool(md_full_name, data_full_name, create_options):
44750 cmd = ['lvconvert']
44751 cmd.extend(options_to_cli_args(create_options))
44752 cmd.extend(['--type', 'thin-pool', '--force', '-y',
44753 '--poolmetadata', md_full_name, data_full_name])
44754 return call(cmd)
44755
44756
44757def lv_remove(lv_path, remove_options):
44758 cmd = ['lvremove']
44759 cmd.extend(options_to_cli_args(remove_options))
44760 cmd.extend(['-f', lv_path])
44761 return call(cmd)
44762
44763
44764def lv_rename(lv_path, new_name, rename_options):
44765 cmd = ['lvrename']
44766 cmd.extend(options_to_cli_args(rename_options))
44767 cmd.extend([lv_path, new_name])
44768 return call(cmd)
44769
44770
44771def lv_resize(lv_full_name, size_change, pv_dests,
44772 resize_options):
44773 cmd = ['lvresize', '--force']
44774
44775 cmd.extend(options_to_cli_args(resize_options))
44776
44777 if size_change < 0:
44778 cmd.append("-L-%dB" % (-size_change))
44779 else:
44780 cmd.append("-L+%dB" % (size_change))
44781
44782 cmd.append(lv_full_name)
44783 pv_dest_ranges(cmd, pv_dests)
44784 return call(cmd)
44785
44786
44787def lv_lv_create(lv_full_name, create_options, name, size_bytes):
44788 cmd = ['lvcreate']
44789 cmd.extend(options_to_cli_args(create_options))
44790 cmd.extend(['--virtualsize', str(size_bytes) + 'B', '-T'])
44791 cmd.extend(['--name', name, lv_full_name])
44792 return call(cmd)
44793
44794
44795def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
44796 # lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
44797 cmd = ['lvconvert']
44798 cmd.extend(options_to_cli_args(cache_options))
44799 cmd.extend(['-y', '--type', 'cache', '--cachepool',
44800 cache_pool_full_name, lv_full_name])
44801 return call(cmd)
44802
44803
44804def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
44805 cmd = ['lvconvert']
44806 if destroy_cache:
44807 option = '--uncache'
44808 else:
44809 # Currently fairly dangerous
44810 # see: https://bugzilla.redhat.com/show_bug.cgi?id=1248972
44811 option = '--splitcache'
44812 cmd.extend(options_to_cli_args(detach_options))
44813 # needed to prevent interactive questions
44814 cmd.extend(["--yes", "--force"])
44815 cmd.extend([option, lv_full_name])
44816 return call(cmd)
44817
44818
44819def supports_json():
44820 cmd = ['help']
44821 rc, out, err = call(cmd)
44822 if rc == 0:
44823 if cfg.SHELL_IN_USE:
44824 return True
44825 else:
44826 if 'fullreport' in err:
44827 return True
44828 return False
44829
44830
44831def lvm_full_report_json():
44832 pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
44833 'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
44834 'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
44835 'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
44836 'vg_uuid', 'pv_missing']
44837
44838 pv_seg_columns = ['pvseg_start', 'pvseg_size', 'segtype',
44839 'pv_uuid', 'lv_uuid', 'pv_name']
44840
44841 vg_columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
44842 'vg_sysid', 'vg_extent_size', 'vg_extent_count',
44843 'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
44844 'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
44845 'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
44846 'vg_mda_used_count', 'vg_attr', 'vg_tags']
44847
44848 lv_columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
44849 'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
44850 'origin', 'data_percent',
44851 'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
44852 'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout',
44853 'snap_percent', 'metadata_percent', 'copy_percent',
44854 'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
44855
44856 lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
44857
44858 cmd = _dc('fullreport', [
44859 '-a', # Need hidden too
44860 '--configreport', 'pv', '-o', ','.join(pv_columns),
44861 '--configreport', 'vg', '-o', ','.join(vg_columns),
44862 '--configreport', 'lv', '-o', ','.join(lv_columns),
44863 '--configreport', 'seg', '-o', ','.join(lv_seg_columns),
44864 '--configreport', 'pvseg', '-o', ','.join(pv_seg_columns),
44865 '--reportformat', 'json'
44866 ])
44867
44868 rc, out, err = call(cmd)
44869 if rc == 0:
44870 # With the current implementation, if we are using the shell then we
44871 # are using JSON and JSON is returned back to us as it was parsed to
44872 # figure out if we completed OK or not
44873 if cfg.SHELL_IN_USE:
44874 assert(type(out) == dict)
44875 return out
44876 else:
44877 return json.loads(out)
44878 return None
44879
44880
44881def pv_retrieve_with_segs(device=None):
44882 d = []
44883 err = ""
44884 out = ""
44885 rc = 0
44886
44887 columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
44888 'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
44889 'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
44890 'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
44891 'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
44892
44893 # Lvm has some issues where it returns failure when querying pvs when other
44894 # operations are in process, see:
44895 # https://bugzilla.redhat.com/show_bug.cgi?id=1274085
44896 for i in range(0, 10):
44897 cmd = _dc('pvs', ['-o', ','.join(columns)])
44898
44899 if device:
44900 cmd.extend(device)
44901
44902 rc, out, err = call(cmd)
44903
44904 if rc == 0:
44905 d = parse_column_names(out, columns)
44906 break
44907 else:
44908 time.sleep(0.2)
44909 log_debug("LVM Bug workaround, retrying pvs command...")
44910
44911 if rc != 0:
44912 msg = "We were unable to get pvs to return without error after " \
44913 "trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
44914 (rc, err, out)
44915 log_error(msg)
44916 raise RuntimeError(msg)
44917
44918 return d
44919
44920
44921def pv_resize(device, size_bytes, create_options):
44922 cmd = ['pvresize']
44923
44924 cmd.extend(options_to_cli_args(create_options))
44925
44926 if size_bytes != 0:
44927 cmd.extend(['--setphysicalvolumesize', str(size_bytes) + 'B'])
44928
44929 cmd.extend([device])
44930 return call(cmd)
44931
44932
44933def pv_create(create_options, devices):
44934 cmd = ['pvcreate', '-ff']
44935 cmd.extend(options_to_cli_args(create_options))
44936 cmd.extend(devices)
44937 return call(cmd)
44938
44939
44940def pv_allocatable(device, yes, allocation_options):
44941 yn = 'n'
44942
44943 if yes:
44944 yn = 'y'
44945
44946 cmd = ['pvchange']
44947 cmd.extend(options_to_cli_args(allocation_options))
44948 cmd.extend(['-x', yn, device])
44949 return call(cmd)
44950
44951
44952def pv_scan(activate, cache, device_paths, major_minors, scan_options):
44953 cmd = ['pvscan']
44954 cmd.extend(options_to_cli_args(scan_options))
44955
44956 if activate:
44957 cmd.extend(['--activate', "ay"])
44958
44959 if cache:
44960 cmd.append('--cache')
44961
44962 if len(device_paths) > 0:
44963 for d in device_paths:
44964 cmd.append(d)
44965
44966 if len(major_minors) > 0:
44967 for mm in major_minors:
44968 cmd.append("%s:%s" % (mm))
44969
44970 return call(cmd)
44971
44972
44973def vg_create(create_options, pv_devices, name):
44974 cmd = ['vgcreate']
44975 cmd.extend(options_to_cli_args(create_options))
44976 cmd.append(name)
44977 cmd.extend(pv_devices)
44978 return call(cmd)
44979
44980
44981def vg_change(change_options, name):
44982 cmd = ['vgchange']
44983 cmd.extend(options_to_cli_args(change_options))
44984 cmd.append(name)
44985 return call(cmd)
44986
44987
44988def vg_reduce(vg_name, missing, pv_devices, reduce_options):
44989 cmd = ['vgreduce']
44990 cmd.extend(options_to_cli_args(reduce_options))
44991
44992 if len(pv_devices) == 0:
44993 cmd.append('--all')
44994 if missing:
44995 cmd.append('--removemissing')
44996
44997 cmd.append(vg_name)
44998 cmd.extend(pv_devices)
44999 return call(cmd)
45000
45001
45002def vg_extend(vg_name, extend_devices, extend_options):
45003 cmd = ['vgextend']
45004 cmd.extend(options_to_cli_args(extend_options))
45005 cmd.append(vg_name)
45006 cmd.extend(extend_devices)
45007 return call(cmd)
45008
45009
45010def _vg_value_set(name, arguments, options):
45011 cmd = ['vgchange']
45012 cmd.extend(options_to_cli_args(options))
45013 cmd.append(name)
45014 cmd.extend(arguments)
45015 return call(cmd)
45016
45017
45018def vg_allocation_policy(vg_name, policy, policy_options):
45019 return _vg_value_set(vg_name, ['--alloc', policy], policy_options)
45020
45021
45022def vg_max_pv(vg_name, number, max_options):
45023 return _vg_value_set(vg_name, ['--maxphysicalvolumes', str(number)],
45024 max_options)
45025
45026
45027def vg_max_lv(vg_name, number, max_options):
45028 return _vg_value_set(vg_name, ['-l', str(number)], max_options)
45029
45030
45031def vg_uuid_gen(vg_name, ignore, options):
45032 assert ignore is None
45033 return _vg_value_set(vg_name, ['--uuid'], options)
45034
45035
45036def activate_deactivate(op, name, activate, control_flags, options):
45037 cmd = [op]
45038 cmd.extend(options_to_cli_args(options))
45039
45040 op = '-a'
45041
45042 if control_flags:
45043 # Autoactivation
45044 if (1 << 0) & control_flags:
45045 op += 'a'
45046 # Exclusive locking (Cluster)
45047 if (1 << 1) & control_flags:
45048 op += 'e'
45049
45050 # Local node activation
45051 if (1 << 2) & control_flags:
45052 op += 'l'
45053
45054 # Activation modes
45055 if (1 << 3) & control_flags:
45056 cmd.extend(['--activationmode', 'complete'])
45057 elif (1 << 4) & control_flags:
45058 cmd.extend(['--activationmode', 'partial'])
45059
45060 # Ignore activation skip
45061 if (1 << 5) & control_flags:
45062 cmd.append('--ignoreactivationskip')
45063
45064 if activate:
45065 op += 'y'
45066 else:
45067 op += 'n'
45068
45069 cmd.append(op)
45070 cmd.append(name)
45071 return call(cmd)
45072
45073
45074def vg_retrieve(vg_specific):
45075 if vg_specific:
45076 assert isinstance(vg_specific, list)
45077
45078 columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
45079 'vg_sysid', 'vg_extent_size', 'vg_extent_count',
45080 'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
45081 'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
45082 'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
45083 'vg_mda_used_count', 'vg_attr', 'vg_tags']
45084
45085 cmd = _dc('vgs', ['-o', ','.join(columns)])
45086
45087 if vg_specific:
45088 cmd.extend(vg_specific)
45089
45090 d = []
45091 rc, out, err = call(cmd)
45092 if rc == 0:
45093 d = parse_column_names(out, columns)
45094
45095 return d
45096
45097
45098def lv_retrieve_with_segments():
45099 columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
45100 'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
45101 'origin', 'data_percent',
45102 'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
45103 'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
45104 'lv_role', 'lv_layout',
45105 'snap_percent', 'metadata_percent', 'copy_percent',
45106 'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
45107
45108 cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
45109 rc, out, err = call(cmd)
45110
45111 d = []
45112
45113 if rc == 0:
45114 d = parse_column_names(out, columns)
45115
45116 return d
45117
45118
45119if __name__ == '__main__':
45120 pv_data = pv_retrieve_with_segs()
45121
45122 for p in pv_data:
45123 print(str(p))
45124\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmdbusd/job.py\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013412\013062740170\0021442\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
45125#
45126# This copyrighted material is made available to anyone wishing to use,
45127# modify, copy, or redistribute it subject to the terms and conditions
45128# of the GNU General Public License v.2.
45129#
45130# You should have received a copy of the GNU General Public License
45131# along with this program. If not, see <http://www.gnu.org/licenses/>.
45132
45133from .automatedproperties import AutomatedProperties
45134from .utils import job_obj_path_generate, mt_async_result, mt_run_no_wait
45135from . import cfg
45136from .cfg import JOB_INTERFACE
45137import dbus
45138import threading
45139# noinspection PyUnresolvedReferences
45140from gi.repository import GLib
45141
45142
45143# Class that handles a client waiting for something to be complete. We either
45144# get a timeout or the operation is done.
45145class WaitingClient(object):
45146
45147 # A timeout occurred
45148 @staticmethod
45149 def _timeout(wc):
45150 with wc.rlock:
45151 if wc.in_use:
45152 wc.in_use = False
45153 # Remove ourselves from waiting client
45154 wc.job_state.remove_waiting_client(wc)
45155 wc.timer_id = -1
45156 mt_async_result(wc.cb, wc.job_state.Complete)
45157 wc.job_state = None
45158
45159 def __init__(self, job_state, tmo, cb, cbe):
45160 self.rlock = threading.RLock()
45161 self.job_state = job_state
45162 self.cb = cb
45163 self.cbe = cbe
45164 self.in_use = True # Indicates if object is in play
45165 self.timer_id = -1
45166 if tmo > 0:
45167 self.timer_id = GLib.timeout_add_seconds(
45168 tmo, WaitingClient._timeout, self)
45169
45170 # The job finished before the timer popped and we are being notified that
45171 # it's done
45172 def notify(self):
45173 with self.rlock:
45174 if self.in_use:
45175 self.in_use = False
45176 # Clear timer
45177 if self.timer_id != -1:
45178 GLib.source_remove(self.timer_id)
45179 self.timer_id = -1
45180
45181 mt_async_result(self.cb, self.job_state.Complete)
45182 self.job_state = None
45183
45184
45185# noinspection PyPep8Naming
45186class JobState(object):
45187 def __init__(self, request=None):
45188 self.rlock = threading.RLock()
45189
45190 self._percent = 0
45191 self._complete = False
45192 self._request = request
45193 self._ec = 0
45194 self._stderr = ''
45195 self._waiting_clients = []
45196
45197 # This is an lvm command that is just taking too long and doesn't
45198 # support background operation
45199 if self._request:
45200 # Faking the percentage when we don't have one
45201 self._percent = 1
45202
45203 @property
45204 def Percent(self):
45205 with self.rlock:
45206 return self._percent
45207
45208 @Percent.setter
45209 def Percent(self, value):
45210 with self.rlock:
45211 self._percent = value
45212
45213 @property
45214 def Complete(self):
45215 with self.rlock:
45216 if self._request:
45217 self._complete = self._request.is_done()
45218
45219 return self._complete
45220
45221 @Complete.setter
45222 def Complete(self, value):
45223 with self.rlock:
45224 self._complete = value
45225 self._percent = 100
45226 self.notify_waiting_clients()
45227
45228 @property
45229 def GetError(self):
45230 with self.rlock:
45231 if self.Complete:
45232 if self._request:
45233 (rc, error) = self._request.get_errors()
45234 return (rc, str(error))
45235 else:
45236 return (self._ec, self._stderr)
45237 else:
45238 return (-1, 'Job is not complete!')
45239
45240 def dtor(self):
45241 with self.rlock:
45242 self._request = None
45243
45244 @property
45245 def Result(self):
45246 with self.rlock:
45247 if self._request:
45248 return self._request.result()
45249 return '/'
45250
45251 def add_waiting_client(self, client):
45252 with self.rlock:
45253 # Avoid race condition where it goes complete before we get added
45254 # to the list of waiting clients
45255 if self.Complete:
45256 client.notify()
45257 else:
45258 self._waiting_clients.append(client)
45259
45260 def remove_waiting_client(self, client):
45261 # If a waiting client timer pops before the job is done we will allow
45262 # the client to remove themselves from the list. As we have a lock
45263 # here and a lock in the waiting client too, and they can be obtained
45264 # in different orders, a dead lock can occur.
45265 # As this remove is really optional, we will try to acquire the lock
45266 # and remove. If we are unsuccessful it's not fatal, we just delay
45267 # the time when the objects can be garbage collected by python
45268 if self.rlock.acquire(False):
45269 try:
45270 self._waiting_clients.remove(client)
45271 finally:
45272 self.rlock.release()
45273
45274 def notify_waiting_clients(self):
45275 with self.rlock:
45276 for c in self._waiting_clients:
45277 c.notify()
45278
45279 self._waiting_clients = []
45280
45281
45282# noinspection PyPep8Naming
45283class Job(AutomatedProperties):
45284 _Percent_meta = ('d', JOB_INTERFACE)
45285 _Complete_meta = ('b', JOB_INTERFACE)
45286 _Result_meta = ('o', JOB_INTERFACE)
45287 _GetError_meta = ('(is)', JOB_INTERFACE)
45288
45289 def __init__(self, request, job_state=None):
45290 super(Job, self).__init__(job_obj_path_generate())
45291 self.set_interface(JOB_INTERFACE)
45292
45293 if job_state:
45294 self.state = job_state
45295 else:
45296 self.state = JobState(request)
45297
45298 @property
45299 def Percent(self):
45300 return dbus.Double(float(self.state.Percent))
45301
45302 @property
45303 def Complete(self):
45304 return dbus.Boolean(self.state.Complete)
45305
45306 @staticmethod
45307 def _signal_complete(obj):
45308 obj.PropertiesChanged(
45309 JOB_INTERFACE, dict(Complete=dbus.Boolean(obj.state.Complete)), [])
45310
45311 @Complete.setter
45312 def Complete(self, value):
45313 self.state.Complete = value
45314 mt_run_no_wait(Job._signal_complete, self)
45315
45316 @property
45317 def GetError(self):
45318 return dbus.Struct(self.state.GetError, signature="(is)")
45319
45320 @dbus.service.method(dbus_interface=JOB_INTERFACE)
45321 def Remove(self):
45322 if self.state.Complete:
45323 cfg.om.remove_object(self, True)
45324 self.state.dtor()
45325 else:
45326 raise dbus.exceptions.DBusException(
45327 JOB_INTERFACE, 'Job is not complete!')
45328
45329 @dbus.service.method(dbus_interface=JOB_INTERFACE,
45330 in_signature='i',
45331 out_signature='b',
45332 async_callbacks=('cb', 'cbe'))
45333 def Wait(self, timeout, cb, cbe):
45334 if timeout == 0 or self.state.Complete:
45335 cb(dbus.Boolean(self.state.Complete))
45336 else:
45337 self.state.add_waiting_client(
45338 WaitingClient(self.state, timeout, cb, cbe))
45339
45340 @property
45341 def Result(self):
45342 return dbus.ObjectPath(self.state.Result)
45343
45344 @property
45345 def lvm_id(self):
45346 return str(id(self))
45347
45348 @property
45349 def Uuid(self):
45350 import uuid
45351 return uuid.uuid1()
45352\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0017602\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005062\013062740170\0021652\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
45353# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
45354#
45355# This file is part of LVM2.
45356#
45357# This copyrighted material is made available to anyone wishing to use,
45358# modify, copy, or redistribute it subject to the terms and conditions
45359# of the GNU General Public License v.2.
45360#
45361# You should have received a copy of the GNU General Public License
45362# along with this program; if not, write to the Free Software Foundation,
45363# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45364
45365srcdir = @srcdir@
45366top_srcdir = @top_srcdir@
45367top_builddir = @top_builddir@
45368
45369CMAN_LIBS = @CMAN_LIBS@
45370CMAN_CFLAGS = @CMAN_CFLAGS@
45371CMAP_LIBS = @CMAP_LIBS@
45372CMAP_CFLAGS = @CMAP_CFLAGS@
45373CONFDB_LIBS = @CONFDB_LIBS@
45374CONFDB_CFLAGS = @CONFDB_CFLAGS@
45375CPG_LIBS = @CPG_LIBS@
45376CPG_CFLAGS = @CPG_CFLAGS@
45377DLM_LIBS = @DLM_LIBS@
45378DLM_CFLAGS = @DLM_CFLAGS@
45379QUORUM_LIBS = @QUORUM_LIBS@
45380QUORUM_CFLAGS = @QUORUM_CFLAGS@
45381SALCK_LIBS = @SALCK_LIBS@
45382SALCK_CFLAGS = @SALCK_CFLAGS@
45383
45384SOURCES = \
45385 clvmd-command.c \
45386 clvmd.c \
45387 lvm-functions.c \
45388 refresh_clvmd.c
45389
45390ifneq (,$(findstring cman,, "@CLVMD@,"))
45391 SOURCES += clvmd-cman.c
45392 LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
45393 CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
45394 DEFS += -DUSE_CMAN
45395endif
45396
45397ifneq (,$(findstring openais,, "@CLVMD@,"))
45398 SOURCES += clvmd-openais.c
45399 LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
45400 CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
45401 DEFS += -DUSE_OPENAIS
45402endif
45403
45404ifneq (,$(findstring corosync,, "@CLVMD@,"))
45405 SOURCES += clvmd-corosync.c
45406 LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
45407 CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
45408 DEFS += -DUSE_COROSYNC
45409endif
45410
45411ifneq (,$(findstring singlenode,, &quot;@CLVMD@,&quot;))
45412 SOURCES += clvmd-singlenode.c
45413 DEFS += -DUSE_SINGLENODE
45414endif
45415
45416ifeq ($(MAKECMDGOALS),distclean)
45417 SOURCES += clvmd-cman.c
45418 SOURCES += clvmd-openais.c
45419 SOURCES += clvmd-corosync.c
45420 SOURCES += clvmd-singlenode.c
45421endif
45422
45423TARGETS = \
45424 clvmd
45425
45426LVMLIBS = $(LVMINTERNAL_LIBS)
45427
45428ifeq ("@DMEVENTD@", "yes")
45429 LVMLIBS += -ldevmapper-event
45430endif
45431
45432include $(top_builddir)/make.tmpl
45433
45434LVMLIBS += -ldevmapper
45435LIBS += $(PTHREAD_LIBS)
45436
45437CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
45438LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
45439
45440INSTALL_TARGETS = \
45441 install_clvmd
45442
45443clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
45444 $(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
45445 $(LVMLIBS) $(LMLIBS) $(LIBS)
45446
45447.PHONY: install_clvmd
45448
45449install_clvmd: $(TARGETS)
45450 $(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
45451
45452install: $(INSTALL_TARGETS)
45453
45454install_cluster: $(INSTALL_TARGETS)
45455\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/refresh_clvmd.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000021674\013062740170\0022603\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
45456 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
45457 * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
45458 *
45459 * This file is part of LVM2.
45460 *
45461 * This copyrighted material is made available to anyone wishing to use,
45462 * modify, copy, or redistribute it subject to the terms and conditions
45463 * of the GNU General Public License v.2.
45464 *
45465 * You should have received a copy of the GNU General Public License
45466 * along with this program; if not, write to the Free Software Foundation,
45467 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45468 */
45469
45470/* FIXME Remove duplicated functions from this file. */
45471
45472/*
45473 * Send a command to a running clvmd from the command-line
45474 */
45475
45476#include "clvmd-common.h"
45477
45478#include "clvm.h"
45479#include "refresh_clvmd.h"
45480
45481#include <stddef.h>
45482#include <sys/socket.h>
45483#include <sys/un.h>
45484
45485typedef struct lvm_response {
45486 char node[255];
45487 char *response;
45488 int status;
45489 int len;
45490} lvm_response_t;
45491
45492/*
45493 * This gets stuck at the start of memory we allocate so we
45494 * can sanity-check it at deallocation time
45495 */
45496#define LVM_SIGNATURE 0x434C564D
45497
45498static int _clvmd_sock = -1;
45499
45500/* Open connection to the clvm daemon */
45501static int _open_local_sock(void)
45502{
45503 int local_socket;
45504 struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
45505
45506 if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
45507 fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME);
45508 return -1;
45509 }
45510
45511 /* Open local socket */
45512 if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
45513 fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
45514 return -1;
45515 }
45516
45517 if (connect(local_socket,(struct sockaddr *) &sockaddr,
45518 sizeof(sockaddr))) {
45519 int saved_errno = errno;
45520
45521 fprintf(stderr, "connect() failed on local socket: %s\n",
45522 strerror(errno));
45523 if (close(local_socket))
45524 return -1;
45525
45526 errno = saved_errno;
45527 return -1;
45528 }
45529
45530 return local_socket;
45531}
45532
45533/* Send a request and return the status */
45534static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
45535{
45536 char outbuf[PIPE_BUF];
45537 struct clvm_header *outheader = (struct clvm_header *) outbuf;
45538 int len;
45539 unsigned off;
45540 int buflen;
45541 int err;
45542
45543 /* Send it to CLVMD */
45544 rewrite:
45545 if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
45546 if (err == -1 && errno == EINTR)
45547 goto rewrite;
45548 fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
45549 return 0;
45550 }
45551 if (no_response)
45552 return 1;
45553
45554 /* Get the response */
45555 reread:
45556 if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
45557 if (errno == EINTR)
45558 goto reread;
45559 fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
45560 return 0;
45561 }
45562
45563 if (len == 0) {
45564 fprintf(stderr, "EOF reading CLVMD");
45565 errno = ENOTCONN;
45566 return 0;
45567 }
45568
45569 /* Allocate buffer */
45570 buflen = len + outheader->arglen;
45571 *retbuf = dm_malloc(buflen);
45572 if (!*retbuf) {
45573 errno = ENOMEM;
45574 return 0;
45575 }
45576
45577 /* Copy the header */
45578 memcpy(*retbuf, outbuf, len);
45579 outheader = (struct clvm_header *) *retbuf;
45580
45581 /* Read the returned values */
45582 off = 1; /* we've already read the first byte */
45583 while (off <= outheader->arglen && len > 0) {
45584 len = read(_clvmd_sock, outheader->args + off,
45585 buflen - off - offsetof(struct clvm_header, args));
45586 if (len > 0)
45587 off += len;
45588 }
45589
45590 /* Was it an error ? */
45591 if (outheader->status != 0) {
45592 errno = outheader->status;
45593
45594 /* Only return an error here if there are no node-specific
45595 errors present in the message that might have more detail */
45596 if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
45597 fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
45598 return 0;
45599 }
45600
45601 }
45602
45603 return 1;
45604}
45605
45606/* Build the structure header and parse-out wildcard node names */
45607static void _build_header(struct clvm_header *head, int cmd, const char *node,
45608 unsigned int len)
45609{
45610 head->cmd = cmd;
45611 head->status = 0;
45612 head->flags = 0;
45613 head->xid = 0;
45614 head->clientid = 0;
45615 if (len)
45616 /* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
45617 head->arglen = len - 1;
45618 else {
45619 head->arglen = 0;
45620 *head->args = '\0';
45621 }
45622
45623 /*
45624 * Translate special node names.
45625 */
45626 if (!node || !strcmp(node, NODE_ALL))
45627 head->node[0] = '\0';
45628 else if (!strcmp(node, NODE_LOCAL)) {
45629 head->node[0] = '\0';
45630 head->flags = CLVMD_FLAG_LOCAL;
45631 } else
45632 strcpy(head->node, node);
45633}
45634
45635/*
45636 * Send a message to a(or all) node(s) in the cluster and wait for replies
45637 */
45638static int _cluster_request(char cmd, const char *node, void *data, int len,
45639 lvm_response_t ** response, int *num, int no_response)
45640{
45641 char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
45642 char *inptr;
45643 char *retbuf = NULL;
45644 int status;
45645 int i;
45646 int num_responses = 0;
45647 struct clvm_header *head = (struct clvm_header *) outbuf;
45648 lvm_response_t *rarray;
45649
45650 *num = 0;
45651
45652 if (_clvmd_sock == -1)
45653 _clvmd_sock = _open_local_sock();
45654
45655 if (_clvmd_sock == -1)
45656 return 0;
45657
45658 _build_header(head, cmd, node, len);
45659 if (len)
45660 memcpy(head->node + strlen(head->node) + 1, data, len);
45661
45662 status = _send_request(outbuf, sizeof(struct clvm_header) +
45663 strlen(head->node) + len, &retbuf, no_response);
45664 if (!status || no_response)
45665 goto out;
45666
45667 /* Count the number of responses we got */
45668 head = (struct clvm_header *) retbuf;
45669 inptr = head->args;
45670 while (inptr[0]) {
45671 num_responses++;
45672 inptr += strlen(inptr) + 1;
45673 inptr += sizeof(int);
45674 inptr += strlen(inptr) + 1;
45675 }
45676
45677 /*
45678 * Allocate response array.
45679 * With an extra pair of INTs on the front to sanity
45680 * check the pointer when we are given it back to free
45681 */
45682 *response = NULL;
45683 if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses +
45684 sizeof(int) * 2))) {
45685 errno = ENOMEM;
45686 status = 0;
45687 goto out;
45688 }
45689
45690 /* Unpack the response into an lvm_response_t array */
45691 inptr = head->args;
45692 i = 0;
45693 while (inptr[0]) {
45694 strcpy(rarray[i].node, inptr);
45695 inptr += strlen(inptr) + 1;
45696
45697 memcpy(&rarray[i].status, inptr, sizeof(int));
45698 inptr += sizeof(int);
45699
45700 rarray[i].response = dm_malloc(strlen(inptr) + 1);
45701 if (rarray[i].response == NULL) {
45702 /* Free up everything else and return error */
45703 int j;
45704 for (j = 0; j < i; j++)
45705 dm_free(rarray[i].response);
45706 dm_free(rarray);
45707 errno = ENOMEM;
45708 status = 0;
45709 goto out;
45710 }
45711
45712 strcpy(rarray[i].response, inptr);
45713 rarray[i].len = strlen(inptr);
45714 inptr += strlen(inptr) + 1;
45715 i++;
45716 }
45717 *num = num_responses;
45718 *response = rarray;
45719
45720 out:
45721 dm_free(retbuf);
45722
45723 return status;
45724}
45725
45726/* Free reply array */
45727static int _cluster_free_request(lvm_response_t * response, int num)
45728{
45729 int i;
45730
45731 for (i = 0; i < num; i++) {
45732 dm_free(response[i].response);
45733 }
45734
45735 dm_free(response);
45736
45737 return 1;
45738}
45739
45740int refresh_clvmd(int all_nodes)
45741{
45742 int num_responses;
45743 char args[1]; // No args really.
45744 lvm_response_t *response = NULL;
45745 int saved_errno;
45746 int status;
45747 int i;
45748
45749 status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
45750
45751 /* If any nodes were down then display them and return an error */
45752 for (i = 0; i < num_responses; i++) {
45753 if (response[i].status == EHOSTDOWN) {
45754 fprintf(stderr, "clvmd not running on node %s",
45755 response[i].node);
45756 status = 0;
45757 errno = response[i].status;
45758 } else if (response[i].status) {
45759 fprintf(stderr, "Error resetting node %s: %s",
45760 response[i].node,
45761 response[i].response[0] ?
45762 response[i].response :
45763 strerror(response[i].status));
45764 status = 0;
45765 errno = response[i].status;
45766 }
45767 }
45768
45769 saved_errno = errno;
45770 _cluster_free_request(response, num_responses);
45771 errno = saved_errno;
45772
45773 return status;
45774}
45775
45776int restart_clvmd(int all_nodes)
45777{
45778 int dummy, status;
45779
45780 status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
45781
45782 /*
45783 * FIXME: we cannot receive response, clvmd re-exec before it.
45784 * but also should not close socket too early (the whole rq is dropped then).
45785 * FIXME: This should be handled this way:
45786 * - client waits for RESTART ack (and socket close)
45787 * - server restarts
45788 * - client checks that server is ready again (VERSION command?)
45789 */
45790 usleep(500000);
45791
45792 return status;
45793}
45794
45795int debug_clvmd(int level, int clusterwide)
45796{
45797 int num_responses;
45798 char args[1];
45799 const char *nodes;
45800 lvm_response_t *response = NULL;
45801 int saved_errno;
45802 int status;
45803 int i;
45804
45805 args[0] = level;
45806 if (clusterwide)
45807 nodes = NODE_ALL;
45808 else
45809 nodes = NODE_LOCAL;
45810
45811 status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
45812
45813 /* If any nodes were down then display them and return an error */
45814 for (i = 0; i < num_responses; i++) {
45815 if (response[i].status == EHOSTDOWN) {
45816 fprintf(stderr, "clvmd not running on node %s",
45817 response[i].node);
45818 status = 0;
45819 errno = response[i].status;
45820 } else if (response[i].status) {
45821 fprintf(stderr, "Error setting debug on node %s: %s",
45822 response[i].node,
45823 response[i].response[0] ?
45824 response[i].response :
45825 strerror(response[i].status));
45826 status = 0;
45827 errno = response[i].status;
45828 }
45829 }
45830
45831 saved_errno = errno;
45832 _cluster_free_request(response, num_responses);
45833 errno = saved_errno;
45834
45835 return status;
45836}
45837\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-command.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000025677\013062740170\0022510\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
45838 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
45839 * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
45840 *
45841 * This file is part of LVM2.
45842 *
45843 * This copyrighted material is made available to anyone wishing to use,
45844 * modify, copy, or redistribute it subject to the terms and conditions
45845 * of the GNU General Public License v.2.
45846 *
45847 * You should have received a copy of the GNU General Public License
45848 * along with this program; if not, write to the Free Software Foundation,
45849 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45850 */
45851
45852/*
45853
45854 CLVMD Cluster LVM daemon command processor.
45855
45856 To add commands to the daemon simply add a processor in do_command and return
45857 and messages back in buf and the length in *retlen. The initial value of
45858 buflen is the maximum size of the buffer. if buf is not large enough then it
45859 may be reallocated by the functions in here to a suitable size bearing in
45860 mind that anything larger than the passed-in size will have to be returned
45861 using the system LV and so performance will suffer.
45862
45863 The status return will be negated and passed back to the originating node.
45864
45865 pre- and post- command routines are called only on the local node. The
45866 purpose is primarily to get and release locks, though the pre- routine should
45867 also do any other local setups required by the command (if any) and can
45868 return a failure code that prevents the command from being distributed around
45869 the cluster
45870
45871 The pre- and post- routines are run in their own thread so can block as long
45872 they like, do_command is run in the main clvmd thread so should not block for
45873 too long. If the pre-command returns an error code (!=0) then the command
45874 will not be propogated around the cluster but the post-command WILL be called
45875
45876 Also note that the pre and post routine are *always* called on the local
45877 node, even if the command to be executed was only requested to run on a
45878 remote node. It may peek inside the client structure to check the status of
45879 the command.
45880
45881 The clients of the daemon must, naturally, understand the return messages and
45882 codes.
45883
45884 Routines in here may only READ the values in the client structure passed in
45885 apart from client->private which they are free to do what they like with.
45886
45887*/
45888
45889#include "clvmd-common.h"
45890#include "clvmd-comms.h"
45891#include "clvm.h"
45892#include "clvmd.h"
45893#include "lvm-globals.h"
45894#include "lvm-functions.h"
45895
45896#include "locking.h"
45897
45898#include <sys/utsname.h>
45899
45900extern struct cluster_ops *clops;
45901static int restart_clvmd(void);
45902
45903/* This is where all the real work happens:
45904 NOTE: client will be NULL when this is executed on a remote node */
45905int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
45906 char **buf, int buflen, int *retlen)
45907{
45908 char *args = msg->node + strlen(msg->node) + 1;
45909 int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
45910 int status = 0;
45911 char *lockname;
45912 const char *locktype;
45913 struct utsname nodeinfo;
45914 unsigned char lock_cmd;
45915 unsigned char lock_flags;
45916
45917 /* Do the command */
45918 switch (msg->cmd) {
45919 /* Just a test message */
45920 case CLVMD_CMD_TEST:
45921 if (arglen > buflen) {
45922 char *new_buf;
45923 buflen = arglen + 200;
45924 new_buf = realloc(*buf, buflen);
45925 if (new_buf == NULL) {
45926 status = errno;
45927 free (*buf);
45928 }
45929 *buf = new_buf;
45930 }
45931 if (*buf) {
45932 if (uname(&nodeinfo))
45933 memset(&nodeinfo, 0, sizeof(nodeinfo));
45934
45935 *retlen = 1 + dm_snprintf(*buf, buflen,
45936 "TEST from %s: %s v%s",
45937 nodeinfo.nodename, args,
45938 nodeinfo.release);
45939 }
45940 break;
45941
45942 case CLVMD_CMD_LOCK_VG:
45943 lock_cmd = args[0];
45944 lock_flags = args[1];
45945 lockname = &args[2];
45946 /* Check to see if the VG is in use by LVM1 */
45947 status = do_check_lvm1(lockname);
45948 do_lock_vg(lock_cmd, lock_flags, lockname);
45949 break;
45950
45951 case CLVMD_CMD_LOCK_LV:
45952 /* This is the biggie */
45953 lock_cmd = args[0];
45954 lock_flags = args[1];
45955 lockname = &args[2];
45956 status = do_lock_lv(lock_cmd, lock_flags, lockname);
45957 /* Replace EIO with something less scary */
45958 if (status == EIO) {
45959 *retlen = 1 + dm_snprintf(*buf, buflen, "%s",
45960 get_last_lvm_error());
45961 return EIO;
45962 }
45963 break;
45964
45965 case CLVMD_CMD_LOCK_QUERY:
45966 lockname = &args[2];
45967 if (buflen < 3)
45968 return EIO;
45969 if ((locktype = do_lock_query(lockname)))
45970 *retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
45971 break;
45972
45973 case CLVMD_CMD_REFRESH:
45974 do_refresh_cache();
45975 break;
45976
45977 case CLVMD_CMD_SYNC_NAMES:
45978 lvm_do_fs_unlock();
45979 break;
45980
45981 case CLVMD_CMD_SET_DEBUG:
45982 clvmd_set_debug((debug_t) args[0]);
45983 break;
45984
45985 case CLVMD_CMD_RESTART:
45986 status = restart_clvmd();
45987 break;
45988
45989 case CLVMD_CMD_GET_CLUSTERNAME:
45990 status = clops->get_cluster_name(*buf, buflen);
45991 if (!status)
45992 *retlen = strlen(*buf)+1;
45993 break;
45994
45995 case CLVMD_CMD_VG_BACKUP:
45996 /*
45997 * Do not run backup on local node, caller should do that.
45998 */
45999 if (!client)
46000 lvm_do_backup(&args[2]);
46001 break;
46002
46003 default:
46004 /* Won't get here because command is validated in pre_command */
46005 break;
46006 }
46007
46008 /* Check the status of the command and return the error text */
46009 if (status) {
46010 *retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
46011 strerror(status)) : -1);
46012 }
46013
46014 return status;
46015}
46016
46017static int lock_vg(struct local_client *client)
46018{
46019 struct dm_hash_table *lock_hash;
46020 struct clvm_header *header =
46021 (struct clvm_header *) client->bits.localsock.cmd;
46022 unsigned char lock_cmd;
46023 int lock_mode;
46024 char *args = header->node + strlen(header->node) + 1;
46025 int lkid;
46026 int status;
46027 char *lockname;
46028
46029 /*
46030 * Keep a track of VG locks in our own hash table. In current
46031 * practice there should only ever be more than two VGs locked
46032 * if a user tries to merge lots of them at once
46033 */
46034 if (!client->bits.localsock.private) {
46035 if (!(lock_hash = dm_hash_create(3)))
46036 return ENOMEM;
46037 client->bits.localsock.private = (void *) lock_hash;
46038 } else
46039 lock_hash = (struct dm_hash_table *) client->bits.localsock.private;
46040
46041 lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
46042 lock_mode = ((int) lock_cmd & LCK_TYPE_MASK);
46043 /* lock_flags = args[1]; */
46044 lockname = &args[2];
46045 DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
46046
46047 if (lock_mode == LCK_UNLOCK) {
46048 if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
46049 return EINVAL;
46050
46051 if ((status = sync_unlock(lockname, lkid)))
46052 status = errno;
46053 else
46054 dm_hash_remove(lock_hash, lockname);
46055 } else {
46056 /* Read locks need to be PR; other modes get passed through */
46057 if (lock_mode == LCK_READ)
46058 lock_mode = LCK_PREAD;
46059
46060 if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid)))
46061 status = errno;
46062 else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid))
46063 return ENOMEM;
46064 }
46065
46066 return status;
46067}
46068
46069
46070/* Pre-command is a good place to get locks that are needed only for the duration
46071 of the commands around the cluster (don't forget to free them in post-command),
46072 and to sanity check the command arguments */
46073int do_pre_command(struct local_client *client)
46074{
46075 struct clvm_header *header =
46076 (struct clvm_header *) client->bits.localsock.cmd;
46077 unsigned char lock_cmd;
46078 unsigned char lock_flags;
46079 char *args = header->node + strlen(header->node) + 1;
46080 int lockid = 0;
46081 int status = 0;
46082 char *lockname;
46083
46084 switch (header->cmd) {
46085 case CLVMD_CMD_TEST:
46086 status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
46087 client->bits.localsock.private = (void *)(long)lockid;
46088 break;
46089
46090 case CLVMD_CMD_LOCK_VG:
46091 lockname = &args[2];
46092 /* We take out a real lock unless LCK_CACHE was set */
46093 if (!strncmp(lockname, "V_", 2) ||
46094 !strncmp(lockname, "P_#", 3))
46095 status = lock_vg(client);
46096 break;
46097
46098 case CLVMD_CMD_LOCK_LV:
46099 lock_cmd = args[0];
46100 lock_flags = args[1];
46101 lockname = &args[2];
46102 status = pre_lock_lv(lock_cmd, lock_flags, lockname);
46103 break;
46104
46105 case CLVMD_CMD_REFRESH:
46106 case CLVMD_CMD_GET_CLUSTERNAME:
46107 case CLVMD_CMD_SET_DEBUG:
46108 case CLVMD_CMD_VG_BACKUP:
46109 case CLVMD_CMD_SYNC_NAMES:
46110 case CLVMD_CMD_LOCK_QUERY:
46111 case CLVMD_CMD_RESTART:
46112 break;
46113
46114 default:
46115 log_error("Unknown command %d received\n", header->cmd);
46116 status = EINVAL;
46117 }
46118 return status;
46119}
46120
46121/* Note that the post-command routine is called even if the pre-command or the real command
46122 failed */
46123int do_post_command(struct local_client *client)
46124{
46125 struct clvm_header *header =
46126 (struct clvm_header *) client->bits.localsock.cmd;
46127 int status = 0;
46128 unsigned char lock_cmd;
46129 unsigned char lock_flags;
46130 char *args = header->node + strlen(header->node) + 1;
46131 char *lockname;
46132
46133 switch (header->cmd) {
46134 case CLVMD_CMD_TEST:
46135 status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
46136 client->bits.localsock.private = NULL;
46137 break;
46138
46139 case CLVMD_CMD_LOCK_LV:
46140 lock_cmd = args[0];
46141 lock_flags = args[1];
46142 lockname = &args[2];
46143 status = post_lock_lv(lock_cmd, lock_flags, lockname);
46144 break;
46145
46146 default:
46147 /* Nothing to do here */
46148 break;
46149 }
46150 return status;
46151}
46152
46153
46154/* Called when the client is about to be deleted */
46155void cmd_client_cleanup(struct local_client *client)
46156{
46157 struct dm_hash_node *v;
46158 struct dm_hash_table *lock_hash;
46159 int lkid;
46160 char *lockname;
46161
46162 DEBUGLOG("Client thread cleanup (%p)\n", client);
46163 if (!client->bits.localsock.private)
46164 return;
46165
46166 lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
46167
46168 dm_hash_iterate(v, lock_hash) {
46169 lkid = (int)(long)dm_hash_get_data(lock_hash, v);
46170 lockname = dm_hash_get_key(lock_hash, v);
46171 DEBUGLOG("Cleanup (%p): Unlocking lock %s %x\n", client, lockname, lkid);
46172 (void) sync_unlock(lockname, lkid);
46173 }
46174
46175 dm_hash_destroy(lock_hash);
46176 client->bits.localsock.private = NULL;
46177}
46178
46179static int restart_clvmd(void)
46180{
46181 const char **argv;
46182 char *lv_name;
46183 int argc = 0, max_locks = 0;
46184 struct dm_hash_node *hn = NULL;
46185 char debug_arg[16];
46186 const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
46187
46188 DEBUGLOG("clvmd restart requested\n");
46189
46190 /* Count exclusively-open LVs */
46191 do {
46192 hn = get_next_excl_lock(hn, &lv_name);
46193 if (lv_name) {
46194 max_locks++;
46195 if (!*lv_name)
46196 break; /* FIXME: Is this error ? */
46197 }
46198 } while (hn);
46199
46200 /* clvmd + locks (-E uuid) + debug (-d X) + NULL */
46201 if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv))))
46202 goto_out;
46203
46204 /*
46205 * Build the command-line
46206 */
46207 argv[argc++] = "clvmd";
46208
46209 /* Propagate debug options */
46210 if (clvmd_get_debug()) {
46211 if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
46212 goto_out;
46213 argv[argc++] = debug_arg;
46214 }
46215
46216 /* Propagate foreground options */
46217 if (clvmd_get_foreground())
46218 argv[argc++] = "-f";
46219
46220 argv[argc++] = "-I";
46221 argv[argc++] = clops->name;
46222
46223 /* Now add the exclusively-open LVs */
46224 hn = NULL;
46225 do {
46226 hn = get_next_excl_lock(hn, &lv_name);
46227 if (lv_name) {
46228 if (!*lv_name)
46229 break; /* FIXME: Is this error ? */
46230 argv[argc++] = "-E";
46231 argv[argc++] = lv_name;
46232 DEBUGLOG("excl lock: %s\n", lv_name);
46233 }
46234 } while (hn);
46235 argv[argc] = NULL;
46236
46237 /* Exec new clvmd */
46238 DEBUGLOG("--- Restarting %s ---\n", clvmd);
46239 for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
46240
46241 /* NOTE: This will fail when downgrading! */
46242 execvp(clvmd, (char **)argv);
46243out:
46244 /* We failed */
46245 DEBUGLOG("Restart of clvmd failed.\n");
46246
46247 free(argv);
46248
46249 return EIO;
46250}
46251\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-corosync.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000036527\013062740170\0022725\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
46252 * Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
46253 *
46254 * This file is part of LVM2.
46255 *
46256 * This copyrighted material is made available to anyone wishing to use,
46257 * modify, copy, or redistribute it subject to the terms and conditions
46258 * of the GNU Lesser General Public License v.2.1.
46259 *
46260 * You should have received a copy of the GNU Lesser General Public License
46261 * along with this program; if not, write to the Free Software Foundation,
46262 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
46263 */
46264
46265/*
46266 * This provides the interface between clvmd and corosync/DLM as the cluster
46267 * and lock manager.
46268 */
46269
46270#include "clvmd-common.h"
46271
46272#include <pthread.h>
46273
46274#include "clvm.h"
46275#include "clvmd-comms.h"
46276#include "clvmd.h"
46277#include "lvm-functions.h"
46278
46279#include "locking.h"
46280
46281#include <corosync/cpg.h>
46282#include <corosync/quorum.h>
46283
46284#ifdef HAVE_COROSYNC_CONFDB_H
46285# include <corosync/confdb.h>
46286#elif defined HAVE_COROSYNC_CMAP_H
46287# include <corosync/cmap.h>
46288#else
46289# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
46290#endif
46291
46292#include <libdlm.h>
46293
46294#include <syslog.h>
46295
46296/* Timeout value for several corosync calls */
46297#define LOCKSPACE_NAME "clvmd"
46298
46299static void corosync_cpg_deliver_callback (cpg_handle_t handle,
46300 const struct cpg_name *groupName,
46301 uint32_t nodeid,
46302 uint32_t pid,
46303 void *msg,
46304 size_t msg_len);
46305static void corosync_cpg_confchg_callback(cpg_handle_t handle,
46306 const struct cpg_name *groupName,
46307 const struct cpg_address *member_list, size_t member_list_entries,
46308 const struct cpg_address *left_list, size_t left_list_entries,
46309 const struct cpg_address *joined_list, size_t joined_list_entries);
46310static void _cluster_closedown(void);
46311
46312/* Hash list of nodes in the cluster */
46313static struct dm_hash_table *node_hash;
46314
46315/* Number of active nodes */
46316static int num_nodes;
46317static unsigned int our_nodeid;
46318
46319static struct local_client *cluster_client;
46320
46321/* Corosync handles */
46322static cpg_handle_t cpg_handle;
46323static quorum_handle_t quorum_handle;
46324
46325/* DLM Handle */
46326static dlm_lshandle_t *lockspace;
46327
46328static struct cpg_name cpg_group_name;
46329
46330/* Corosync callback structs */
46331cpg_callbacks_t corosync_cpg_callbacks = {
46332 .cpg_deliver_fn = corosync_cpg_deliver_callback,
46333 .cpg_confchg_fn = corosync_cpg_confchg_callback,
46334};
46335
46336quorum_callbacks_t quorum_callbacks = {
46337 .quorum_notify_fn = NULL,
46338};
46339
46340struct node_info
46341{
46342 enum {NODE_DOWN, NODE_CLVMD} state;
46343 int nodeid;
46344};
46345
46346
46347/* Set errno to something approximating the right value and return 0 or -1 */
46348static int cs_to_errno(cs_error_t err)
46349{
46350 switch(err)
46351 {
46352 case CS_OK:
46353 return 0;
46354 case CS_ERR_LIBRARY:
46355 errno = EINVAL;
46356 break;
46357 case CS_ERR_VERSION:
46358 errno = EINVAL;
46359 break;
46360 case CS_ERR_INIT:
46361 errno = EINVAL;
46362 break;
46363 case CS_ERR_TIMEOUT:
46364 errno = ETIME;
46365 break;
46366 case CS_ERR_TRY_AGAIN:
46367 errno = EAGAIN;
46368 break;
46369 case CS_ERR_INVALID_PARAM:
46370 errno = EINVAL;
46371 break;
46372 case CS_ERR_NO_MEMORY:
46373 errno = ENOMEM;
46374 break;
46375 case CS_ERR_BAD_HANDLE:
46376 errno = EINVAL;
46377 break;
46378 case CS_ERR_BUSY:
46379 errno = EBUSY;
46380 break;
46381 case CS_ERR_ACCESS:
46382 errno = EPERM;
46383 break;
46384 case CS_ERR_NOT_EXIST:
46385 errno = ENOENT;
46386 break;
46387 case CS_ERR_NAME_TOO_LONG:
46388 errno = ENAMETOOLONG;
46389 break;
46390 case CS_ERR_EXIST:
46391 errno = EEXIST;
46392 break;
46393 case CS_ERR_NO_SPACE:
46394 errno = ENOSPC;
46395 break;
46396 case CS_ERR_INTERRUPT:
46397 errno = EINTR;
46398 break;
46399 case CS_ERR_NAME_NOT_FOUND:
46400 errno = ENOENT;
46401 break;
46402 case CS_ERR_NO_RESOURCES:
46403 errno = ENOMEM;
46404 break;
46405 case CS_ERR_NOT_SUPPORTED:
46406 errno = EOPNOTSUPP;
46407 break;
46408 case CS_ERR_BAD_OPERATION:
46409 errno = EINVAL;
46410 break;
46411 case CS_ERR_FAILED_OPERATION:
46412 errno = EIO;
46413 break;
46414 case CS_ERR_MESSAGE_ERROR:
46415 errno = EIO;
46416 break;
46417 case CS_ERR_QUEUE_FULL:
46418 errno = EXFULL;
46419 break;
46420 case CS_ERR_QUEUE_NOT_AVAILABLE:
46421 errno = EINVAL;
46422 break;
46423 case CS_ERR_BAD_FLAGS:
46424 errno = EINVAL;
46425 break;
46426 case CS_ERR_TOO_BIG:
46427 errno = E2BIG;
46428 break;
46429 case CS_ERR_NO_SECTIONS:
46430 errno = ENOMEM;
46431 break;
46432 default:
46433 errno = EINVAL;
46434 break;
46435 }
46436 return -1;
46437}
46438
46439static char *print_corosync_csid(const char *csid)
46440{
46441 static char buf[128];
46442 int id;
46443
46444 memcpy(&id, csid, sizeof(int));
46445 sprintf(buf, "%d", id);
46446 return buf;
46447}
46448
46449static void corosync_cpg_deliver_callback (cpg_handle_t handle,
46450 const struct cpg_name *groupName,
46451 uint32_t nodeid,
46452 uint32_t pid,
46453 void *msg,
46454 size_t msg_len)
46455{
46456 int target_nodeid;
46457
46458 memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
46459
46460 DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
46461 our_nodeid, nodeid, target_nodeid, msg_len-4);
46462
46463 if (nodeid != our_nodeid)
46464 if (target_nodeid == our_nodeid || target_nodeid == 0)
46465 process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
46466 msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
46467}
46468
46469static void corosync_cpg_confchg_callback(cpg_handle_t handle,
46470 const struct cpg_name *groupName,
46471 const struct cpg_address *member_list, size_t member_list_entries,
46472 const struct cpg_address *left_list, size_t left_list_entries,
46473 const struct cpg_address *joined_list, size_t joined_list_entries)
46474{
46475 int i;
46476 struct node_info *ninfo;
46477
46478 DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
46479 joined_list_entries, left_list_entries, member_list_entries);
46480
46481 for (i=0; i<joined_list_entries; i++) {
46482 ninfo = dm_hash_lookup_binary(node_hash,
46483 (char *)&joined_list[i].nodeid,
46484 COROSYNC_CSID_LEN);
46485 if (!ninfo) {
46486 ninfo = malloc(sizeof(struct node_info));
46487 if (!ninfo) {
46488 break;
46489 }
46490 else {
46491 ninfo->nodeid = joined_list[i].nodeid;
46492 dm_hash_insert_binary(node_hash,
46493 (char *)&ninfo->nodeid,
46494 COROSYNC_CSID_LEN, ninfo);
46495 }
46496 }
46497 ninfo->state = NODE_CLVMD;
46498 }
46499
46500 for (i=0; i<left_list_entries; i++) {
46501 ninfo = dm_hash_lookup_binary(node_hash,
46502 (char *)&left_list[i].nodeid,
46503 COROSYNC_CSID_LEN);
46504 if (ninfo)
46505 ninfo->state = NODE_DOWN;
46506 }
46507
46508 num_nodes = member_list_entries;
46509}
46510
46511static int _init_cluster(void)
46512{
46513 cs_error_t err;
46514
46515#ifdef QUORUM_SET /* corosync/quorum.h */
46516 uint32_t quorum_type;
46517#endif
46518
46519 node_hash = dm_hash_create(100);
46520
46521 err = cpg_initialize(&cpg_handle,
46522 &corosync_cpg_callbacks);
46523 if (err != CS_OK) {
46524 syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
46525 err);
46526 DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
46527 return cs_to_errno(err);
46528 }
46529
46530#ifdef QUORUM_SET
46531 err = quorum_initialize(&quorum_handle,
46532 &quorum_callbacks,
46533 &quorum_type);
46534
46535 if (quorum_type != QUORUM_SET) {
46536 syslog(LOG_ERR, "Corosync quorum service is not configured");
46537 DEBUGLOG("Corosync quorum service is not configured");
46538 return EINVAL;
46539 }
46540#else
46541 err = quorum_initialize(&quorum_handle,
46542 &quorum_callbacks);
46543#endif
46544
46545 if (err != CS_OK) {
46546 syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
46547 err);
46548 DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
46549 return cs_to_errno(err);
46550 }
46551
46552 /* Create a lockspace for LV & VG locks to live in */
46553 lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
46554 if (!lockspace) {
46555 lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
46556 if (!lockspace) {
46557 syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
46558 return -1;
46559 }
46560 DEBUGLOG("Created DLM lockspace for CLVMD.\n");
46561 } else
46562 DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
46563
46564 dlm_ls_pthread_init(lockspace);
46565 DEBUGLOG("DLM initialisation complete\n");
46566
46567 /* Connect to the clvmd group */
46568 strcpy((char *)cpg_group_name.value, "clvmd");
46569 cpg_group_name.length = strlen((char *)cpg_group_name.value);
46570 err = cpg_join(cpg_handle, &cpg_group_name);
46571 if (err != CS_OK) {
46572 cpg_finalize(cpg_handle);
46573 quorum_finalize(quorum_handle);
46574 dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
46575 syslog(LOG_ERR, "Cannot join clvmd process group");
46576 DEBUGLOG("Cannot join clvmd process group: %d\n", err);
46577 return cs_to_errno(err);
46578 }
46579
46580 err = cpg_local_get(cpg_handle,
46581 &our_nodeid);
46582 if (err != CS_OK) {
46583 cpg_finalize(cpg_handle);
46584 quorum_finalize(quorum_handle);
46585 dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
46586 syslog(LOG_ERR, "Cannot get local node id\n");
46587 return cs_to_errno(err);
46588 }
46589 DEBUGLOG("Our local node id is %d\n", our_nodeid);
46590
46591 DEBUGLOG("Connected to Corosync\n");
46592
46593 return 0;
46594}
46595
46596static void _cluster_closedown(void)
46597{
46598 dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
46599 cpg_finalize(cpg_handle);
46600 quorum_finalize(quorum_handle);
46601}
46602
46603static void _get_our_csid(char *csid)
46604{
46605 memcpy(csid, &our_nodeid, sizeof(int));
46606}
46607
46608/* Corosync doesn't really have nmode names so we
46609 just use the node ID in hex instead */
46610static int _csid_from_name(char *csid, const char *name)
46611{
46612 int nodeid;
46613 struct node_info *ninfo;
46614
46615 if (sscanf(name, "%x", &nodeid) == 1) {
46616 ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
46617 if (ninfo)
46618 return nodeid;
46619 }
46620 return -1;
46621}
46622
46623static int _name_from_csid(const char *csid, char *name)
46624{
46625 struct node_info *ninfo;
46626
46627 ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
46628 if (!ninfo)
46629 {
46630 sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
46631 return -1;
46632 }
46633
46634 sprintf(name, "%x", ninfo->nodeid);
46635 return 0;
46636}
46637
46638static int _get_num_nodes(void)
46639{
46640 DEBUGLOG("num_nodes = %d\n", num_nodes);
46641 return num_nodes;
46642}
46643
46644/* Node is now known to be running a clvmd */
46645static void _add_up_node(const char *csid)
46646{
46647 struct node_info *ninfo;
46648
46649 ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
46650 if (!ninfo) {
46651 DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
46652 print_corosync_csid(csid));
46653 return;
46654 }
46655
46656 DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
46657
46658 ninfo->state = NODE_CLVMD;
46659
46660 return;
46661}
46662
46663/* Call a callback for each node, so the caller knows whether it's up or down */
46664static int _cluster_do_node_callback(struct local_client *master_client,
46665 void (*callback)(struct local_client *,
46666 const char *csid, int node_up))
46667{
46668 struct dm_hash_node *hn;
46669 struct node_info *ninfo;
46670
46671 dm_hash_iterate(hn, node_hash)
46672 {
46673 char csid[COROSYNC_CSID_LEN];
46674
46675 ninfo = dm_hash_get_data(node_hash, hn);
46676 memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
46677
46678 DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
46679 ninfo->state);
46680
46681 if (ninfo->state == NODE_CLVMD)
46682 callback(master_client, csid, 1);
46683 }
46684 return 0;
46685}
46686
46687/* Real locking */
46688static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
46689{
46690 struct dlm_lksb lksb;
46691 int err;
46692
46693 DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
46694
46695 if (flags & LKF_CONVERT)
46696 lksb.sb_lkid = *lockid;
46697
46698 err = dlm_ls_lock_wait(lockspace,
46699 mode,
46700 &lksb,
46701 flags,
46702 resource,
46703 strlen(resource),
46704 0,
46705 NULL, NULL, NULL);
46706
46707 if (err != 0)
46708 {
46709 DEBUGLOG("dlm_ls_lock returned %d\n", errno);
46710 return err;
46711 }
46712 if (lksb.sb_status != 0)
46713 {
46714 DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
46715 errno = lksb.sb_status;
46716 return -1;
46717 }
46718
46719 DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
46720
46721 *lockid = lksb.sb_lkid;
46722
46723 return 0;
46724}
46725
46726
46727static int _unlock_resource(const char *resource, int lockid)
46728{
46729 struct dlm_lksb lksb;
46730 int err;
46731
46732 DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
46733 lksb.sb_lkid = lockid;
46734
46735 err = dlm_ls_unlock_wait(lockspace,
46736 lockid,
46737 0,
46738 &lksb);
46739 if (err != 0)
46740 {
46741 DEBUGLOG("Unlock returned %d\n", err);
46742 return err;
46743 }
46744 if (lksb.sb_status != EUNLOCK)
46745 {
46746 DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
46747 errno = lksb.sb_status;
46748 return -1;
46749 }
46750
46751
46752 return 0;
46753}
46754
46755static int _is_quorate(void)
46756{
46757 int quorate;
46758 if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
46759 return quorate;
46760 else
46761 return 0;
46762}
46763
46764static int _get_main_cluster_fd(void)
46765{
46766 int select_fd;
46767
46768 cpg_fd_get(cpg_handle, &select_fd);
46769 return select_fd;
46770}
46771
46772static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
46773 const char *csid,
46774 struct local_client **new_client)
46775{
46776 cluster_client = fd;
46777 *new_client = NULL;
46778 cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
46779 return 1;
46780}
46781
46782static int _cluster_send_message(const void *buf, int msglen, const char *csid,
46783 const char *errtext)
46784{
46785 struct iovec iov[2];
46786 cs_error_t err;
46787 int target_node;
46788
46789 if (csid)
46790 memcpy(&target_node, csid, COROSYNC_CSID_LEN);
46791 else
46792 target_node = 0;
46793
46794 iov[0].iov_base = &target_node;
46795 iov[0].iov_len = sizeof(int);
46796 iov[1].iov_base = (char *)buf;
46797 iov[1].iov_len = msglen;
46798
46799 err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
46800 return cs_to_errno(err);
46801}
46802
46803#ifdef HAVE_COROSYNC_CONFDB_H
46804/*
46805 * We are not necessarily connected to a Red Hat Cluster system,
46806 * but if we are, this returns the cluster name from cluster.conf.
46807 * I've used confdb rather than ccs to reduce the inter-package
46808 * dependancies as well as to allow people to set a cluster name
46809 * for themselves even if they are not running on RH cluster.
46810 */
46811static int _get_cluster_name(char *buf, int buflen)
46812{
46813 confdb_handle_t handle;
46814 int result;
46815 size_t namelen = buflen;
46816 hdb_handle_t cluster_handle;
46817 confdb_callbacks_t callbacks = {
46818 .confdb_key_change_notify_fn = NULL,
46819 .confdb_object_create_change_notify_fn = NULL,
46820 .confdb_object_delete_change_notify_fn = NULL
46821 };
46822
46823 /* This is a default in case everything else fails */
46824 strncpy(buf, "Corosync", buflen);
46825
46826 /* Look for a cluster name in confdb */
46827 result = confdb_initialize (&handle, &callbacks);
46828 if (result != CS_OK)
46829 return 0;
46830
46831 result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
46832 if (result != CS_OK)
46833 goto out;
46834
46835 result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
46836 if (result != CS_OK)
46837 goto out;
46838
46839 result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
46840 if (result != CS_OK)
46841 goto out;
46842
46843 buf[namelen] = '\0';
46844
46845out:
46846 confdb_finalize(handle);
46847 return 0;
46848}
46849
46850#elif defined HAVE_COROSYNC_CMAP_H
46851
46852static int _get_cluster_name(char *buf, int buflen)
46853{
46854 cmap_handle_t cmap_handle = 0;
46855 int result;
46856 char *name = NULL;
46857
46858 /* This is a default in case everything else fails */
46859 strncpy(buf, "Corosync", buflen);
46860
46861 /* Look for a cluster name in cmap */
46862 result = cmap_initialize(&cmap_handle);
46863 if (result != CS_OK)
46864 return 0;
46865
46866 result = cmap_get_string(cmap_handle, "totem.cluster_name", &name);
46867 if (result != CS_OK)
46868 goto out;
46869
46870 memset(buf, 0, buflen);
46871 strncpy(buf, name, buflen - 1);
46872
46873out:
46874 if (name)
46875 free(name);
46876 cmap_finalize(cmap_handle);
46877 return 0;
46878}
46879
46880#endif
46881
46882static struct cluster_ops _cluster_corosync_ops = {
46883 .name = "corosync",
46884 .cluster_init_completed = NULL,
46885 .cluster_send_message = _cluster_send_message,
46886 .name_from_csid = _name_from_csid,
46887 .csid_from_name = _csid_from_name,
46888 .get_num_nodes = _get_num_nodes,
46889 .cluster_fd_callback = _cluster_fd_callback,
46890 .get_main_cluster_fd = _get_main_cluster_fd,
46891 .cluster_do_node_callback = _cluster_do_node_callback,
46892 .is_quorate = _is_quorate,
46893 .get_our_csid = _get_our_csid,
46894 .add_up_node = _add_up_node,
46895 .reread_config = NULL,
46896 .cluster_closedown = _cluster_closedown,
46897 .get_cluster_name = _get_cluster_name,
46898 .sync_lock = _lock_resource,
46899 .sync_unlock = _unlock_resource,
46900};
46901
46902struct cluster_ops *init_corosync_cluster(void)
46903{
46904 if (!_init_cluster())
46905 return &_cluster_corosync_ops;
46906 else
46907 return NULL;
46908}
46909\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-common.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001317\013062740170\0022350\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
46910 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
46911 *
46912 * This file is part of LVM2.
46913 *
46914 * This copyrighted material is made available to anyone wishing to use,
46915 * modify, copy, or redistribute it subject to the terms and conditions
46916 * of the GNU Lesser General Public License v.2.1.
46917 *
46918 * You should have received a copy of the GNU Lesser General Public License
46919 * along with this program; if not, write to the Free Software Foundation,
46920 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
46921 */
46922
46923/*
46924 * This file must be included first by every clvmd source file.
46925 */
46926#ifndef _LVM_CLVMD_COMMON_H
46927#define _LVM_CLVMD_COMMON_H
46928
46929#define _REENTRANT
46930
46931#include "tool.h"
46932
46933#include "lvm-logging.h"
46934
46935#endif
46936\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000177630\013062740170\0021071\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
46937 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
46938 * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
46939 *
46940 * This file is part of LVM2.
46941 *
46942 * This copyrighted material is made available to anyone wishing to use,
46943 * modify, copy, or redistribute it subject to the terms and conditions
46944 * of the GNU General Public License v.2.
46945 *
46946 * You should have received a copy of the GNU General Public License
46947 * along with this program; if not, write to the Free Software Foundation,
46948 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
46949 */
46950
46951/*
46952 * CLVMD: Cluster LVM daemon
46953 */
46954
46955#include "clvmd-common.h"
46956
46957#include "clvmd-comms.h"
46958#include "clvm.h"
46959#include "clvmd.h"
46960#include "lvm-functions.h"
46961#include "lvm-version.h"
46962#include "refresh_clvmd.h"
46963
46964#ifdef HAVE_COROSYNC_CONFDB_H
46965#include <corosync/confdb.h>
46966#endif
46967
46968#include <pthread.h>
46969#include <getopt.h>
46970#include <ctype.h>
46971#include <stdarg.h>
46972
46973#include <fcntl.h>
46974#include <netinet/in.h>
46975#include <signal.h>
46976#include <stddef.h>
46977#include <syslog.h>
46978#include <sys/un.h>
46979#include <sys/utsname.h>
46980
46981#ifndef TRUE
46982#define TRUE 1
46983#endif
46984#ifndef FALSE
46985#define FALSE 0
46986#endif
46987
46988#define MAX_RETRIES 4
46989#define MAX_MISSING_LEN 8000 /* Max supported clvmd message size ? */
46990
46991#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0)
46992
46993/* Head of the fd list. Also contains
46994 the cluster_socket details */
46995static struct local_client local_client_head;
46996
46997static unsigned short global_xid = 0; /* Last transaction ID issued */
46998
46999struct cluster_ops *clops = NULL;
47000
47001static char our_csid[MAX_CSID_LEN];
47002static unsigned max_csid_len;
47003static unsigned max_cluster_message;
47004static unsigned max_cluster_member_name_len;
47005
47006/* Structure of items on the LVM thread list */
47007struct lvm_thread_cmd {
47008 struct dm_list list;
47009
47010 struct local_client *client;
47011 struct clvm_header *msg;
47012 char csid[MAX_CSID_LEN];
47013 int remote; /* Flag */
47014 int msglen;
47015 unsigned short xid;
47016};
47017
47018struct lvm_startup_params {
47019 struct dm_hash_table *excl_uuid;
47020};
47021
47022static debug_t debug = DEBUG_OFF;
47023static int foreground_mode = 0;
47024static pthread_t lvm_thread;
47025/* Stack size 128KiB for thread, must be bigger then DEFAULT_RESERVED_STACK */
47026static const size_t STACK_SIZE = 128 * 1024;
47027static pthread_attr_t stack_attr;
47028static int lvm_thread_exit = 0;
47029static pthread_mutex_t lvm_thread_mutex;
47030static pthread_cond_t lvm_thread_cond;
47031static pthread_barrier_t lvm_start_barrier;
47032static struct dm_list lvm_cmd_head;
47033static volatile sig_atomic_t quit = 0;
47034static volatile sig_atomic_t reread_config = 0;
47035static int child_pipe[2];
47036
47037/* Reasons the daemon failed initialisation */
47038#define DFAIL_INIT 1
47039#define DFAIL_LOCAL_SOCK 2
47040#define DFAIL_CLUSTER_IF 3
47041#define DFAIL_MALLOC 4
47042#define DFAIL_TIMEOUT 5
47043#define SUCCESS 0
47044
47045typedef enum {IF_AUTO, IF_CMAN, IF_OPENAIS, IF_COROSYNC, IF_SINGLENODE} if_type_t;
47046
47047/* Prototypes for code further down */
47048static void sigusr2_handler(int sig);
47049static void sighup_handler(int sig);
47050static void sigterm_handler(int sig);
47051static void send_local_reply(struct local_client *client, int status,
47052 int clientid);
47053static void free_reply(struct local_client *client);
47054static void send_version_message(void);
47055static void *pre_and_post_thread(void *arg);
47056static int send_message(void *buf, int msglen, const char *csid, int fd,
47057 const char *errtext);
47058static int read_from_local_sock(struct local_client *thisfd);
47059static int cleanup_zombie(struct local_client *thisfd);
47060static int process_local_command(struct clvm_header *msg, int msglen,
47061 struct local_client *client,
47062 unsigned short xid);
47063static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
47064 const char *csid);
47065static int process_reply(const struct clvm_header *msg, int msglen,
47066 const char *csid);
47067static int open_local_sock(void);
47068static void close_local_sock(int local_socket);
47069static int check_local_clvmd(void);
47070static struct local_client *find_client(int clientid);
47071static void main_loop(int cmd_timeout);
47072static void be_daemon(int start_timeout);
47073static int check_all_clvmds_running(struct local_client *client);
47074static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
47075 int len, const char *csid,
47076 struct local_client **new_client);
47077static void *lvm_thread_fn(void *) __attribute__((noreturn));
47078static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
47079 int msglen, const char *csid);
47080static int distribute_command(struct local_client *thisfd);
47081static void hton_clvm(struct clvm_header *hdr);
47082static void ntoh_clvm(struct clvm_header *hdr);
47083static void add_reply_to_list(struct local_client *client, int status,
47084 const char *csid, const char *buf, int len);
47085static if_type_t parse_cluster_interface(char *ifname);
47086static if_type_t get_cluster_type(void);
47087
47088static void usage(const char *prog, FILE *file)
47089{
47090 fprintf(file, "Usage: %s [options]\n"
47091 " -C Sets debug level (from -d) on all clvmd instances clusterwide\n"
47092 " -d[<n>] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n"
47093 " -E<uuid> Take this lock uuid as exclusively locked resource (for restart)\n"
47094 " -f Don't fork, run in the foreground\n"
47095 " -h Show this help information\n"
47096 " -I<cmgr> Cluster manager (default: auto)\n"
47097 " Available cluster managers: "
47098#ifdef USE_COROSYNC
47099 "corosync "
47100#endif
47101#ifdef USE_CMAN
47102 "cman "
47103#endif
47104#ifdef USE_OPENAIS
47105 "openais "
47106#endif
47107#ifdef USE_SINGLENODE
47108 "singlenode "
47109#endif
47110 "\n"
47111 " -R Tell all running clvmds in the cluster to reload their device cache\n"
47112 " -S Restart clvmd, preserving exclusive locks\n"
47113 " -t<secs> Command timeout (default: 60 seconds)\n"
47114 " -T<secs> Startup timeout (default: 0 seconds)\n"
47115 " -V Show version of clvmd\n"
47116 "\n", prog);
47117}
47118
47119/* Called to signal the parent how well we got on during initialisation */
47120static void child_init_signal(int status)
47121{
47122 if (child_pipe[1]) {
47123 /* FIXME Use a proper wrapper around write */
47124 if (write(child_pipe[1], &status, sizeof(status)) < 0)
47125 log_sys_error("write", "child_pipe");
47126 if (close(child_pipe[1]))
47127 log_sys_error("close", "child_pipe");
47128 }
47129}
47130
47131static __attribute__((noreturn)) void child_init_signal_and_exit(int status)
47132{
47133 child_init_signal(status);
47134 exit(status);
47135}
47136
47137static void safe_close(int *fd)
47138{
47139 if (*fd >= 0) {
47140 int to_close = *fd;
47141 *fd = -1;
47142 if (close(to_close))
47143 log_sys_error("close", ""); /* path */
47144 }
47145}
47146
47147void debuglog(const char *fmt, ...)
47148{
47149 time_t P;
47150 va_list ap;
47151 static int syslog_init = 0;
47152 char buf_ctime[64];
47153
47154 switch (clvmd_get_debug()) {
47155 case DEBUG_STDERR:
47156 va_start(ap,fmt);
47157 time(&P);
47158 fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime_r(&P, buf_ctime) + 4);
47159 vfprintf(stderr, fmt, ap);
47160 va_end(ap);
47161 fflush(stderr);
47162 break;
47163 case DEBUG_SYSLOG:
47164 if (!syslog_init) {
47165 openlog("clvmd", LOG_PID, LOG_DAEMON);
47166 syslog_init = 1;
47167 }
47168
47169 va_start(ap,fmt);
47170 vsyslog(LOG_DEBUG, fmt, ap);
47171 va_end(ap);
47172 break;
47173 case DEBUG_OFF:
47174 break;
47175 }
47176}
47177
47178void clvmd_set_debug(debug_t new_debug)
47179{
47180 if (!foreground_mode && new_debug == DEBUG_STDERR)
47181 new_debug = DEBUG_SYSLOG;
47182
47183 if (new_debug > DEBUG_SYSLOG)
47184 new_debug = DEBUG_SYSLOG;
47185
47186 debug = new_debug;
47187}
47188
47189debug_t clvmd_get_debug(void)
47190{
47191 return debug;
47192}
47193
47194int clvmd_get_foreground(void)
47195{
47196 return foreground_mode;
47197}
47198
47199static const char *decode_cmd(unsigned char cmdl)
47200{
47201 static char buf[128];
47202 const char *command;
47203
47204 switch (cmdl) {
47205 case CLVMD_CMD_TEST:
47206 command = "TEST";
47207 break;
47208 case CLVMD_CMD_LOCK_VG:
47209 command = "LOCK_VG";
47210 break;
47211 case CLVMD_CMD_LOCK_LV:
47212 command = "LOCK_LV";
47213 break;
47214 case CLVMD_CMD_REFRESH:
47215 command = "REFRESH";
47216 break;
47217 case CLVMD_CMD_SET_DEBUG:
47218 command = "SET_DEBUG";
47219 break;
47220 case CLVMD_CMD_GET_CLUSTERNAME:
47221 command = "GET_CLUSTERNAME";
47222 break;
47223 case CLVMD_CMD_VG_BACKUP:
47224 command = "VG_BACKUP";
47225 break;
47226 case CLVMD_CMD_REPLY:
47227 command = "REPLY";
47228 break;
47229 case CLVMD_CMD_VERSION:
47230 command = "VERSION";
47231 break;
47232 case CLVMD_CMD_GOAWAY:
47233 command = "GOAWAY";
47234 break;
47235 case CLVMD_CMD_LOCK:
47236 command = "LOCK";
47237 break;
47238 case CLVMD_CMD_UNLOCK:
47239 command = "UNLOCK";
47240 break;
47241 case CLVMD_CMD_LOCK_QUERY:
47242 command = "LOCK_QUERY";
47243 break;
47244 case CLVMD_CMD_RESTART:
47245 command = "RESTART";
47246 break;
47247 case CLVMD_CMD_SYNC_NAMES:
47248 command = "SYNC_NAMES";
47249 break;
47250 default:
47251 command = "unknown";
47252 break;
47253 }
47254
47255 snprintf(buf, sizeof(buf), "%s (0x%x)", command, cmdl);
47256
47257 return buf;
47258}
47259
47260static void remove_lockfile(void)
47261{
47262 if (unlink(CLVMD_PIDFILE))
47263 log_sys_error("unlink", CLVMD_PIDFILE);
47264}
47265
47266/*
47267 * clvmd require dm-ioctl capability for operation
47268 */
47269static void check_permissions(void)
47270{
47271 if (getuid() || geteuid()) {
47272 log_error("Cannot run as a non-root user.");
47273
47274 /*
47275 * Fail cleanly here if not run as root, instead of failing
47276 * later when attempting a root-only operation
47277 * Preferred exit code from an initscript for this.
47278 */
47279 exit(4);
47280 }
47281}
47282
47283int main(int argc, char *argv[])
47284{
47285 int local_sock;
47286 struct local_client *newfd, *delfd;
47287 struct lvm_startup_params lvm_params;
47288 int opt;
47289 int cmd_timeout = DEFAULT_CMD_TIMEOUT;
47290 int start_timeout = 0;
47291 if_type_t cluster_iface = IF_AUTO;
47292 sigset_t ss;
47293 debug_t debug_opt = DEBUG_OFF;
47294 debug_t debug_arg = DEBUG_OFF;
47295 int clusterwide_opt = 0;
47296 mode_t old_mask;
47297 int ret = 1;
47298
47299 struct option longopts[] = {
47300 { "help", 0, 0, 'h' },
47301 { NULL, 0, 0, 0 }
47302 };
47303
47304 if (!(lvm_params.excl_uuid = dm_hash_create(128))) {
47305 fprintf(stderr, "Failed to allocate hash table\n");
47306 return 1;
47307 }
47308
47309 /* Deal with command-line arguments */
47310 opterr = 0;
47311 optind = 0;
47312 while ((opt = getopt_long(argc, argv, "Vhfd:t:RST:CI:E:",
47313 longopts, NULL)) != -1) {
47314 switch (opt) {
47315 case 'h':
47316 usage(argv[0], stdout);
47317 exit(0);
47318
47319 case 'R':
47320 check_permissions();
47321 ret = (refresh_clvmd(1) == 1) ? 0 : 1;
47322 goto out;
47323
47324 case 'S':
47325 check_permissions();
47326 ret = (restart_clvmd(clusterwide_opt) == 1) ? 0 : 1;
47327 goto out;
47328
47329 case 'C':
47330 clusterwide_opt = 1;
47331 break;
47332
47333 case 'd':
47334 debug_opt = DEBUG_STDERR;
47335 debug_arg = (debug_t) atoi(optarg);
47336 if (debug_arg == DEBUG_STDERR)
47337 foreground_mode = 1;
47338 break;
47339
47340 case 'f':
47341 foreground_mode = 1;
47342 break;
47343 case 't':
47344 cmd_timeout = atoi(optarg);
47345 if (!cmd_timeout) {
47346 fprintf(stderr, "command timeout is invalid\n");
47347 usage(argv[0], stderr);
47348 exit(1);
47349 }
47350 break;
47351 case 'I':
47352 cluster_iface = parse_cluster_interface(optarg);
47353 break;
47354 case 'E':
47355 if (!dm_hash_insert(lvm_params.excl_uuid, optarg, optarg)) {
47356 fprintf(stderr, "Failed to allocate hash entry\n");
47357 goto out;
47358 }
47359 break;
47360 case 'T':
47361 start_timeout = atoi(optarg);
47362 if (start_timeout <= 0) {
47363 fprintf(stderr, "startup timeout is invalid\n");
47364 usage(argv[0], stderr);
47365 exit(1);
47366 }
47367 break;
47368
47369 case 'V':
47370 printf("Cluster LVM daemon version: %s\n", LVM_VERSION);
47371 printf("Protocol version: %d.%d.%d\n",
47372 CLVMD_MAJOR_VERSION, CLVMD_MINOR_VERSION,
47373 CLVMD_PATCH_VERSION);
47374 exit(0);
47375 break;
47376
47377 default:
47378 usage(argv[0], stderr);
47379 exit(2);
47380 }
47381 }
47382
47383 check_permissions();
47384
47385 /*
47386 * Switch to C locale to avoid reading large locale-archive file
47387 * used by some glibc (on some distributions it takes over 100MB).
47388 * Daemon currently needs to use mlockall().
47389 */
47390 if (setenv("LC_ALL", "C", 1))
47391 perror("Cannot set LC_ALL to C");
47392
47393 /* Setting debug options on an existing clvmd */
47394 if (debug_opt && !check_local_clvmd()) {
47395 dm_hash_destroy(lvm_params.excl_uuid);
47396 return debug_clvmd(debug_arg, clusterwide_opt)==1?0:1;
47397 }
47398
47399 clvmd_set_debug(debug_arg);
47400
47401 /* Fork into the background (unless requested not to) */
47402 if (!foreground_mode)
47403 be_daemon(start_timeout);
47404
47405 (void) dm_prepare_selinux_context(DEFAULT_RUN_DIR, S_IFDIR);
47406 old_mask = umask(0077);
47407 if (dm_create_dir(DEFAULT_RUN_DIR) == 0) {
47408 DEBUGLOG("clvmd: unable to create %s directory\n",
47409 DEFAULT_RUN_DIR);
47410 umask(old_mask);
47411 exit(1);
47412 }
47413 umask(old_mask);
47414
47415 /* Create pidfile */
47416 (void) dm_prepare_selinux_context(CLVMD_PIDFILE, S_IFREG);
47417 if (dm_create_lockfile(CLVMD_PIDFILE) == 0) {
47418 DEBUGLOG("clvmd: unable to create lockfile\n");
47419 exit(1);
47420 }
47421 (void) dm_prepare_selinux_context(NULL, 0);
47422
47423 atexit(remove_lockfile);
47424
47425 DEBUGLOG("CLVMD started\n");
47426
47427 /* Open the Unix socket we listen for commands on.
47428 We do this before opening the cluster socket so that
47429 potential clients will block rather than error if we are running
47430 but the cluster is not ready yet */
47431 local_sock = open_local_sock();
47432 if (local_sock < 0) {
47433 child_init_signal_and_exit(DFAIL_LOCAL_SOCK);
47434 /* NOTREACHED */
47435 }
47436
47437 /* Set up signal handlers, USR1 is for cluster change notifications (in cman)
47438 USR2 causes child threads to exit.
47439 (HUP used to cause gulm to re-read the nodes list from CCS.)
47440 PIPE should be ignored */
47441 signal(SIGUSR2, sigusr2_handler);
47442 signal(SIGHUP, sighup_handler);
47443 signal(SIGPIPE, SIG_IGN);
47444
47445 /* Block SIGUSR2/SIGINT/SIGTERM in process */
47446 sigemptyset(&ss);
47447 sigaddset(&ss, SIGUSR2);
47448 sigaddset(&ss, SIGINT);
47449 sigaddset(&ss, SIGTERM);
47450 sigprocmask(SIG_BLOCK, &ss, NULL);
47451
47452 /* Initialise the LVM thread variables */
47453 dm_list_init(&lvm_cmd_head);
47454 if (pthread_attr_init(&stack_attr) ||
47455 pthread_attr_setstacksize(&stack_attr, STACK_SIZE)) {
47456 log_sys_error("pthread_attr_init", "");
47457 exit(1);
47458 }
47459 pthread_mutex_init(&lvm_thread_mutex, NULL);
47460 pthread_cond_init(&lvm_thread_cond, NULL);
47461 pthread_barrier_init(&lvm_start_barrier, NULL, 2);
47462 init_lvhash();
47463
47464 /* Start the cluster interface */
47465 if (cluster_iface == IF_AUTO)
47466 cluster_iface = get_cluster_type();
47467
47468#ifdef USE_CMAN
47469 if ((cluster_iface == IF_AUTO || cluster_iface == IF_CMAN) &&
47470 (clops = init_cman_cluster())) {
47471 max_csid_len = CMAN_MAX_CSID_LEN;
47472 max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
47473 max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
47474 syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
47475 }
47476#endif
47477#ifdef USE_COROSYNC
47478 if (!clops)
47479 if (((cluster_iface == IF_AUTO || cluster_iface == IF_COROSYNC) &&
47480 (clops = init_corosync_cluster()))) {
47481 max_csid_len = COROSYNC_CSID_LEN;
47482 max_cluster_message = COROSYNC_MAX_CLUSTER_MESSAGE;
47483 max_cluster_member_name_len = COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN;
47484 syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to Corosync");
47485 }
47486#endif
47487#ifdef USE_OPENAIS
47488 if (!clops)
47489 if ((cluster_iface == IF_AUTO || cluster_iface == IF_OPENAIS) &&
47490 (clops = init_openais_cluster())) {
47491 max_csid_len = OPENAIS_CSID_LEN;
47492 max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
47493 max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
47494 syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS");
47495 }
47496#endif
47497#ifdef USE_SINGLENODE
47498 if (!clops)
47499 if (cluster_iface == IF_SINGLENODE && (clops = init_singlenode_cluster())) {
47500 max_csid_len = SINGLENODE_CSID_LEN;
47501 max_cluster_message = SINGLENODE_MAX_CLUSTER_MESSAGE;
47502 max_cluster_member_name_len = MAX_CLUSTER_MEMBER_NAME_LEN;
47503 syslog(LOG_NOTICE, "Cluster LVM daemon started - running in single-node mode");
47504 }
47505#endif
47506
47507 if (!clops) {
47508 DEBUGLOG("Can't initialise cluster interface\n");
47509 log_error("Can't initialise cluster interface.");
47510 child_init_signal_and_exit(DFAIL_CLUSTER_IF);
47511 /* NOTREACHED */
47512 }
47513 DEBUGLOG("Cluster ready, doing some more initialisation\n");
47514
47515 /* Save our CSID */
47516 clops->get_our_csid(our_csid);
47517
47518 /* Initialise the FD list head */
47519 local_client_head.fd = clops->get_main_cluster_fd();
47520 local_client_head.type = CLUSTER_MAIN_SOCK;
47521 local_client_head.callback = clops->cluster_fd_callback;
47522
47523 /* Add the local socket to the list */
47524 if (!(newfd = dm_zalloc(sizeof(struct local_client)))) {
47525 child_init_signal_and_exit(DFAIL_MALLOC);
47526 /* NOTREACHED */
47527 }
47528
47529 newfd->fd = local_sock;
47530 newfd->type = LOCAL_RENDEZVOUS;
47531 newfd->callback = local_rendezvous_callback;
47532 newfd->next = local_client_head.next;
47533 local_client_head.next = newfd;
47534
47535 /* This needs to be started after cluster initialisation
47536 as it may need to take out locks */
47537 DEBUGLOG("Starting LVM thread\n");
47538 DEBUGLOG("Main cluster socket fd %d (%p) with local socket %d (%p)\n",
47539 local_client_head.fd, &local_client_head, newfd->fd, newfd);
47540
47541 /* Don't let anyone else to do work until we are started */
47542 if (pthread_create(&lvm_thread, &stack_attr, lvm_thread_fn, &lvm_params)) {
47543 log_sys_error("pthread_create", "");
47544 goto out;
47545 }
47546
47547 /* Don't start until the LVM thread is ready */
47548 pthread_barrier_wait(&lvm_start_barrier);
47549
47550 /* Tell the rest of the cluster our version number */
47551 if (clops->cluster_init_completed)
47552 clops->cluster_init_completed();
47553
47554 DEBUGLOG("clvmd ready for work\n");
47555 child_init_signal(SUCCESS);
47556
47557 /* Try to shutdown neatly */
47558 signal(SIGTERM, sigterm_handler);
47559 signal(SIGINT, sigterm_handler);
47560
47561 /* Do some work */
47562 main_loop(cmd_timeout);
47563
47564 pthread_mutex_lock(&lvm_thread_mutex);
47565 lvm_thread_exit = 1;
47566 pthread_cond_signal(&lvm_thread_cond);
47567 pthread_mutex_unlock(&lvm_thread_mutex);
47568 if ((errno = pthread_join(lvm_thread, NULL)))
47569 log_sys_error("pthread_join", "");
47570
47571 close_local_sock(local_sock);
47572
47573 while ((delfd = local_client_head.next)) {
47574 local_client_head.next = delfd->next;
47575 /* Failing cleanup_zombie leaks... */
47576 if (delfd->type == LOCAL_SOCK && !cleanup_zombie(delfd))
47577 cmd_client_cleanup(delfd); /* calls sync_unlock */
47578 if (delfd->fd != local_sock)
47579 safe_close(&(delfd->fd));
47580 dm_free(delfd);
47581 }
47582
47583 DEBUGLOG("cluster_closedown\n");
47584 destroy_lvhash();
47585 clops->cluster_closedown();
47586
47587 ret = 0;
47588out:
47589 dm_hash_destroy(lvm_params.excl_uuid);
47590
47591 return ret;
47592}
47593
47594/* Called when the cluster layer has completed initialisation.
47595 We send the version message */
47596void clvmd_cluster_init_completed(void)
47597{
47598 send_version_message();
47599}
47600
47601/* Data on a connected socket */
47602static int local_sock_callback(struct local_client *thisfd, char *buf, int len,
47603 const char *csid,
47604 struct local_client **new_client)
47605{
47606 *new_client = NULL;
47607 return read_from_local_sock(thisfd);
47608}
47609
47610/* Data on a connected socket */
47611static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
47612 int len, const char *csid,
47613 struct local_client **new_client)
47614{
47615 /* Someone connected to our local socket, accept it. */
47616
47617 struct sockaddr_un socka;
47618 struct local_client *newfd;
47619 socklen_t sl = sizeof(socka);
47620 int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl);
47621
47622 if (client_fd == -1 && errno == EINTR)
47623 return 1;
47624
47625 if (client_fd >= 0) {
47626 if (!(newfd = dm_zalloc(sizeof(*newfd)))) {
47627 if (close(client_fd))
47628 log_sys_error("close", "socket");
47629 return 1;
47630 }
47631
47632 pthread_cond_init(&newfd->bits.localsock.cond, NULL);
47633 pthread_mutex_init(&newfd->bits.localsock.mutex, NULL);
47634
47635 if (fcntl(client_fd, F_SETFD, 1))
47636 DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
47637
47638 newfd->fd = client_fd;
47639 newfd->type = LOCAL_SOCK;
47640 newfd->callback = local_sock_callback;
47641 newfd->bits.localsock.all_success = 1;
47642 DEBUGLOG("Got new connection on fd %d (%p)\n", newfd->fd, newfd);
47643 *new_client = newfd;
47644 }
47645 return 1;
47646}
47647
47648static int local_pipe_callback(struct local_client *thisfd, char *buf,
47649 int maxlen, const char *csid,
47650 struct local_client **new_client)
47651{
47652 int len;
47653 char buffer[PIPE_BUF];
47654 struct local_client *sock_client = thisfd->bits.pipe.client;
47655 int status = -1; /* in error by default */
47656
47657 len = read(thisfd->fd, buffer, sizeof(int));
47658 if (len == -1 && errno == EINTR)
47659 return 1;
47660
47661 if (len == sizeof(int))
47662 memcpy(&status, buffer, sizeof(int));
47663
47664 DEBUGLOG("Read on pipe %d, %d bytes, status %d\n",
47665 thisfd->fd, len, status);
47666
47667 /* EOF on pipe or an error, close it */
47668 if (len <= 0) {
47669 void *ret = &status;
47670 if (close(thisfd->fd))
47671 log_sys_error("close", "local_pipe");
47672
47673 /* Clear out the cross-link */
47674 if (thisfd->bits.pipe.client)
47675 thisfd->bits.pipe.client->bits.localsock.pipe_client = NULL;
47676
47677 /* Reap child thread */
47678 if (thisfd->bits.pipe.threadid) {
47679 if ((errno = pthread_join(thisfd->bits.pipe.threadid, &ret)))
47680 log_sys_error("pthread_join", "");
47681
47682 thisfd->bits.pipe.threadid = 0;
47683 if (thisfd->bits.pipe.client)
47684 thisfd->bits.pipe.client->bits.localsock.threadid = 0;
47685 }
47686 return -1;
47687 } else {
47688 DEBUGLOG("Background routine status was %d, sock_client (%p)\n",
47689 status, sock_client);
47690 /* But has the client gone away ?? */
47691 if (!sock_client) {
47692 DEBUGLOG("Got pipe response for dead client, ignoring it\n");
47693 } else {
47694 /* If error then just return that code */
47695 if (status)
47696 send_local_reply(sock_client, status,
47697 sock_client->fd);
47698 else {
47699 /* FIXME: closer inspect this code since state is write thread protected */
47700 pthread_mutex_lock(&sock_client->bits.localsock.mutex);
47701 if (sock_client->bits.localsock.state == POST_COMMAND) {
47702 pthread_mutex_unlock(&sock_client->bits.localsock.mutex);
47703 send_local_reply(sock_client, 0,
47704 sock_client->fd);
47705 } else {
47706 /* PRE_COMMAND finished. */
47707 pthread_mutex_unlock(&sock_client->bits.localsock.mutex);
47708 if ((status = distribute_command(sock_client)))
47709 send_local_reply(sock_client, EFBIG,
47710 sock_client->fd);
47711 }
47712 }
47713 }
47714 }
47715 return len;
47716}
47717
47718/* If a noed is up, look for it in the reply array, if it's not there then
47719 add one with "ETIMEDOUT".
47720 NOTE: This won't race with real replies because they happen in the same thread.
47721*/
47722static void timedout_callback(struct local_client *client, const char *csid,
47723 int node_up)
47724{
47725 struct node_reply *reply;
47726 char nodename[max_cluster_member_name_len];
47727
47728 if (!node_up)
47729 return;
47730
47731 clops->name_from_csid(csid, nodename);
47732 DEBUGLOG("Checking for a reply from %s\n", nodename);
47733 pthread_mutex_lock(&client->bits.localsock.mutex);
47734
47735 reply = client->bits.localsock.replies;
47736 while (reply && strcmp(reply->node, nodename) != 0)
47737 reply = reply->next;
47738
47739 pthread_mutex_unlock(&client->bits.localsock.mutex);
47740
47741 if (!reply) {
47742 DEBUGLOG("Node %s timed-out\n", nodename);
47743 add_reply_to_list(client, ETIMEDOUT, csid,
47744 "Command timed out", 18);
47745 }
47746}
47747
47748/* Called when the request has timed out on at least one node. We fill in
47749 the remaining node entries with ETIMEDOUT and return.
47750
47751 By the time we get here the node that caused
47752 the timeout could have gone down, in which case we will never get the expected
47753 number of replies that triggers the post command so we need to do it here
47754*/
47755static void request_timed_out(struct local_client *client)
47756{
47757 DEBUGLOG("Request timed-out. padding\n");
47758 clops->cluster_do_node_callback(client, timedout_callback);
47759
47760 if (!client->bits.localsock.threadid)
47761 return;
47762
47763 pthread_mutex_lock(&client->bits.localsock.mutex);
47764
47765 if (!client->bits.localsock.finished &&
47766 (client->bits.localsock.num_replies !=
47767 client->bits.localsock.expected_replies)) {
47768 /* Post-process the command */
47769 client->bits.localsock.state = POST_COMMAND;
47770 pthread_cond_signal(&client->bits.localsock.cond);
47771 }
47772
47773 pthread_mutex_unlock(&client->bits.localsock.mutex);
47774}
47775
47776/* This is where the real work happens */
47777static void main_loop(int cmd_timeout)
47778{
47779 sigset_t ss;
47780
47781 DEBUGLOG("Using timeout of %d seconds\n", cmd_timeout);
47782
47783 sigemptyset(&ss);
47784 sigaddset(&ss, SIGINT);
47785 sigaddset(&ss, SIGTERM);
47786 pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
47787 /* Main loop */
47788 while (!quit) {
47789 fd_set in;
47790 int select_status;
47791 struct local_client *thisfd;
47792 struct timeval tv = { cmd_timeout, 0 };
47793 int quorate = clops->is_quorate();
47794 int client_count = 0;
47795 int max_fd = 0;
47796 struct local_client *lastfd = &local_client_head;
47797 struct local_client *nextfd = local_client_head.next;
47798
47799 /* Wait on the cluster FD and all local sockets/pipes */
47800 local_client_head.fd = clops->get_main_cluster_fd();
47801 FD_ZERO(&in);
47802
47803 for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
47804 client_count++;
47805 max_fd = max(max_fd, thisfd->fd);
47806 }
47807
47808 if (max_fd > FD_SETSIZE - 32) {
47809 fprintf(stderr, "WARNING: There are too many connections to clvmd. Investigate and take action now!\n");
47810 fprintf(stderr, "WARNING: Your cluster may freeze up if the number of clvmd file descriptors (%d) exceeds %d.\n", max_fd + 1, FD_SETSIZE);
47811 }
47812
47813 for (thisfd = &local_client_head; thisfd; thisfd = nextfd, nextfd = thisfd ? thisfd->next : NULL) {
47814
47815 if (thisfd->removeme && !cleanup_zombie(thisfd)) {
47816 struct local_client *free_fd = thisfd;
47817 lastfd->next = nextfd;
47818 DEBUGLOG("removeme set for %p with %d monitored fds remaining\n", free_fd, client_count - 1);
47819
47820 /* Queue cleanup, this also frees the client struct */
47821 add_to_lvmqueue(free_fd, NULL, 0, NULL);
47822
47823 continue;
47824 }
47825
47826 lastfd = thisfd;
47827
47828 if (thisfd->removeme)
47829 continue;
47830
47831 /* if the cluster is not quorate then don't listen for new requests */
47832 if ((thisfd->type != LOCAL_RENDEZVOUS &&
47833 thisfd->type != LOCAL_SOCK) || quorate)
47834 if (thisfd->fd < FD_SETSIZE)
47835 FD_SET(thisfd->fd, &in);
47836 }
47837
47838 select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv);
47839
47840 if (reread_config) {
47841 int saved_errno = errno;
47842
47843 reread_config = 0;
47844 DEBUGLOG("got SIGHUP\n");
47845 if (clops->reread_config)
47846 clops->reread_config();
47847 errno = saved_errno;
47848 }
47849
47850 if (select_status > 0) {
47851 char csid[MAX_CSID_LEN];
47852 char buf[max_cluster_message];
47853
47854 for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
47855 if (thisfd->fd < FD_SETSIZE && FD_ISSET(thisfd->fd, &in)) {
47856 struct local_client *newfd = NULL;
47857 int ret;
47858
47859 /* FIXME Remove from main thread in case it blocks! */
47860 /* Do callback */
47861 ret = thisfd->callback(thisfd, buf, sizeof(buf),
47862 csid, &newfd);
47863 /* Ignore EAGAIN */
47864 if (ret < 0 && (errno == EAGAIN || errno == EINTR)) {
47865 continue;
47866 }
47867
47868 /* Got error or EOF: Remove it from the list safely */
47869 if (ret <= 0) {
47870 int type = thisfd->type;
47871
47872 /* If the cluster socket shuts down, so do we */
47873 if (type == CLUSTER_MAIN_SOCK ||
47874 type == CLUSTER_INTERNAL)
47875 goto closedown;
47876
47877 DEBUGLOG("ret == %d, errno = %d. removing client\n",
47878 ret, errno);
47879 thisfd->removeme = 1;
47880 continue;
47881 }
47882
47883 /* New client...simply add it to the list */
47884 if (newfd) {
47885 newfd->next = thisfd->next;
47886 thisfd->next = newfd;
47887 thisfd = newfd;
47888 }
47889 }
47890 }
47891 }
47892
47893 /* Select timed out. Check for clients that have been waiting too long for a response */
47894 if (select_status == 0) {
47895 time_t the_time = time(NULL);
47896
47897 for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
47898 if (thisfd->type == LOCAL_SOCK &&
47899 thisfd->bits.localsock.sent_out &&
47900 (thisfd->bits.localsock.sent_time + cmd_timeout) < the_time &&
47901 thisfd->bits.localsock.expected_replies !=
47902 thisfd->bits.localsock.num_replies) {
47903 /* Send timed out message + replies we already have */
47904 DEBUGLOG("Request timed-out (send: %ld, now: %ld)\n",
47905 thisfd->bits.localsock.sent_time, the_time);
47906
47907 thisfd->bits.localsock.all_success = 0;
47908
47909 request_timed_out(thisfd);
47910 }
47911 }
47912 }
47913 if (select_status < 0) {
47914 if (errno == EINTR)
47915 continue;
47916
47917#ifdef DEBUG
47918 perror("select error");
47919 exit(-1);
47920#endif
47921 }
47922 }
47923
47924 closedown:
47925 if (quit)
47926 DEBUGLOG("SIGTERM received\n");
47927}
47928
47929static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout)
47930{
47931 int child_status;
47932 fd_set fds;
47933 struct timeval tv = {timeout, 0};
47934
47935 FD_ZERO(&fds);
47936 FD_SET(c_pipe, &fds);
47937
47938 switch (select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL)) {
47939 case 0:
47940 fprintf(stderr, "clvmd startup timed out\n");
47941 exit(DFAIL_TIMEOUT);
47942 case 1:
47943 if (read(c_pipe, &child_status, sizeof(child_status)) !=
47944 sizeof(child_status)) {
47945 fprintf(stderr, "clvmd failed in initialisation\n");
47946 exit(DFAIL_INIT);
47947 }
47948
47949 switch (child_status) {
47950 case SUCCESS:
47951 break;
47952 case DFAIL_INIT:
47953 fprintf(stderr, "clvmd failed in initialisation\n");
47954 break;
47955 case DFAIL_LOCAL_SOCK:
47956 fprintf(stderr, "clvmd could not create local socket\n");
47957 fprintf(stderr, "Another clvmd is probably already running\n");
47958 break;
47959 case DFAIL_CLUSTER_IF:
47960 fprintf(stderr, "clvmd could not connect to cluster manager\n");
47961 fprintf(stderr, "Consult syslog for more information\n");
47962 break;
47963 case DFAIL_MALLOC:
47964 fprintf(stderr, "clvmd failed, not enough memory\n");
47965 break;
47966 default:
47967 fprintf(stderr, "clvmd failed, error was %d\n", child_status);
47968 break;
47969 }
47970 exit(child_status);
47971 default:
47972 fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno));
47973 exit(DFAIL_INIT);
47974 }
47975}
47976
47977/*
47978 * Fork into the background and detach from our parent process.
47979 * In the interests of user-friendliness we wait for the daemon
47980 * to complete initialisation before returning its status
47981 * the the user.
47982 */
47983static void be_daemon(int timeout)
47984{
47985 int devnull = open("/dev/null", O_RDWR);
47986 if (devnull == -1) {
47987 perror("Can't open /dev/null");
47988 exit(3);
47989 }
47990
47991 if (pipe(child_pipe)) {
47992 perror("Error creating pipe");
47993 exit(3);
47994 }
47995
47996 switch (fork()) {
47997 case -1:
47998 perror("clvmd: can't fork");
47999 exit(2);
48000
48001 case 0: /* Child */
48002 (void) close(child_pipe[0]);
48003 break;
48004
48005 default: /* Parent */
48006 (void) close(child_pipe[1]);
48007 wait_for_child(child_pipe[0], timeout);
48008 }
48009
48010 /* Detach ourself from the calling environment */
48011 if (close(0) || close(1) || close(2)) {
48012 perror("Error closing terminal FDs");
48013 exit(4);
48014 }
48015 setsid();
48016
48017 if (dup2(devnull, 0) < 0 || dup2(devnull, 1) < 0
48018 || dup2(devnull, 2) < 0) {
48019 perror("Error setting terminal FDs to /dev/null");
48020 log_error("Error setting terminal FDs to /dev/null: %m");
48021 exit(5);
48022 }
48023 if ((devnull > STDERR_FILENO) && close(devnull)) {
48024 log_sys_error("close", "/dev/null");
48025 exit(7);
48026 }
48027 if (chdir("/")) {
48028 log_error("Error setting current directory to /: %m");
48029 exit(6);
48030 }
48031}
48032
48033static int verify_message(char *buf, int len)
48034{
48035 struct clvm_header *h = (struct clvm_header *)buf;
48036
48037 if (len < (int)sizeof(struct clvm_header)) {
48038 log_error("verify_message short len %d.", len);
48039 return -1;
48040 }
48041
48042 switch (h->cmd) {
48043 case CLVMD_CMD_REPLY:
48044 case CLVMD_CMD_VERSION:
48045 case CLVMD_CMD_GOAWAY:
48046 case CLVMD_CMD_TEST:
48047 case CLVMD_CMD_LOCK:
48048 case CLVMD_CMD_UNLOCK:
48049 case CLVMD_CMD_LOCK_LV:
48050 case CLVMD_CMD_LOCK_VG:
48051 case CLVMD_CMD_LOCK_QUERY:
48052 case CLVMD_CMD_REFRESH:
48053 case CLVMD_CMD_GET_CLUSTERNAME:
48054 case CLVMD_CMD_SET_DEBUG:
48055 case CLVMD_CMD_VG_BACKUP:
48056 case CLVMD_CMD_RESTART:
48057 case CLVMD_CMD_SYNC_NAMES:
48058 break;
48059 default:
48060 log_error("verify_message bad cmd %x.", h->cmd);
48061 return -1;
48062 }
48063
48064 /* TODO: we may be able to narrow len/flags/clientid/arglen checks based on cmd */
48065
48066 if (h->flags & ~(CLVMD_FLAG_LOCAL | CLVMD_FLAG_SYSTEMLV | CLVMD_FLAG_NODEERRS | CLVMD_FLAG_REMOTE)) {
48067 log_error("verify_message bad flags %x.", h->flags);
48068 return -1;
48069 }
48070
48071 if (h->arglen > max_cluster_message) {
48072 log_error("verify_message bad arglen %x max %d.", h->arglen, max_cluster_message);
48073 return -1;
48074 }
48075
48076 return 0;
48077}
48078
48079static void dump_message(char *buf, int len)
48080{
48081 unsigned char row[8];
48082 char str[9];
48083 int i, j = 0;
48084
48085 str[8] = '\0';
48086 if (len > 128)
48087 len = 128;
48088
48089 for (i = 0; i < len; ++i) {
48090 row[j] = buf[i];
48091 str[j] = (isprint(buf[i])) ? buf[i] : ' ';
48092
48093 if (i + 1 == len) {
48094 for (;j < 8; ++j) {
48095 row[j] = 0;
48096 str[j] = ' ';
48097 }
48098
48099 log_error("%02x %02x %02x %02x %02x %02x %02x %02x [%s]",
48100 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], str);
48101 j = 0;
48102 }
48103 }
48104}
48105
48106static int cleanup_zombie(struct local_client *thisfd)
48107{
48108 int *status;
48109 struct local_client *pipe_client;
48110
48111 if (thisfd->type != LOCAL_SOCK)
48112 return 0;
48113
48114 if (!thisfd->bits.localsock.cleanup_needed)
48115 return 0;
48116
48117 DEBUGLOG("EOF on local socket: inprogress=%d\n",
48118 thisfd->bits.localsock.in_progress);
48119
48120 if ((pipe_client = thisfd->bits.localsock.pipe_client))
48121 pipe_client = pipe_client->bits.pipe.client;
48122
48123 /* If the client went away in mid command then tidy up */
48124 if (thisfd->bits.localsock.in_progress) {
48125 DEBUGLOG("Sending SIGUSR2 to pre&post thread (%p in-progress)\n", pipe_client);
48126 pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2);
48127 if (pthread_mutex_trylock(&thisfd->bits.localsock.mutex))
48128 return 1;
48129 thisfd->bits.localsock.state = POST_COMMAND;
48130 thisfd->bits.localsock.finished = 1;
48131 pthread_cond_signal(&thisfd->bits.localsock.cond);
48132 pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
48133
48134 /* Free any unsent buffers */
48135 free_reply(thisfd);
48136 }
48137
48138 /* Kill the subthread & free resources */
48139 if (thisfd->bits.localsock.threadid) {
48140 DEBUGLOG("Waiting for pre&post thread (%p)\n", pipe_client);
48141 pthread_mutex_lock(&thisfd->bits.localsock.mutex);
48142 thisfd->bits.localsock.state = PRE_COMMAND;
48143 thisfd->bits.localsock.finished = 1;
48144 pthread_cond_signal(&thisfd->bits.localsock.cond);
48145 pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
48146
48147 if ((errno = pthread_join(thisfd->bits.localsock.threadid,
48148 (void **) &status)))
48149 log_sys_error("pthread_join", "");
48150
48151 DEBUGLOG("Joined pre&post thread\n");
48152
48153 thisfd->bits.localsock.threadid = 0;
48154
48155 /* Remove the pipe client */
48156 if (thisfd->bits.localsock.pipe_client) {
48157 struct local_client *delfd;
48158 struct local_client *lastfd;
48159
48160 (void) close(thisfd->bits.localsock.pipe_client->fd); /* Close pipe */
48161 (void) close(thisfd->bits.localsock.pipe);
48162
48163 /* Remove pipe client */
48164 for (lastfd = &local_client_head; (delfd = lastfd->next); lastfd = delfd)
48165 if (thisfd->bits.localsock.pipe_client == delfd) {
48166 thisfd->bits.localsock.pipe_client = NULL;
48167 lastfd->next = delfd->next;
48168 dm_free(delfd);
48169 break;
48170 }
48171 }
48172 }
48173
48174 /* Free the command buffer */
48175 dm_free(thisfd->bits.localsock.cmd);
48176
48177 safe_close(&(thisfd->fd));
48178 thisfd->bits.localsock.cleanup_needed = 0;
48179
48180 return 0;
48181}
48182
48183/* Called when we have a read from the local socket.
48184 was in the main loop but it's grown up and is a big girl now */
48185static int read_from_local_sock(struct local_client *thisfd)
48186{
48187 int len;
48188 int argslen;
48189 int missing_len;
48190 char buffer[PIPE_BUF + 1];
48191 char csid[MAX_CSID_LEN];
48192 int comms_pipe[2];
48193 struct local_client *newfd;
48194 struct clvm_header *inheader = (struct clvm_header *) buffer;
48195 int status;
48196
48197 len = read(thisfd->fd, buffer, sizeof(buffer) - 1);
48198 if (len == -1 && errno == EINTR)
48199 return 1;
48200
48201 DEBUGLOG("Read on local socket %d, len = %d\n", thisfd->fd, len);
48202
48203 if (len && verify_message(buffer, len) < 0) {
48204 log_error("read_from_local_sock from %d len %d bad verify.",
48205 thisfd->fd, len);
48206 dump_message(buffer, len);
48207 /* force error handling below */
48208 len = 0;
48209 }
48210
48211 /* EOF or error on socket */
48212 if (len <= 0) {
48213 thisfd->bits.localsock.cleanup_needed = 1;
48214 (void) cleanup_zombie(thisfd); /* ignore errors here */
48215 return 0;
48216 }
48217
48218 buffer[len] = 0; /* Ensure \0 terminated */
48219
48220 /* Fill in the client ID */
48221 inheader->clientid = htonl(thisfd->fd);
48222
48223 /* If we are already busy then return an error */
48224 if (thisfd->bits.localsock.in_progress) {
48225 struct clvm_header reply = {
48226 .cmd = CLVMD_CMD_REPLY,
48227 .status = EBUSY
48228 };
48229 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48230 "Error sending EBUSY reply to local user");
48231 return len;
48232 }
48233
48234 /* See if we have the whole message */
48235 argslen = len - strlen(inheader->node) - sizeof(struct clvm_header);
48236 missing_len = inheader->arglen - argslen;
48237
48238 if (missing_len < 0)
48239 missing_len = 0;
48240
48241 /* We need at least sizeof(struct clvm_header) bytes in buffer */
48242 if (len < (int)sizeof(struct clvm_header) || /* Already handled in verify_message() */
48243 argslen < 0 || missing_len > MAX_MISSING_LEN) {
48244 struct clvm_header reply = {
48245 .cmd = CLVMD_CMD_REPLY,
48246 .status = EINVAL
48247 };
48248 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48249 "Error sending EINVAL reply to local user");
48250 return 0;
48251 }
48252
48253 /* Free any old buffer space */
48254 dm_free(thisfd->bits.localsock.cmd);
48255
48256 /* Save the message */
48257 if (!(thisfd->bits.localsock.cmd = dm_malloc(len + missing_len))) {
48258 struct clvm_header reply = {
48259 .cmd = CLVMD_CMD_REPLY,
48260 .status = ENOMEM
48261 };
48262 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48263 "Error sending ENOMEM reply to local user");
48264 return 0;
48265 }
48266 memcpy(thisfd->bits.localsock.cmd, buffer, len);
48267 thisfd->bits.localsock.cmd_len = len + missing_len;
48268 inheader = (struct clvm_header *) thisfd->bits.localsock.cmd;
48269
48270 /* If we don't have the full message then read the rest now */
48271 if (missing_len) {
48272 char *argptr = inheader->node + strlen(inheader->node) + 1;
48273
48274 while (missing_len > 0) {
48275 DEBUGLOG("got %d bytes, need another %d (total %d)\n",
48276 argslen, missing_len, inheader->arglen);
48277 len = read(thisfd->fd, argptr + argslen, missing_len);
48278 if (len == -1 && errno == EINTR)
48279 continue;
48280
48281 if (len <= 0) {
48282 /* EOF or error on socket */
48283 DEBUGLOG("EOF on local socket\n");
48284 dm_free(thisfd->bits.localsock.cmd);
48285 thisfd->bits.localsock.cmd = NULL;
48286 return 0;
48287 }
48288
48289 missing_len -= len;
48290 argslen += len;
48291 }
48292 }
48293
48294 /* Only run the command if all the cluster nodes are running CLVMD */
48295 if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) &&
48296 (check_all_clvmds_running(thisfd) == -1)) {
48297 thisfd->bits.localsock.expected_replies = 0;
48298 thisfd->bits.localsock.num_replies = 0;
48299 send_local_reply(thisfd, EHOSTDOWN, thisfd->fd);
48300 return len;
48301 }
48302
48303 /* Check the node name for validity */
48304 if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) {
48305 /* Error, node is not in the cluster */
48306 struct clvm_header reply = {
48307 .cmd = CLVMD_CMD_REPLY,
48308 .status = ENOENT
48309 };
48310
48311 DEBUGLOG("Unknown node: '%s'\n", inheader->node);
48312 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48313 "Error sending ENOENT reply to local user");
48314 thisfd->bits.localsock.expected_replies = 0;
48315 thisfd->bits.localsock.num_replies = 0;
48316 thisfd->bits.localsock.in_progress = FALSE;
48317 thisfd->bits.localsock.sent_out = FALSE;
48318 return len;
48319 }
48320
48321 /* If we already have a subthread then just signal it to start */
48322 if (thisfd->bits.localsock.threadid) {
48323 pthread_mutex_lock(&thisfd->bits.localsock.mutex);
48324 thisfd->bits.localsock.state = PRE_COMMAND;
48325 pthread_cond_signal(&thisfd->bits.localsock.cond);
48326 pthread_mutex_unlock(&thisfd->bits.localsock.mutex);
48327 return len;
48328 }
48329
48330 /* Create a pipe and add the reading end to our FD list */
48331 if (pipe(comms_pipe)) {
48332 struct clvm_header reply = {
48333 .cmd = CLVMD_CMD_REPLY,
48334 .status = EBUSY
48335 };
48336
48337 DEBUGLOG("Creating pipe failed: %s\n", strerror(errno));
48338 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48339 "Error sending EBUSY reply to local user");
48340 return len;
48341 }
48342
48343 if (!(newfd = dm_zalloc(sizeof(*newfd)))) {
48344 struct clvm_header reply = {
48345 .cmd = CLVMD_CMD_REPLY,
48346 .status = ENOMEM
48347 };
48348
48349 (void) close(comms_pipe[0]);
48350 (void) close(comms_pipe[1]);
48351
48352 send_message(&reply, sizeof(reply), our_csid, thisfd->fd,
48353 "Error sending ENOMEM reply to local user");
48354 return len;
48355 }
48356
48357 DEBUGLOG("Creating pipe, [%d, %d]\n", comms_pipe[0], comms_pipe[1]);
48358
48359 if (fcntl(comms_pipe[0], F_SETFD, 1))
48360 DEBUGLOG("setting CLOEXEC on pipe[0] failed: %s\n", strerror(errno));
48361 if (fcntl(comms_pipe[1], F_SETFD, 1))
48362 DEBUGLOG("setting CLOEXEC on pipe[1] failed: %s\n", strerror(errno));
48363
48364 newfd->fd = comms_pipe[0];
48365 newfd->type = THREAD_PIPE;
48366 newfd->callback = local_pipe_callback;
48367 newfd->bits.pipe.client = thisfd;
48368 newfd->next = thisfd->next;
48369 thisfd->next = newfd;
48370
48371 /* Store a cross link to the pipe */
48372 thisfd->bits.localsock.pipe_client = newfd;
48373 thisfd->bits.localsock.pipe = comms_pipe[1];
48374
48375 /* Make sure the thread has a copy of it's own ID */
48376 newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid;
48377
48378 /* Run the pre routine */
48379 thisfd->bits.localsock.in_progress = TRUE;
48380 thisfd->bits.localsock.state = PRE_COMMAND;
48381 thisfd->bits.localsock.cleanup_needed = 1;
48382 DEBUGLOG("Creating pre&post thread for pipe fd %d (%p)\n", newfd->fd, newfd);
48383 status = pthread_create(&thisfd->bits.localsock.threadid,
48384 &stack_attr, pre_and_post_thread, thisfd);
48385 DEBUGLOG("Created pre&post thread, state = %d\n", status);
48386
48387 return len;
48388}
48389
48390/* Add a file descriptor from the cluster or comms interface to
48391 our list of FDs for select
48392*/
48393int add_client(struct local_client *new_client)
48394{
48395 new_client->next = local_client_head.next;
48396 local_client_head.next = new_client;
48397
48398 return 0;
48399}
48400
48401/* Called when the pre-command has completed successfully - we
48402 now execute the real command on all the requested nodes */
48403static int distribute_command(struct local_client *thisfd)
48404{
48405 struct clvm_header *inheader =
48406 (struct clvm_header *) thisfd->bits.localsock.cmd;
48407 int len = thisfd->bits.localsock.cmd_len;
48408
48409 thisfd->xid = global_xid++;
48410 DEBUGLOG("distribute command: XID = %d, flags=0x%x (%s%s)\n",
48411 thisfd->xid, inheader->flags,
48412 (inheader->flags & CLVMD_FLAG_LOCAL) ? "LOCAL" : "",
48413 (inheader->flags & CLVMD_FLAG_REMOTE) ? "REMOTE" : "");
48414
48415 /* Forward it to other nodes in the cluster if needed */
48416 if (!(inheader->flags & CLVMD_FLAG_LOCAL)) {
48417 /* if node is empty then do it on the whole cluster */
48418 if (inheader->node[0] == '\0') {
48419 thisfd->bits.localsock.expected_replies =
48420 clops->get_num_nodes();
48421 thisfd->bits.localsock.num_replies = 0;
48422 thisfd->bits.localsock.sent_time = time(NULL);
48423 thisfd->bits.localsock.in_progress = TRUE;
48424 thisfd->bits.localsock.sent_out = TRUE;
48425
48426 /*
48427 * Send to local node first, even if CLVMD_FLAG_REMOTE
48428 * is set so we still get a reply if this is the
48429 * only node.
48430 */
48431 add_to_lvmqueue(thisfd, inheader, len, NULL);
48432
48433 DEBUGLOG("Sending message to all cluster nodes\n");
48434 inheader->xid = thisfd->xid;
48435 send_message(inheader, len, NULL, -1,
48436 "Error forwarding message to cluster");
48437 } else {
48438 /* Do it on a single node */
48439 char csid[MAX_CSID_LEN];
48440
48441 if (clops->csid_from_name(csid, inheader->node))
48442 /* This has already been checked so should not happen */
48443 return 0;
48444
48445 /* OK, found a node... */
48446 thisfd->bits.localsock.in_progress = TRUE;
48447 thisfd->bits.localsock.expected_replies = 1;
48448 thisfd->bits.localsock.num_replies = 0;
48449
48450 /* Are we the requested node ?? */
48451 if (memcmp(csid, our_csid, max_csid_len) == 0) {
48452 DEBUGLOG("Doing command on local node only\n");
48453 add_to_lvmqueue(thisfd, inheader, len, NULL);
48454 } else {
48455 DEBUGLOG("Sending message to single node: %s\n",
48456 inheader->node);
48457 inheader->xid = thisfd->xid;
48458 send_message(inheader, len, csid, -1,
48459 "Error forwarding message to cluster node");
48460 }
48461 }
48462 } else {
48463 /* Local explicitly requested, ignore nodes */
48464 thisfd->bits.localsock.in_progress = TRUE;
48465 thisfd->bits.localsock.expected_replies = 1;
48466 thisfd->bits.localsock.num_replies = 0;
48467 DEBUGLOG("Doing command explicitly on local node only\n");
48468 add_to_lvmqueue(thisfd, inheader, len, NULL);
48469 }
48470
48471 return 0;
48472}
48473
48474/* Process a command from a remote node and return the result */
48475static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
48476 const char *csid)
48477{
48478 char *replyargs;
48479 char nodename[max_cluster_member_name_len];
48480 int replylen = 0;
48481 int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
48482 int status;
48483
48484 /* Get the node name as we /may/ need it later */
48485 clops->name_from_csid(csid, nodename);
48486
48487 DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n",
48488 decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename);
48489
48490 /* Check for GOAWAY and sulk */
48491 if (msg->cmd == CLVMD_CMD_GOAWAY) {
48492 DEBUGLOG("Told to go away by %s\n", nodename);
48493 log_error("Told to go away by %s.", nodename);
48494 exit(99);
48495 }
48496
48497 /* Version check is internal - don't bother exposing it in clvmd-command.c */
48498 if (msg->cmd == CLVMD_CMD_VERSION) {
48499 int version_nums[3];
48500 char node[256];
48501
48502 memcpy(version_nums, msg->args, sizeof(version_nums));
48503
48504 clops->name_from_csid(csid, node);
48505 DEBUGLOG("Remote node %s is version %d.%d.%d\n",
48506 node, ntohl(version_nums[0]),
48507 ntohl(version_nums[1]), ntohl(version_nums[2]));
48508
48509 if (ntohl(version_nums[0]) != CLVMD_MAJOR_VERSION) {
48510 struct clvm_header byebyemsg = {
48511 .cmd = CLVMD_CMD_GOAWAY
48512 };
48513
48514 DEBUGLOG("Telling node %s to go away because of incompatible version number\n",
48515 node);
48516 log_notice("Telling node %s to go away because of incompatible version number %d.%d.%d\n",
48517 node, ntohl(version_nums[0]),
48518 ntohl(version_nums[1]), ntohl(version_nums[2]));
48519
48520 clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg), our_csid,
48521 "Error Sending GOAWAY message");
48522 } else
48523 clops->add_up_node(csid);
48524
48525 return;
48526 }
48527
48528 /* Allocate a default reply buffer */
48529 if ((replyargs = dm_malloc(max_cluster_message - sizeof(struct clvm_header))))
48530 /* Run the command */
48531 /* FIXME: usage of init_test() is unprotected */
48532 status = do_command(NULL, msg, msglen, &replyargs,
48533 buflen, &replylen);
48534 else
48535 status = ENOMEM;
48536
48537 /* If it wasn't a reply, then reply */
48538 if (msg->cmd != CLVMD_CMD_REPLY) {
48539 char *aggreply;
48540
48541 aggreply = dm_realloc(replyargs, replylen + sizeof(struct clvm_header));
48542 if (aggreply) {
48543 struct clvm_header *agghead =
48544 (struct clvm_header *) aggreply;
48545
48546 replyargs = aggreply;
48547 /* Move it up so there's room for a header in front of the data */
48548 memmove(aggreply + offsetof(struct clvm_header, args),
48549 replyargs, replylen);
48550
48551 agghead->xid = msg->xid;
48552 agghead->cmd = CLVMD_CMD_REPLY;
48553 agghead->status = status;
48554 agghead->flags = 0;
48555 agghead->clientid = msg->clientid;
48556 agghead->arglen = replylen;
48557 agghead->node[0] = '\0';
48558 send_message(aggreply, sizeof(struct clvm_header) + replylen,
48559 csid, fd, "Error sending command reply");
48560 } else {
48561 /* Return a failure response */
48562 struct clvm_header reply = {
48563 .cmd = CLVMD_CMD_REPLY,
48564 .status = ENOMEM,
48565 .clientid = msg->clientid
48566 };
48567 DEBUGLOG("Error attempting to realloc return buffer\n");
48568 send_message(&reply, sizeof(reply), csid, fd,
48569 "Error sending ENOMEM command reply");
48570 }
48571 }
48572
48573 dm_free(replyargs);
48574}
48575
48576/* Add a reply to a command to the list of replies for this client.
48577 If we have got a full set then send them to the waiting client down the local
48578 socket */
48579static void add_reply_to_list(struct local_client *client, int status,
48580 const char *csid, const char *buf, int len)
48581{
48582 struct node_reply *reply;
48583
48584 /* Add it to the list of replies */
48585 if (!(reply = dm_zalloc(sizeof(*reply)))) {
48586 /* It's all gone horribly wrong... */
48587 send_local_reply(client, ENOMEM, client->fd);
48588 return;
48589 }
48590
48591 reply->status = status;
48592 clops->name_from_csid(csid, reply->node);
48593 DEBUGLOG("Reply from node %s: %d bytes\n", reply->node, len);
48594
48595 if (len > 0) {
48596 if (!(reply->replymsg = dm_malloc(len)))
48597 reply->status = ENOMEM;
48598 else
48599 memcpy(reply->replymsg, buf, len);
48600 } else
48601 reply->replymsg = NULL;
48602
48603 pthread_mutex_lock(&client->bits.localsock.mutex);
48604
48605 if (client->bits.localsock.finished) {
48606 dm_free(reply->replymsg);
48607 dm_free(reply);
48608 } else {
48609 /* Hook it onto the reply chain */
48610 reply->next = client->bits.localsock.replies;
48611 client->bits.localsock.replies = reply;
48612
48613 /* If we have the whole lot then do the post-process */
48614 /* Post-process the command */
48615 if (++client->bits.localsock.num_replies ==
48616 client->bits.localsock.expected_replies) {
48617 client->bits.localsock.state = POST_COMMAND;
48618 pthread_cond_signal(&client->bits.localsock.cond);
48619 }
48620 DEBUGLOG("Got %d replies, expecting: %d\n",
48621 client->bits.localsock.num_replies,
48622 client->bits.localsock.expected_replies);
48623 }
48624 pthread_mutex_unlock(&client->bits.localsock.mutex);
48625}
48626
48627/* This is the thread that runs the PRE and post commands for a particular connection */
48628static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg)
48629{
48630 struct local_client *client = (struct local_client *) arg;
48631 int status;
48632 int write_status;
48633 sigset_t ss;
48634 int pipe_fd = client->bits.localsock.pipe;
48635
48636 DEBUGLOG("Pre&post thread (%p), pipe fd %d\n", client, pipe_fd);
48637 pthread_mutex_lock(&client->bits.localsock.mutex);
48638
48639 /* Ignore SIGUSR1 (handled by master process) but enable
48640 SIGUSR2 (kills subthreads) */
48641 sigemptyset(&ss);
48642 sigaddset(&ss, SIGUSR1);
48643 pthread_sigmask(SIG_BLOCK, &ss, NULL);
48644
48645 sigdelset(&ss, SIGUSR1);
48646 sigaddset(&ss, SIGUSR2);
48647 pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
48648
48649 /* Loop around doing PRE and POST functions until the client goes away */
48650 while (!client->bits.localsock.finished) {
48651 /* Execute the code */
48652 /* FIXME: usage of init_test() is unprotected as in do_command() */
48653 if ((status = do_pre_command(client)))
48654 client->bits.localsock.all_success = 0;
48655
48656 DEBUGLOG("Pre&post thread (%p) writes status %d down to pipe fd %d\n",
48657 client, status, pipe_fd);
48658
48659 /* Tell the parent process we have finished this bit */
48660 while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int))
48661 if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) {
48662 log_error("Error sending to pipe: %m");
48663 break;
48664 }
48665
48666 if (status) {
48667 client->bits.localsock.state = POST_COMMAND;
48668 goto next_pre;
48669 }
48670
48671 /* We may need to wait for the condition variable before running the post command */
48672 if (client->bits.localsock.state != POST_COMMAND &&
48673 !client->bits.localsock.finished) {
48674 DEBUGLOG("Pre&post thread (%p) waiting to do post command, state = %d\n",
48675 client, client->bits.localsock.state);
48676 pthread_cond_wait(&client->bits.localsock.cond,
48677 &client->bits.localsock.mutex);
48678 }
48679
48680 DEBUGLOG("Pre&post thread (%p) got post command condition...\n", client);
48681
48682 /* POST function must always run, even if the client aborts */
48683 status = 0;
48684 do_post_command(client);
48685
48686 while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int))
48687 if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) {
48688 log_error("Error sending to pipe: %m");
48689 break;
48690 }
48691next_pre:
48692 if (client->bits.localsock.state != PRE_COMMAND &&
48693 !client->bits.localsock.finished) {
48694 DEBUGLOG("Pre&post thread (%p) waiting for next pre command\n", client);
48695 pthread_cond_wait(&client->bits.localsock.cond,
48696 &client->bits.localsock.mutex);
48697 }
48698
48699 DEBUGLOG("Pre&post thread (%p) got pre command condition...\n", client);
48700 }
48701 pthread_mutex_unlock(&client->bits.localsock.mutex);
48702 DEBUGLOG("Pre&post thread (%p) finished\n", client);
48703
48704 pthread_exit(NULL);
48705}
48706
48707/* Process a command on the local node and store the result */
48708static int process_local_command(struct clvm_header *msg, int msglen,
48709 struct local_client *client,
48710 unsigned short xid)
48711{
48712 char *replybuf;
48713 int buflen = max_cluster_message - sizeof(struct clvm_header) - 1;
48714 int replylen = 0;
48715 int status;
48716
48717 if (!(replybuf = dm_malloc(max_cluster_message)))
48718 return -1;
48719
48720 DEBUGLOG("process_local_command: %s msg=%p, msglen =%d, client=%p\n",
48721 decode_cmd(msg->cmd), msg, msglen, client);
48722
48723 /* If remote flag is set, just set a successful status code. */
48724 if (msg->flags & CLVMD_FLAG_REMOTE)
48725 status = 0;
48726 else
48727 status = do_command(client, msg, msglen, &replybuf, buflen, &replylen);
48728
48729 if (status)
48730 client->bits.localsock.all_success = 0;
48731
48732 /* If we took too long then discard the reply */
48733 if (xid == client->xid)
48734 add_reply_to_list(client, status, our_csid, replybuf, replylen);
48735 else
48736 DEBUGLOG("Local command took too long, discarding xid %d, current is %d\n",
48737 xid, client->xid);
48738
48739 dm_free(replybuf);
48740
48741 return status;
48742}
48743
48744static int process_reply(const struct clvm_header *msg, int msglen, const char *csid)
48745{
48746 struct local_client *client;
48747
48748 if (!(client = find_client(msg->clientid))) {
48749 DEBUGLOG("Got message for unknown client 0x%x\n",
48750 msg->clientid);
48751 log_error("Got message for unknown client 0x%x.",
48752 msg->clientid);
48753 return -1;
48754 }
48755
48756 if (msg->status)
48757 client->bits.localsock.all_success = 0;
48758
48759 /* Gather replies together for this client id */
48760 if (msg->xid == client->xid)
48761 add_reply_to_list(client, msg->status, csid, msg->args,
48762 msg->arglen);
48763 else
48764 DEBUGLOG("Discarding reply with old XID %d, current = %d\n",
48765 msg->xid, client->xid);
48766
48767 return 0;
48768}
48769
48770/* Send an aggregated reply back to the client */
48771static void send_local_reply(struct local_client *client, int status, int fd)
48772{
48773 struct clvm_header *clientreply;
48774 struct node_reply *thisreply = client->bits.localsock.replies;
48775 char *replybuf;
48776 char *ptr;
48777 int message_len = 0;
48778
48779 DEBUGLOG("Send local reply\n");
48780
48781 /* Work out the total size of the reply */
48782 while (thisreply) {
48783 if (thisreply->replymsg)
48784 message_len += strlen(thisreply->replymsg) + 1;
48785 else
48786 message_len++;
48787
48788 message_len += strlen(thisreply->node) + 1 + sizeof(int);
48789
48790 thisreply = thisreply->next;
48791 }
48792
48793 /* Add in the size of our header */
48794 message_len = message_len + sizeof(struct clvm_header);
48795 if (!(replybuf = dm_malloc(message_len))) {
48796 DEBUGLOG("Memory allocation fails\n");
48797 return;
48798 }
48799
48800 clientreply = (struct clvm_header *) replybuf;
48801 clientreply->status = status;
48802 clientreply->cmd = CLVMD_CMD_REPLY;
48803 clientreply->node[0] = '\0';
48804 clientreply->xid = 0;
48805 clientreply->clientid = 0;
48806 clientreply->flags = 0;
48807
48808 ptr = clientreply->args;
48809
48810 /* Add in all the replies, and free them as we go */
48811 thisreply = client->bits.localsock.replies;
48812 while (thisreply) {
48813 struct node_reply *tempreply = thisreply;
48814
48815 strcpy(ptr, thisreply->node);
48816 ptr += strlen(thisreply->node) + 1;
48817
48818 if (thisreply->status)
48819 clientreply->flags |= CLVMD_FLAG_NODEERRS;
48820
48821 memcpy(ptr, &thisreply->status, sizeof(int));
48822 ptr += sizeof(int);
48823
48824 if (thisreply->replymsg) {
48825 strcpy(ptr, thisreply->replymsg);
48826 ptr += strlen(thisreply->replymsg) + 1;
48827 } else {
48828 ptr[0] = '\0';
48829 ptr++;
48830 }
48831 thisreply = thisreply->next;
48832
48833 dm_free(tempreply->replymsg);
48834 dm_free(tempreply);
48835 }
48836
48837 /* Terminate with an empty node name */
48838 *ptr = '\0';
48839
48840 clientreply->arglen = ptr - clientreply->args;
48841
48842 /* And send it */
48843 send_message(replybuf, message_len, our_csid, fd,
48844 "Error sending REPLY to client");
48845 dm_free(replybuf);
48846
48847 /* Reset comms variables */
48848 client->bits.localsock.replies = NULL;
48849 client->bits.localsock.expected_replies = 0;
48850 client->bits.localsock.in_progress = FALSE;
48851 client->bits.localsock.sent_out = FALSE;
48852}
48853
48854/* Just free a reply chain baceuse it wasn't used. */
48855static void free_reply(struct local_client *client)
48856{
48857 /* Add in all the replies, and free them as we go */
48858 struct node_reply *thisreply = client->bits.localsock.replies;
48859 while (thisreply) {
48860 struct node_reply *tempreply = thisreply;
48861
48862 thisreply = thisreply->next;
48863
48864 dm_free(tempreply->replymsg);
48865 dm_free(tempreply);
48866 }
48867 client->bits.localsock.replies = NULL;
48868}
48869
48870/* Send our version number to the cluster */
48871static void send_version_message(void)
48872{
48873 char message[sizeof(struct clvm_header) + sizeof(int) * 3];
48874 struct clvm_header *msg = (struct clvm_header *) message;
48875 int version_nums[3] = {
48876 htonl(CLVMD_MAJOR_VERSION),
48877 htonl(CLVMD_MINOR_VERSION),
48878 htonl(CLVMD_PATCH_VERSION)
48879 };
48880
48881 msg->cmd = CLVMD_CMD_VERSION;
48882 msg->status = 0;
48883 msg->flags = 0;
48884 msg->clientid = 0;
48885 msg->arglen = sizeof(version_nums);
48886
48887 memcpy(&msg->args, version_nums, sizeof(version_nums));
48888
48889 hton_clvm(msg);
48890
48891 clops->cluster_send_message(message, sizeof(message), NULL,
48892 "Error Sending version number");
48893}
48894
48895/* Send a message to either a local client or another server */
48896static int send_message(void *buf, int msglen, const char *csid, int fd,
48897 const char *errtext)
48898{
48899 int len = 0;
48900 int ptr;
48901 struct timespec delay;
48902 struct timespec remtime;
48903 int retry_cnt = 0;
48904
48905 /* Send remote messages down the cluster socket */
48906 if (!csid || !ISLOCAL_CSID(csid)) {
48907 hton_clvm((struct clvm_header *) buf);
48908 return clops->cluster_send_message(buf, msglen, csid, errtext);
48909 }
48910
48911 /* Make sure it all goes */
48912 for (ptr = 0; ptr < msglen;) {
48913 if ((len = write(fd, (char*)buf + ptr, msglen - ptr)) <= 0) {
48914 if (errno == EINTR)
48915 continue;
48916 if ((errno == EAGAIN || errno == EIO || errno == ENOSPC) &&
48917 ++retry_cnt < MAX_RETRIES) {
48918 delay.tv_sec = 0;
48919 delay.tv_nsec = 100000;
48920 remtime.tv_sec = 0;
48921 remtime.tv_nsec = 0;
48922 (void) nanosleep (&delay, &remtime);
48923 continue;
48924 }
48925 log_error("%s", errtext);
48926 break;
48927 }
48928 ptr += len;
48929 }
48930
48931 return len;
48932}
48933
48934static int process_work_item(struct lvm_thread_cmd *cmd)
48935{
48936 /* If msg is NULL then this is a cleanup request */
48937 if (cmd->msg == NULL) {
48938 DEBUGLOG("process_work_item: free %p\n", cmd->client);
48939 cmd_client_cleanup(cmd->client);
48940 pthread_mutex_destroy(&cmd->client->bits.localsock.mutex);
48941 pthread_cond_destroy(&cmd->client->bits.localsock.cond);
48942 dm_free(cmd->client);
48943 return 0;
48944 }
48945
48946 if (!cmd->remote) {
48947 DEBUGLOG("process_work_item: local\n");
48948 process_local_command(cmd->msg, cmd->msglen, cmd->client,
48949 cmd->xid);
48950 } else {
48951 DEBUGLOG("process_work_item: remote\n");
48952 process_remote_command(cmd->msg, cmd->msglen, cmd->client->fd,
48953 cmd->csid);
48954 }
48955
48956 return 0;
48957}
48958
48959/*
48960 * Routine that runs in the "LVM thread".
48961 */
48962static void *lvm_thread_fn(void *arg)
48963{
48964 sigset_t ss;
48965 struct lvm_startup_params *lvm_params = arg;
48966 struct lvm_thread_cmd *cmd;
48967
48968 DEBUGLOG("LVM thread function started\n");
48969
48970 /* Ignore SIGUSR1 & 2 */
48971 sigemptyset(&ss);
48972 sigaddset(&ss, SIGUSR1);
48973 sigaddset(&ss, SIGUSR2);
48974 pthread_sigmask(SIG_BLOCK, &ss, NULL);
48975
48976 /* Initialise the interface to liblvm */
48977 init_clvm(lvm_params->excl_uuid);
48978
48979 /* Allow others to get moving */
48980 pthread_barrier_wait(&lvm_start_barrier);
48981 DEBUGLOG("LVM thread ready for work.\n");
48982
48983 /* Now wait for some actual work */
48984 pthread_mutex_lock(&lvm_thread_mutex);
48985
48986 for (;;) {
48987 while (!dm_list_empty(&lvm_cmd_head)) {
48988 cmd = dm_list_item(dm_list_first(&lvm_cmd_head),
48989 struct lvm_thread_cmd);
48990 dm_list_del(&cmd->list);
48991 pthread_mutex_unlock(&lvm_thread_mutex);
48992
48993 process_work_item(cmd);
48994 dm_free(cmd->msg);
48995 dm_free(cmd);
48996
48997 pthread_mutex_lock(&lvm_thread_mutex);
48998 }
48999
49000 if (lvm_thread_exit)
49001 break;
49002
49003 DEBUGLOG("LVM thread waiting for work\n");
49004 pthread_cond_wait(&lvm_thread_cond, &lvm_thread_mutex);
49005 }
49006
49007 pthread_mutex_unlock(&lvm_thread_mutex);
49008 DEBUGLOG("LVM thread exits\n");
49009
49010 destroy_lvm();
49011
49012 pthread_exit(NULL);
49013}
49014
49015/* Pass down some work to the LVM thread */
49016static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
49017 int msglen, const char *csid)
49018{
49019 struct lvm_thread_cmd *cmd;
49020
49021 if (!(cmd = dm_malloc(sizeof(*cmd))))
49022 return ENOMEM;
49023
49024 if (msglen) {
49025 if (!(cmd->msg = dm_malloc(msglen))) {
49026 log_error("Unable to allocate buffer space.");
49027 dm_free(cmd);
49028 return -1;
49029 }
49030 memcpy(cmd->msg, msg, msglen);
49031 }
49032 else
49033 cmd->msg = NULL;
49034
49035 cmd->client = client;
49036 cmd->msglen = msglen;
49037 cmd->xid = client->xid;
49038
49039 if (csid) {
49040 memcpy(cmd->csid, csid, max_csid_len);
49041 cmd->remote = 1;
49042 } else
49043 cmd->remote = 0;
49044
49045 DEBUGLOG("add_to_lvmqueue: cmd=%p. client=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
49046 cmd, client, msg, msglen, csid, cmd->xid);
49047 pthread_mutex_lock(&lvm_thread_mutex);
49048 if (lvm_thread_exit) {
49049 pthread_mutex_unlock(&lvm_thread_mutex);
49050 dm_free(cmd->msg);
49051 dm_free(cmd);
49052 return -1; /* We are about to exit */
49053 }
49054 dm_list_add(&lvm_cmd_head, &cmd->list);
49055 pthread_cond_signal(&lvm_thread_cond);
49056 pthread_mutex_unlock(&lvm_thread_mutex);
49057
49058 return 0;
49059}
49060
49061/* Return 0 if we can talk to an existing clvmd */
49062static int check_local_clvmd(void)
49063{
49064 int local_socket;
49065 int ret = 0;
49066 struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
49067
49068 if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
49069 log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME);
49070 return -1;
49071 }
49072
49073 /* Open local socket */
49074 if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
49075 log_sys_error("socket", "local socket");
49076 return -1;
49077 }
49078
49079 if (connect(local_socket,(struct sockaddr *) &sockaddr,
49080 sizeof(sockaddr))) {
49081 log_sys_error("connect", "local socket");
49082 ret = -1;
49083 }
49084
49085 if (close(local_socket))
49086 log_sys_error("close", "local socket");
49087
49088 return ret;
49089}
49090
49091static void close_local_sock(int local_socket)
49092{
49093 if (local_socket != -1 && close(local_socket))
49094 log_sys_error("close", CLVMD_SOCKNAME);
49095
49096 if (CLVMD_SOCKNAME[0] != '\0' && unlink(CLVMD_SOCKNAME))
49097 stack;
49098}
49099
49100/* Open the local socket, that's the one we talk to libclvm down */
49101static int open_local_sock(void)
49102{
49103 mode_t old_mask;
49104 int local_socket = -1;
49105 struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
49106
49107 if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
49108 log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME);
49109 return -1;
49110 }
49111
49112 close_local_sock(local_socket);
49113
49114 (void) dm_prepare_selinux_context(CLVMD_SOCKNAME, S_IFSOCK);
49115 old_mask = umask(0077);
49116
49117 /* Open local socket */
49118 if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
49119 log_error("Can't create local socket: %m");
49120 goto error;
49121 }
49122
49123 /* Set Close-on-exec & non-blocking */
49124 if (fcntl(local_socket, F_SETFD, 1))
49125 DEBUGLOG("setting CLOEXEC on local_socket failed: %s\n", strerror(errno));
49126 if (fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK))
49127 DEBUGLOG("setting O_NONBLOCK on local_socket failed: %s\n", strerror(errno));
49128
49129
49130 if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
49131 log_error("can't bind local socket: %m");
49132 goto error;
49133 }
49134 if (listen(local_socket, 1) != 0) {
49135 log_error("listen local: %m");
49136 goto error;
49137 }
49138
49139 umask(old_mask);
49140 (void) dm_prepare_selinux_context(NULL, 0);
49141 return local_socket;
49142error:
49143 close_local_sock(local_socket);
49144 umask(old_mask);
49145 (void) dm_prepare_selinux_context(NULL, 0);
49146 return -1;
49147}
49148
49149void process_message(struct local_client *client, char *buf, int len,
49150 const char *csid)
49151{
49152 char nodename[max_cluster_member_name_len];
49153 struct clvm_header *inheader = (struct clvm_header *) buf;
49154 ntoh_clvm(inheader); /* Byteswap fields */
49155
49156 if (verify_message(buf, len) < 0) {
49157 clops->name_from_csid(csid, nodename);
49158 log_error("process_message from %s len %d bad verify.", nodename, len);
49159 dump_message(buf, len);
49160 return;
49161 }
49162
49163 if (inheader->cmd == CLVMD_CMD_REPLY)
49164 process_reply(inheader, len, csid);
49165 else
49166 add_to_lvmqueue(client, inheader, len, csid);
49167}
49168
49169
49170static void check_all_callback(struct local_client *client, const char *csid,
49171 int node_up)
49172{
49173 if (!node_up)
49174 add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running", 18);
49175}
49176
49177/* Check to see if all CLVMDs are running (ie one on
49178 every node in the cluster).
49179 If not, returns -1 and prints out a list of errant nodes */
49180static int check_all_clvmds_running(struct local_client *client)
49181{
49182 DEBUGLOG("check_all_clvmds_running\n");
49183 return clops->cluster_do_node_callback(client, check_all_callback);
49184}
49185
49186/* Return a local_client struct given a client ID.
49187 client IDs are in network byte order */
49188static struct local_client *find_client(int clientid)
49189{
49190 struct local_client *thisfd;
49191
49192 for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next)
49193 if (thisfd->fd == (int)ntohl(clientid))
49194 return thisfd;
49195
49196 return NULL;
49197}
49198
49199/* Byte-swapping routines for the header so we
49200 work in a heterogeneous environment */
49201static void hton_clvm(struct clvm_header *hdr)
49202{
49203 hdr->status = htonl(hdr->status);
49204 hdr->arglen = htonl(hdr->arglen);
49205 hdr->xid = htons(hdr->xid);
49206 /* Don't swap clientid as it's only a token as far as
49207 remote nodes are concerned */
49208}
49209
49210static void ntoh_clvm(struct clvm_header *hdr)
49211{
49212 hdr->status = ntohl(hdr->status);
49213 hdr->arglen = ntohl(hdr->arglen);
49214 hdr->xid = ntohs(hdr->xid);
49215}
49216
49217/* Handler for SIGUSR2 - sent to kill subthreads */
49218static void sigusr2_handler(int sig)
49219{
49220 DEBUGLOG("SIGUSR2 received\n");
49221 return;
49222}
49223
49224static void sigterm_handler(int sig)
49225{
49226 quit = 1;
49227 return;
49228}
49229
49230static void sighup_handler(int sig)
49231{
49232 reread_config = 1;
49233}
49234
49235int sync_lock(const char *resource, int mode, int flags, int *lockid)
49236{
49237 return clops->sync_lock(resource, mode, flags, lockid);
49238}
49239
49240int sync_unlock(const char *resource, int lockid)
49241{
49242 return clops->sync_unlock(resource, lockid);
49243}
49244
49245static if_type_t parse_cluster_interface(char *ifname)
49246{
49247 if_type_t iface = IF_AUTO;
49248
49249 if (!strcmp(ifname, "auto"))
49250 iface = IF_AUTO;
49251 else if (!strcmp(ifname, "cman"))
49252 iface = IF_CMAN;
49253 else if (!strcmp(ifname, "openais"))
49254 iface = IF_OPENAIS;
49255 else if (!strcmp(ifname, "corosync"))
49256 iface = IF_COROSYNC;
49257 else if (!strcmp(ifname, "singlenode"))
49258 iface = IF_SINGLENODE;
49259
49260 return iface;
49261}
49262
49263/*
49264 * Try and find a cluster system in corosync's objdb, if it is running. This is
49265 * only called if the command-line option is not present, and if it fails
49266 * we still try the interfaces in order.
49267 */
49268static if_type_t get_cluster_type(void)
49269{
49270#ifdef HAVE_COROSYNC_CONFDB_H
49271 confdb_handle_t handle;
49272 if_type_t type = IF_AUTO;
49273 int result;
49274 char buf[255];
49275 size_t namelen = sizeof(buf);
49276 hdb_handle_t cluster_handle;
49277 hdb_handle_t clvmd_handle;
49278 confdb_callbacks_t callbacks = { 0 };
49279
49280 result = confdb_initialize (&handle, &callbacks);
49281 if (result != CS_OK)
49282 return type;
49283
49284 result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
49285 if (result != CS_OK)
49286 goto out;
49287
49288 result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
49289 if (result != CS_OK)
49290 goto out;
49291
49292 result = confdb_object_find_start(handle, cluster_handle);
49293 if (result != CS_OK)
49294 goto out;
49295
49296 result = confdb_object_find(handle, cluster_handle, (void *)"clvmd", strlen("clvmd"), &clvmd_handle);
49297 if (result != CS_OK)
49298 goto out;
49299
49300 result = confdb_key_get(handle, clvmd_handle, (void *)"interface", strlen("interface"), buf, &namelen);
49301 if (result != CS_OK)
49302 goto out;
49303
49304 if (namelen >= sizeof(buf))
49305 namelen = sizeof(buf) - 1;
49306
49307 buf[namelen] = '\0';
49308 type = parse_cluster_interface(buf);
49309 DEBUGLOG("got interface type '%s' from confdb\n", buf);
49310out:
49311 confdb_finalize(handle);
49312 return type;
49313#else
49314 return IF_AUTO;
49315#endif
49316}
49317\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/lvm-functions.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003007\013062740170\0022557\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
49318 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
49319 * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
49320 *
49321 * This file is part of LVM2.
49322 *
49323 * This copyrighted material is made available to anyone wishing to use,
49324 * modify, copy, or redistribute it subject to the terms and conditions
49325 * of the GNU General Public License v.2.
49326 *
49327 * You should have received a copy of the GNU General Public License
49328 * along with this program; if not, write to the Free Software Foundation,
49329 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49330 */
49331
49332/* Functions in lvm-functions.c */
49333
49334#ifndef _LVM_FUNCTIONS_H
49335#define _LVM_FUNCTIONS_H
49336
49337extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
49338 char *resource);
49339extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
49340 char *resource);
49341extern const char *do_lock_query(char *resource);
49342extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
49343 char *resource);
49344extern int do_check_lvm1(const char *vgname);
49345extern int do_refresh_cache(void);
49346extern int init_clvm(struct dm_hash_table *excl_uuid);
49347extern void destroy_lvm(void);
49348extern void init_lvhash(void);
49349extern void destroy_lvhash(void);
49350extern void lvm_do_backup(const char *vgname);
49351extern char *get_last_lvm_error(void);
49352extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
49353 char *resource);
49354extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
49355void lvm_do_fs_unlock(void);
49356
49357#endif
49358\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvm.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005541\013062740170\0020721\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
49359 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
49360 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
49361 *
49362 * This file is part of LVM2.
49363 *
49364 * This copyrighted material is made available to anyone wishing to use,
49365 * modify, copy, or redistribute it subject to the terms and conditions
49366 * of the GNU General Public License v.2.
49367 *
49368 * You should have received a copy of the GNU General Public License
49369 * along with this program; if not, write to the Free Software Foundation,
49370 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49371 */
49372
49373/* Definitions for CLVMD server and clients */
49374
49375/*
49376 * The protocol spoken over the cluster and across the local socket.
49377 */
49378
49379#ifndef _CLVM_H
49380#define _CLVM_H
49381
49382#include "configure.h"
49383#include <inttypes.h>
49384
49385struct clvm_header {
49386 uint8_t cmd; /* See below */
49387 uint8_t flags; /* See below */
49388 uint16_t xid; /* Transaction ID */
49389 uint32_t clientid; /* Only used in Daemon->Daemon comms */
49390 int32_t status; /* For replies, whether request succeeded */
49391 uint32_t arglen; /* Length of argument below.
49392 If >1500 then it will be passed
49393 around the cluster in the system LV */
49394 char node[1]; /* Actually a NUL-terminated string, node name.
49395 If this is empty then the command is
49396 forwarded to all cluster nodes unless
49397 FLAG_LOCAL or FLAG_REMOTE is also set. */
49398 char args[1]; /* Arguments for the command follow the
49399 node name, This member is only
49400 valid if the node name is empty */
49401} __attribute__ ((packed));
49402
49403/* Flags */
49404#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
49405#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
49406#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
49407#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
49408
49409/* Name of the local socket to communicate between lvm and clvmd */
49410#define CLVMD_SOCKNAME DEFAULT_RUN_DIR "/clvmd.sock"
49411
49412/* Internal commands & replies */
49413#define CLVMD_CMD_REPLY 1
49414#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
49415#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
49416 an incompatible version */
49417#define CLVMD_CMD_TEST 4 /* Just for mucking about */
49418
49419#define CLVMD_CMD_LOCK 30
49420#define CLVMD_CMD_UNLOCK 31
49421
49422/* Lock/Unlock commands */
49423#define CLVMD_CMD_LOCK_LV 50
49424#define CLVMD_CMD_LOCK_VG 51
49425#define CLVMD_CMD_LOCK_QUERY 52
49426
49427/* Misc functions */
49428#define CLVMD_CMD_REFRESH 40
49429#define CLVMD_CMD_GET_CLUSTERNAME 41
49430#define CLVMD_CMD_SET_DEBUG 42
49431#define CLVMD_CMD_VG_BACKUP 43
49432#define CLVMD_CMD_RESTART 44
49433#define CLVMD_CMD_SYNC_NAMES 45
49434
49435/* Used internally by some callers, but not part of the protocol.*/
49436#ifndef NODE_ALL
49437# define NODE_ALL "*"
49438# define NODE_LOCAL "."
49439# define NODE_REMOTE "^"
49440#endif
49441
49442#endif
49443\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-cman.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000027175\013062740170\0022003\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
49444 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
49445 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
49446 *
49447 * This file is part of LVM2.
49448 *
49449 * This copyrighted material is made available to anyone wishing to use,
49450 * modify, copy, or redistribute it subject to the terms and conditions
49451 * of the GNU General Public License v.2.
49452 *
49453 * You should have received a copy of the GNU General Public License
49454 * along with this program; if not, write to the Free Software Foundation,
49455 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49456 */
49457
49458/*
49459 * CMAN communication layer for clvmd.
49460 */
49461
49462#include "clvmd-common.h"
49463
49464#include <pthread.h>
49465
49466#include "clvmd-comms.h"
49467#include "clvm.h"
49468#include "clvmd.h"
49469#include "lvm-functions.h"
49470
49471#include <libdlm.h>
49472
49473#include <syslog.h>
49474
49475#define LOCKSPACE_NAME "clvmd"
49476
49477struct clvmd_node
49478{
49479 struct cman_node *node;
49480 int clvmd_up;
49481};
49482
49483static int num_nodes;
49484static struct cman_node *nodes = NULL;
49485static struct cman_node this_node;
49486static int count_nodes; /* size of allocated nodes array */
49487static struct dm_hash_table *node_updown_hash;
49488static dlm_lshandle_t *lockspace;
49489static cman_handle_t c_handle;
49490
49491static void count_clvmds_running(void);
49492static void get_members(void);
49493static int nodeid_from_csid(const char *csid);
49494static int name_from_nodeid(int nodeid, char *name);
49495static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
49496static void data_callback(cman_handle_t handle, void *private,
49497 char *buf, int len, uint8_t port, int nodeid);
49498
49499struct lock_wait {
49500 pthread_cond_t cond;
49501 pthread_mutex_t mutex;
49502 struct dlm_lksb lksb;
49503};
49504
49505static int _init_cluster(void)
49506{
49507 node_updown_hash = dm_hash_create(100);
49508
49509 /* Open the cluster communication socket */
49510 c_handle = cman_init(NULL);
49511 if (!c_handle) {
49512 syslog(LOG_ERR, "Can't open cluster manager socket: %m");
49513 return -1;
49514 }
49515 DEBUGLOG("Connected to CMAN\n");
49516
49517 if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
49518 syslog(LOG_ERR, "Can't bind cluster socket: %m");
49519 return -1;
49520 }
49521
49522 if (cman_start_notification(c_handle, event_callback)) {
49523 syslog(LOG_ERR, "Can't start cluster event listening");
49524 return -1;
49525 }
49526
49527 /* Get the cluster members list */
49528 get_members();
49529 count_clvmds_running();
49530
49531 DEBUGLOG("CMAN initialisation complete\n");
49532
49533 /* Create a lockspace for LV & VG locks to live in */
49534 lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
49535 if (!lockspace) {
49536 lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
49537 if (!lockspace) {
49538 syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
49539 return -1;
49540 }
49541 DEBUGLOG("Created DLM lockspace for CLVMD.\n");
49542 } else
49543 DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
49544
49545 dlm_ls_pthread_init(lockspace);
49546 DEBUGLOG("DLM initialisation complete\n");
49547 return 0;
49548}
49549
49550static void _cluster_init_completed(void)
49551{
49552 clvmd_cluster_init_completed();
49553}
49554
49555static int _get_main_cluster_fd(void)
49556{
49557 return cman_get_fd(c_handle);
49558}
49559
49560static int _get_num_nodes(void)
49561{
49562 int i;
49563 int nnodes = 0;
49564
49565 /* return number of ACTIVE nodes */
49566 for (i=0; i<num_nodes; i++) {
49567 if (nodes[i].cn_member && nodes[i].cn_nodeid)
49568 nnodes++;
49569 }
49570 return nnodes;
49571}
49572
49573/* send_message with the fd check removed */
49574static int _cluster_send_message(const void *buf, int msglen, const char *csid,
49575 const char *errtext)
49576{
49577 int nodeid = 0;
49578
49579 if (csid)
49580 memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
49581
49582 if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
49583 {
49584 log_error("%s", errtext);
49585 }
49586 return msglen;
49587}
49588
49589static void _get_our_csid(char *csid)
49590{
49591 if (this_node.cn_nodeid == 0) {
49592 cman_get_node(c_handle, 0, &this_node);
49593 }
49594 memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
49595}
49596
49597/* Call a callback routine for each node is that known (down means not running a clvmd) */
49598static int _cluster_do_node_callback(struct local_client *client,
49599 void (*callback) (struct local_client *,
49600 const char *,
49601 int))
49602{
49603 int i;
49604 int somedown = 0;
49605
49606 for (i = 0; i < _get_num_nodes(); i++) {
49607 if (nodes[i].cn_member && nodes[i].cn_nodeid) {
49608 int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
49609
49610 callback(client, (char *)&nodes[i].cn_nodeid, up);
49611 if (!up)
49612 somedown = -1;
49613 }
49614 }
49615 return somedown;
49616}
49617
49618/* Process OOB messages from the cluster socket */
49619static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
49620{
49621 char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
49622
49623 switch (reason) {
49624 case CMAN_REASON_PORTCLOSED:
49625 name_from_nodeid(arg, namebuf);
49626 log_notice("clvmd on node %s has died\n", namebuf);
49627 DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
49628
49629 dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
49630 break;
49631
49632 case CMAN_REASON_STATECHANGE:
49633 DEBUGLOG("Got state change message, re-reading members list\n");
49634 get_members();
49635 break;
49636
49637#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
49638 case CMAN_REASON_PORTOPENED:
49639 /* Ignore this, wait for startup message from clvmd itself */
49640 break;
49641
49642 case CMAN_REASON_TRY_SHUTDOWN:
49643 DEBUGLOG("Got try shutdown, sending OK\n");
49644 cman_replyto_shutdown(c_handle, 1);
49645 break;
49646#endif
49647 default:
49648 /* ERROR */
49649 DEBUGLOG("Got unknown event callback message: %d\n", reason);
49650 break;
49651 }
49652}
49653
49654static struct local_client *cman_client;
49655static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
49656 const char *csid,
49657 struct local_client **new_client)
49658{
49659
49660 /* Save this for data_callback */
49661 cman_client = fd;
49662
49663 /* We never return a new client */
49664 *new_client = NULL;
49665
49666 return cman_dispatch(c_handle, 0);
49667}
49668
49669
49670static void data_callback(cman_handle_t handle, void *private,
49671 char *buf, int len, uint8_t port, int nodeid)
49672{
49673 /* Ignore looped back messages */
49674 if (nodeid == this_node.cn_nodeid)
49675 return;
49676 process_message(cman_client, buf, len, (char *)&nodeid);
49677}
49678
49679static void _add_up_node(const char *csid)
49680{
49681 /* It's up ! */
49682 int nodeid = nodeid_from_csid(csid);
49683
49684 dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
49685 DEBUGLOG("Added new node %d to updown list\n", nodeid);
49686}
49687
49688static void _cluster_closedown(void)
49689{
49690 dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
49691 cman_finish(c_handle);
49692}
49693
49694static int is_listening(int nodeid)
49695{
49696 int status;
49697
49698 do {
49699 status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
49700 if (status < 0 && errno == EBUSY) { /* Don't busywait */
49701 sleep(1);
49702 errno = EBUSY; /* In case sleep trashes it */
49703 }
49704 }
49705 while (status < 0 && errno == EBUSY);
49706
49707 return status;
49708}
49709
49710/* Populate the list of CLVMDs running.
49711 called only at startup time */
49712static void count_clvmds_running(void)
49713{
49714 int i;
49715
49716 for (i = 0; i < num_nodes; i++) {
49717 int nodeid = nodes[i].cn_nodeid;
49718
49719 if (is_listening(nodeid) == 1)
49720 dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
49721 else
49722 dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
49723 }
49724}
49725
49726/* Get a list of active cluster members */
49727static void get_members(void)
49728{
49729 int retnodes;
49730 int status;
49731 int i;
49732 int high_nodeid = 0;
49733
49734 num_nodes = cman_get_node_count(c_handle);
49735 if (num_nodes == -1) {
49736 log_error("Unable to get node count");
49737 return;
49738 }
49739
49740 /* Not enough room for new nodes list ? */
49741 if (num_nodes > count_nodes && nodes) {
49742 free(nodes);
49743 nodes = NULL;
49744 }
49745
49746 if (nodes == NULL) {
49747 count_nodes = num_nodes + 10; /* Overallocate a little */
49748 nodes = malloc(count_nodes * sizeof(struct cman_node));
49749 if (!nodes) {
49750 log_error("Unable to allocate nodes array\n");
49751 exit(5);
49752 }
49753 }
49754
49755 status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
49756 if (status < 0) {
49757 log_error("Unable to get node details");
49758 exit(6);
49759 }
49760
49761 /* Get the highest nodeid */
49762 for (i=0; i<retnodes; i++) {
49763 if (nodes[i].cn_nodeid > high_nodeid)
49764 high_nodeid = nodes[i].cn_nodeid;
49765 }
49766}
49767
49768
49769/* Convert a node name to a CSID */
49770static int _csid_from_name(char *csid, const char *name)
49771{
49772 int i;
49773
49774 for (i = 0; i < num_nodes; i++) {
49775 if (strcmp(name, nodes[i].cn_name) == 0) {
49776 memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
49777 return 0;
49778 }
49779 }
49780 return -1;
49781}
49782
49783/* Convert a CSID to a node name */
49784static int _name_from_csid(const char *csid, char *name)
49785{
49786 int i;
49787
49788 for (i = 0; i < num_nodes; i++) {
49789 if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
49790 strcpy(name, nodes[i].cn_name);
49791 return 0;
49792 }
49793 }
49794 /* Who?? */
49795 strcpy(name, "Unknown");
49796 return -1;
49797}
49798
49799/* Convert a node ID to a node name */
49800static int name_from_nodeid(int nodeid, char *name)
49801{
49802 int i;
49803
49804 for (i = 0; i < num_nodes; i++) {
49805 if (nodeid == nodes[i].cn_nodeid) {
49806 strcpy(name, nodes[i].cn_name);
49807 return 0;
49808 }
49809 }
49810 /* Who?? */
49811 strcpy(name, "Unknown");
49812 return -1;
49813}
49814
49815/* Convert a CSID to a node ID */
49816static int nodeid_from_csid(const char *csid)
49817{
49818 int nodeid;
49819
49820 memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
49821
49822 return nodeid;
49823}
49824
49825static int _is_quorate(void)
49826{
49827 return cman_is_quorate(c_handle);
49828}
49829
49830static void sync_ast_routine(void *arg)
49831{
49832 struct lock_wait *lwait = arg;
49833
49834 pthread_mutex_lock(&lwait->mutex);
49835 pthread_cond_signal(&lwait->cond);
49836 pthread_mutex_unlock(&lwait->mutex);
49837}
49838
49839static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
49840{
49841 int status;
49842 struct lock_wait lwait;
49843
49844 if (!lockid) {
49845 errno = EINVAL;
49846 return -1;
49847 }
49848
49849 DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
49850 /* Conversions need the lockid in the LKSB */
49851 if (flags & LKF_CONVERT)
49852 lwait.lksb.sb_lkid = *lockid;
49853
49854 pthread_cond_init(&lwait.cond, NULL);
49855 pthread_mutex_init(&lwait.mutex, NULL);
49856 pthread_mutex_lock(&lwait.mutex);
49857
49858 status = dlm_ls_lock(lockspace,
49859 mode,
49860 &lwait.lksb,
49861 flags,
49862 resource,
49863 strlen(resource),
49864 0, sync_ast_routine, &lwait, NULL, NULL);
49865 if (status)
49866 return status;
49867
49868 /* Wait for it to complete */
49869 pthread_cond_wait(&lwait.cond, &lwait.mutex);
49870 pthread_mutex_unlock(&lwait.mutex);
49871
49872 *lockid = lwait.lksb.sb_lkid;
49873
49874 errno = lwait.lksb.sb_status;
49875 DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
49876 if (lwait.lksb.sb_status)
49877 return -1;
49878 else
49879 return 0;
49880}
49881
49882static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
49883{
49884 int status;
49885 struct lock_wait lwait;
49886
49887 DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
49888
49889 pthread_cond_init(&lwait.cond, NULL);
49890 pthread_mutex_init(&lwait.mutex, NULL);
49891 pthread_mutex_lock(&lwait.mutex);
49892
49893 status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
49894
49895 if (status)
49896 return status;
49897
49898 /* Wait for it to complete */
49899 pthread_cond_wait(&lwait.cond, &lwait.mutex);
49900 pthread_mutex_unlock(&lwait.mutex);
49901
49902 errno = lwait.lksb.sb_status;
49903 if (lwait.lksb.sb_status != EUNLOCK)
49904 return -1;
49905 else
49906 return 0;
49907
49908}
49909
49910static int _get_cluster_name(char *buf, int buflen)
49911{
49912 cman_cluster_t cluster_info;
49913 int status;
49914
49915 status = cman_get_cluster(c_handle, &cluster_info);
49916 if (!status) {
49917 strncpy(buf, cluster_info.ci_name, buflen);
49918 }
49919 return status;
49920}
49921
49922static struct cluster_ops _cluster_cman_ops = {
49923 .name = "cman",
49924 .cluster_init_completed = _cluster_init_completed,
49925 .cluster_send_message = _cluster_send_message,
49926 .name_from_csid = _name_from_csid,
49927 .csid_from_name = _csid_from_name,
49928 .get_num_nodes = _get_num_nodes,
49929 .cluster_fd_callback = _cluster_fd_callback,
49930 .get_main_cluster_fd = _get_main_cluster_fd,
49931 .cluster_do_node_callback = _cluster_do_node_callback,
49932 .is_quorate = _is_quorate,
49933 .get_our_csid = _get_our_csid,
49934 .add_up_node = _add_up_node,
49935 .cluster_closedown = _cluster_closedown,
49936 .get_cluster_name = _get_cluster_name,
49937 .sync_lock = _sync_lock,
49938 .sync_unlock = _sync_unlock,
49939};
49940
49941struct cluster_ops *init_cman_cluster(void)
49942{
49943 if (!_init_cluster())
49944 return &_cluster_cman_ops;
49945 else
49946 return NULL;
49947}
49948\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-comms.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007153\013062740170\0022202\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
49949 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
49950 * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
49951 *
49952 * This file is part of LVM2.
49953 *
49954 * This copyrighted material is made available to anyone wishing to use,
49955 * modify, copy, or redistribute it subject to the terms and conditions
49956 * of the GNU General Public License v.2.
49957 *
49958 * You should have received a copy of the GNU General Public License
49959 * along with this program; if not, write to the Free Software Foundation,
49960 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
49961 */
49962
49963/*
49964 * Abstraction layer for clvmd cluster communications
49965 */
49966
49967#ifndef _CLVMD_COMMS_H
49968#define _CLVMD_COMMS_H
49969
49970struct local_client;
49971
49972struct cluster_ops {
49973 const char *name;
49974 void (*cluster_init_completed) (void);
49975
49976 int (*cluster_send_message) (const void *buf, int msglen,
49977 const char *csid,
49978 const char *errtext);
49979 int (*name_from_csid) (const char *csid, char *name);
49980 int (*csid_from_name) (char *csid, const char *name);
49981 int (*get_num_nodes) (void);
49982 int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
49983 const char *csid,
49984 struct local_client **new_client);
49985 int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
49986 int (*cluster_do_node_callback) (struct local_client *client,
49987 void (*callback) (struct local_client *,
49988 const char *csid,
49989 int node_up));
49990 int (*is_quorate) (void);
49991
49992 void (*get_our_csid) (char *csid);
49993 void (*add_up_node) (const char *csid);
49994 void (*reread_config) (void);
49995 void (*cluster_closedown) (void);
49996
49997 int (*get_cluster_name)(char *buf, int buflen);
49998
49999 int (*sync_lock) (const char *resource, int mode,
50000 int flags, int *lockid);
50001 int (*sync_unlock) (const char *resource, int lockid);
50002
50003};
50004
50005#ifdef USE_CMAN
50006# include <netinet/in.h>
50007# include "libcman.h"
50008# define CMAN_MAX_CSID_LEN 4
50009# ifndef MAX_CSID_LEN
50010# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
50011# endif
50012# undef MAX_CLUSTER_MEMBER_NAME_LEN
50013# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
50014# define CMAN_MAX_CLUSTER_MESSAGE 1500
50015# define CLUSTER_PORT_CLVMD 11
50016struct cluster_ops *init_cman_cluster(void);
50017#endif
50018
50019#ifdef USE_OPENAIS
50020# include <openais/saAis.h>
50021# include <corosync/totem/totem.h>
50022# define OPENAIS_CSID_LEN (sizeof(int))
50023# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
50024# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
50025# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
50026# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
50027# endif
50028# ifndef CMAN_MAX_CLUSTER_MESSAGE
50029# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
50030# endif
50031# ifndef MAX_CSID_LEN
50032# define MAX_CSID_LEN sizeof(int)
50033# endif
50034struct cluster_ops *init_openais_cluster(void);
50035#endif
50036
50037#ifdef USE_COROSYNC
50038# include <corosync/corotypes.h>
50039# define COROSYNC_CSID_LEN (sizeof(int))
50040# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
50041# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
50042# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
50043# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
50044# endif
50045# ifndef CMAN_MAX_CLUSTER_MESSAGE
50046# define CMAN_MAX_CLUSTER_MESSAGE 65535
50047# endif
50048# ifndef MAX_CSID_LEN
50049# define MAX_CSID_LEN sizeof(int)
50050# endif
50051struct cluster_ops *init_corosync_cluster(void);
50052#endif
50053
50054#ifdef USE_SINGLENODE
50055# define SINGLENODE_CSID_LEN (sizeof(int))
50056# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
50057# define MAX_CLUSTER_MEMBER_NAME_LEN 64
50058# endif
50059# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
50060# ifndef MAX_CSID_LEN
50061# define MAX_CSID_LEN sizeof(int)
50062# endif
50063struct cluster_ops *init_singlenode_cluster(void);
50064#endif
50065
50066#endif
50067\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/refresh_clvmd.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001152\013062740170\0022575\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
50068 * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
50069 *
50070 * This file is part of LVM2.
50071 *
50072 * This copyrighted material is made available to anyone wishing to use,
50073 * modify, copy, or redistribute it subject to the terms and conditions
50074 * of the GNU General Public License v.2.
50075 *
50076 * You should have received a copy of the GNU General Public License
50077 * along with this program; if not, write to the Free Software Foundation,
50078 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
50079 */
50080
50081
50082int refresh_clvmd(int all_nodes);
50083int restart_clvmd(int all_nodes);
50084int debug_clvmd(int level, int clusterwide);
50085
50086\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-openais.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000037723\013062740170\0022523\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
50087 * Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
50088 *
50089 * This file is part of LVM2.
50090 *
50091 * This copyrighted material is made available to anyone wishing to use,
50092 * modify, copy, or redistribute it subject to the terms and conditions
50093 * of the GNU Lesser General Public License v.2.1.
50094 *
50095 * You should have received a copy of the GNU Lesser General Public License
50096 * along with this program; if not, write to the Free Software Foundation,
50097 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
50098 */
50099
50100/*
50101 * This provides the interface between clvmd and OpenAIS as the cluster
50102 * and lock manager.
50103 */
50104
50105#include "clvmd-common.h"
50106
50107#include <pthread.h>
50108#include <fcntl.h>
50109#include <syslog.h>
50110
50111#include <openais/saAis.h>
50112#include <openais/saLck.h>
50113
50114#include <corosync/corotypes.h>
50115#include <corosync/cpg.h>
50116
50117#include "locking.h"
50118#include "clvm.h"
50119#include "clvmd-comms.h"
50120#include "lvm-functions.h"
50121#include "clvmd.h"
50122#include "lib.h"
50123
50124/* Timeout value for several openais calls */
50125#define TIMEOUT 10
50126
50127static void openais_cpg_deliver_callback (cpg_handle_t handle,
50128 const struct cpg_name *groupName,
50129 uint32_t nodeid,
50130 uint32_t pid,
50131 void *msg,
50132 size_t msg_len);
50133static void openais_cpg_confchg_callback(cpg_handle_t handle,
50134 const struct cpg_name *groupName,
50135 const struct cpg_address *member_list, size_t member_list_entries,
50136 const struct cpg_address *left_list, size_t left_list_entries,
50137 const struct cpg_address *joined_list, size_t joined_list_entries);
50138
50139static void _cluster_closedown(void);
50140
50141/* Hash list of nodes in the cluster */
50142static struct dm_hash_table *node_hash;
50143
50144/* For associating lock IDs & resource handles */
50145static struct dm_hash_table *lock_hash;
50146
50147/* Number of active nodes */
50148static int num_nodes;
50149static unsigned int our_nodeid;
50150
50151static struct local_client *cluster_client;
50152
50153/* OpenAIS handles */
50154static cpg_handle_t cpg_handle;
50155static SaLckHandleT lck_handle;
50156
50157static struct cpg_name cpg_group_name;
50158
50159/* Openais callback structs */
50160cpg_callbacks_t openais_cpg_callbacks = {
50161 .cpg_deliver_fn = openais_cpg_deliver_callback,
50162 .cpg_confchg_fn = openais_cpg_confchg_callback,
50163};
50164
50165struct node_info
50166{
50167 enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
50168 int nodeid;
50169};
50170
50171struct lock_info
50172{
50173 SaLckResourceHandleT res_handle;
50174 SaLckLockIdT lock_id;
50175 SaNameT lock_name;
50176};
50177
50178/* Set errno to something approximating the right value and return 0 or -1 */
50179static int ais_to_errno(SaAisErrorT err)
50180{
50181 switch(err)
50182 {
50183 case SA_AIS_OK:
50184 return 0;
50185 case SA_AIS_ERR_LIBRARY:
50186 errno = EINVAL;
50187 break;
50188 case SA_AIS_ERR_VERSION:
50189 errno = EINVAL;
50190 break;
50191 case SA_AIS_ERR_INIT:
50192 errno = EINVAL;
50193 break;
50194 case SA_AIS_ERR_TIMEOUT:
50195 errno = ETIME;
50196 break;
50197 case SA_AIS_ERR_TRY_AGAIN:
50198 errno = EAGAIN;
50199 break;
50200 case SA_AIS_ERR_INVALID_PARAM:
50201 errno = EINVAL;
50202 break;
50203 case SA_AIS_ERR_NO_MEMORY:
50204 errno = ENOMEM;
50205 break;
50206 case SA_AIS_ERR_BAD_HANDLE:
50207 errno = EINVAL;
50208 break;
50209 case SA_AIS_ERR_BUSY:
50210 errno = EBUSY;
50211 break;
50212 case SA_AIS_ERR_ACCESS:
50213 errno = EPERM;
50214 break;
50215 case SA_AIS_ERR_NOT_EXIST:
50216 errno = ENOENT;
50217 break;
50218 case SA_AIS_ERR_NAME_TOO_LONG:
50219 errno = ENAMETOOLONG;
50220 break;
50221 case SA_AIS_ERR_EXIST:
50222 errno = EEXIST;
50223 break;
50224 case SA_AIS_ERR_NO_SPACE:
50225 errno = ENOSPC;
50226 break;
50227 case SA_AIS_ERR_INTERRUPT:
50228 errno = EINTR;
50229 break;
50230 case SA_AIS_ERR_NAME_NOT_FOUND:
50231 errno = ENOENT;
50232 break;
50233 case SA_AIS_ERR_NO_RESOURCES:
50234 errno = ENOMEM;
50235 break;
50236 case SA_AIS_ERR_NOT_SUPPORTED:
50237 errno = EOPNOTSUPP;
50238 break;
50239 case SA_AIS_ERR_BAD_OPERATION:
50240 errno = EINVAL;
50241 break;
50242 case SA_AIS_ERR_FAILED_OPERATION:
50243 errno = EIO;
50244 break;
50245 case SA_AIS_ERR_MESSAGE_ERROR:
50246 errno = EIO;
50247 break;
50248 case SA_AIS_ERR_QUEUE_FULL:
50249 errno = EXFULL;
50250 break;
50251 case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
50252 errno = EINVAL;
50253 break;
50254 case SA_AIS_ERR_BAD_FLAGS:
50255 errno = EINVAL;
50256 break;
50257 case SA_AIS_ERR_TOO_BIG:
50258 errno = E2BIG;
50259 break;
50260 case SA_AIS_ERR_NO_SECTIONS:
50261 errno = ENOMEM;
50262 break;
50263 default:
50264 errno = EINVAL;
50265 break;
50266 }
50267 return -1;
50268}
50269
50270static char *print_openais_csid(const char *csid)
50271{
50272 static char buf[128];
50273 int id;
50274
50275 memcpy(&id, csid, sizeof(int));
50276 sprintf(buf, "%d", id);
50277 return buf;
50278}
50279
50280static int add_internal_client(int fd, fd_callback_t callback)
50281{
50282 struct local_client *client;
50283
50284 DEBUGLOG("Add_internal_client, fd = %d\n", fd);
50285
50286 if (!(client = dm_zalloc(sizeof(*client)))) {
50287 DEBUGLOG("malloc failed\n");
50288 return -1;
50289 }
50290
50291 client->fd = fd;
50292 client->type = CLUSTER_INTERNAL;
50293 client->callback = callback;
50294 add_client(client);
50295
50296 /* Set Close-on-exec */
50297 fcntl(fd, F_SETFD, 1);
50298
50299 return 0;
50300}
50301
50302static void openais_cpg_deliver_callback (cpg_handle_t handle,
50303 const struct cpg_name *groupName,
50304 uint32_t nodeid,
50305 uint32_t pid,
50306 void *msg,
50307 size_t msg_len)
50308{
50309 int target_nodeid;
50310
50311 memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
50312
50313 DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
50314 our_nodeid, nodeid, target_nodeid, msg_len-4);
50315
50316 if (nodeid != our_nodeid)
50317 if (target_nodeid == our_nodeid || target_nodeid == 0)
50318 process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
50319 msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
50320}
50321
50322static void openais_cpg_confchg_callback(cpg_handle_t handle,
50323 const struct cpg_name *groupName,
50324 const struct cpg_address *member_list, size_t member_list_entries,
50325 const struct cpg_address *left_list, size_t left_list_entries,
50326 const struct cpg_address *joined_list, size_t joined_list_entries)
50327{
50328 int i;
50329 struct node_info *ninfo;
50330
50331 DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
50332 FMTsize_t " left, %" PRIsize_t " members\n",
50333 joined_list_entries, left_list_entries, member_list_entries);
50334
50335 for (i=0; i<joined_list_entries; i++) {
50336 ninfo = dm_hash_lookup_binary(node_hash,
50337 (char *)&joined_list[i].nodeid,
50338 OPENAIS_CSID_LEN);
50339 if (!ninfo) {
50340 ninfo = malloc(sizeof(struct node_info));
50341 if (!ninfo) {
50342 break;
50343 }
50344 else {
50345 ninfo->nodeid = joined_list[i].nodeid;
50346 dm_hash_insert_binary(node_hash,
50347 (char *)&ninfo->nodeid,
50348 OPENAIS_CSID_LEN, ninfo);
50349 }
50350 }
50351 ninfo->state = NODE_CLVMD;
50352 }
50353
50354 for (i=0; i<left_list_entries; i++) {
50355 ninfo = dm_hash_lookup_binary(node_hash,
50356 (char *)&left_list[i].nodeid,
50357 OPENAIS_CSID_LEN);
50358 if (ninfo)
50359 ninfo->state = NODE_DOWN;
50360 }
50361
50362 for (i=0; i<member_list_entries; i++) {
50363 if (member_list[i].nodeid == 0) continue;
50364 ninfo = dm_hash_lookup_binary(node_hash,
50365 (char *)&member_list[i].nodeid,
50366 OPENAIS_CSID_LEN);
50367 if (!ninfo) {
50368 ninfo = malloc(sizeof(struct node_info));
50369 if (!ninfo) {
50370 break;
50371 }
50372 else {
50373 ninfo->nodeid = member_list[i].nodeid;
50374 dm_hash_insert_binary(node_hash,
50375 (char *)&ninfo->nodeid,
50376 OPENAIS_CSID_LEN, ninfo);
50377 }
50378 }
50379 ninfo->state = NODE_CLVMD;
50380 }
50381
50382 num_nodes = member_list_entries;
50383}
50384
50385static int lck_dispatch(struct local_client *client, char *buf, int len,
50386 const char *csid, struct local_client **new_client)
50387{
50388 *new_client = NULL;
50389 saLckDispatch(lck_handle, SA_DISPATCH_ONE);
50390 return 1;
50391}
50392
50393static int _init_cluster(void)
50394{
50395 SaAisErrorT err;
50396 SaVersionT ver = { 'B', 1, 1 };
50397 int select_fd;
50398
50399 node_hash = dm_hash_create(100);
50400 lock_hash = dm_hash_create(10);
50401
50402 err = cpg_initialize(&cpg_handle,
50403 &openais_cpg_callbacks);
50404 if (err != SA_AIS_OK) {
50405 syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
50406 err);
50407 DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
50408 return ais_to_errno(err);
50409 }
50410
50411 err = saLckInitialize(&lck_handle,
50412 NULL,
50413 &ver);
50414 if (err != SA_AIS_OK) {
50415 cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
50416 syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
50417 err);
50418 DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
50419 return ais_to_errno(err);
50420 }
50421
50422 /* Connect to the clvmd group */
50423 strcpy((char *)cpg_group_name.value, "clvmd");
50424 cpg_group_name.length = strlen((char *)cpg_group_name.value);
50425 err = cpg_join(cpg_handle, &cpg_group_name);
50426 if (err != SA_AIS_OK) {
50427 cpg_finalize(cpg_handle);
50428 saLckFinalize(lck_handle);
50429 syslog(LOG_ERR, "Cannot join clvmd process group");
50430 DEBUGLOG("Cannot join clvmd process group: %d\n", err);
50431 return ais_to_errno(err);
50432 }
50433
50434 err = cpg_local_get(cpg_handle,
50435 &our_nodeid);
50436 if (err != SA_AIS_OK) {
50437 cpg_finalize(cpg_handle);
50438 saLckFinalize(lck_handle);
50439 syslog(LOG_ERR, "Cannot get local node id\n");
50440 return ais_to_errno(err);
50441 }
50442 DEBUGLOG("Our local node id is %d\n", our_nodeid);
50443
50444 saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
50445 add_internal_client(select_fd, lck_dispatch);
50446
50447 DEBUGLOG("Connected to OpenAIS\n");
50448
50449 return 0;
50450}
50451
50452static void _cluster_closedown(void)
50453{
50454 saLckFinalize(lck_handle);
50455 cpg_finalize(cpg_handle);
50456}
50457
50458static void _get_our_csid(char *csid)
50459{
50460 memcpy(csid, &our_nodeid, sizeof(int));
50461}
50462
50463/* OpenAIS doesn't really have nmode names so we
50464 just use the node ID in hex instead */
50465static int _csid_from_name(char *csid, const char *name)
50466{
50467 int nodeid;
50468 struct node_info *ninfo;
50469
50470 if (sscanf(name, "%x", &nodeid) == 1) {
50471 ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
50472 if (ninfo)
50473 return nodeid;
50474 }
50475 return -1;
50476}
50477
50478static int _name_from_csid(const char *csid, char *name)
50479{
50480 struct node_info *ninfo;
50481
50482 ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
50483 if (!ninfo)
50484 {
50485 sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
50486 return -1;
50487 }
50488
50489 sprintf(name, "%x", ninfo->nodeid);
50490 return 0;
50491}
50492
50493static int _get_num_nodes()
50494{
50495 DEBUGLOG("num_nodes = %d\n", num_nodes);
50496 return num_nodes;
50497}
50498
50499/* Node is now known to be running a clvmd */
50500static void _add_up_node(const char *csid)
50501{
50502 struct node_info *ninfo;
50503
50504 ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
50505 if (!ninfo) {
50506 DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
50507 print_openais_csid(csid));
50508 return;
50509 }
50510
50511 DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
50512
50513 ninfo->state = NODE_CLVMD;
50514
50515 return;
50516}
50517
50518/* Call a callback for each node, so the caller knows whether it's up or down */
50519static int _cluster_do_node_callback(struct local_client *master_client,
50520 void (*callback)(struct local_client *,
50521 const char *csid, int node_up))
50522{
50523 struct dm_hash_node *hn;
50524 struct node_info *ninfo;
50525 int somedown = 0;
50526
50527 dm_hash_iterate(hn, node_hash)
50528 {
50529 char csid[OPENAIS_CSID_LEN];
50530
50531 ninfo = dm_hash_get_data(node_hash, hn);
50532 memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
50533
50534 DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
50535 ninfo->state);
50536
50537 if (ninfo->state != NODE_DOWN)
50538 callback(master_client, csid, ninfo->state == NODE_CLVMD);
50539 if (ninfo->state != NODE_CLVMD)
50540 somedown = -1;
50541 }
50542 return somedown;
50543}
50544
50545/* Real locking */
50546static int _lock_resource(char *resource, int mode, int flags, int *lockid)
50547{
50548 struct lock_info *linfo;
50549 SaLckResourceHandleT res_handle;
50550 SaAisErrorT err;
50551 SaLckLockIdT lock_id;
50552 SaLckLockStatusT lockStatus;
50553
50554 /* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
50555 if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
50556
50557 linfo = malloc(sizeof(struct lock_info));
50558 if (!linfo)
50559 return -1;
50560
50561 DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
50562
50563 linfo->lock_name.length = strlen(resource)+1;
50564 strcpy((char *)linfo->lock_name.value, resource);
50565
50566 err = saLckResourceOpen(lck_handle, &linfo->lock_name,
50567 SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
50568 if (err != SA_AIS_OK)
50569 {
50570 DEBUGLOG("ResourceOpen returned %d\n", err);
50571 free(linfo);
50572 return ais_to_errno(err);
50573 }
50574
50575 err = saLckResourceLock(
50576 res_handle,
50577 &lock_id,
50578 mode,
50579 flags,
50580 0,
50581 SA_TIME_END,
50582 &lockStatus);
50583 if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
50584 {
50585 free(linfo);
50586 saLckResourceClose(res_handle);
50587 return ais_to_errno(err);
50588 }
50589
50590 /* Wait for it to complete */
50591
50592 DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
50593 err, lock_id);
50594
50595 linfo->lock_id = lock_id;
50596 linfo->res_handle = res_handle;
50597
50598 dm_hash_insert(lock_hash, resource, linfo);
50599
50600 return ais_to_errno(err);
50601}
50602
50603
50604static int _unlock_resource(char *resource, int lockid)
50605{
50606 SaAisErrorT err;
50607 struct lock_info *linfo;
50608
50609 DEBUGLOG("unlock_resource %s\n", resource);
50610 linfo = dm_hash_lookup(lock_hash, resource);
50611 if (!linfo)
50612 return 0;
50613
50614 DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
50615 err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
50616 if (err != SA_AIS_OK)
50617 {
50618 DEBUGLOG("Unlock returned %d\n", err);
50619 return ais_to_errno(err);
50620 }
50621
50622 /* Release the resource */
50623 dm_hash_remove(lock_hash, resource);
50624 saLckResourceClose(linfo->res_handle);
50625 free(linfo);
50626
50627 return ais_to_errno(err);
50628}
50629
50630static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
50631{
50632 int status;
50633 char lock1[strlen(resource)+3];
50634 char lock2[strlen(resource)+3];
50635
50636 snprintf(lock1, sizeof(lock1), "%s-1", resource);
50637 snprintf(lock2, sizeof(lock2), "%s-2", resource);
50638
50639 switch (mode)
50640 {
50641 case LCK_EXCL:
50642 status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
50643 if (status)
50644 goto out;
50645
50646 /* If we can't get this lock too then bail out */
50647 status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
50648 lockid);
50649 if (status == SA_LCK_LOCK_NOT_QUEUED)
50650 {
50651 _unlock_resource(lock1, *lockid);
50652 status = -1;
50653 errno = EAGAIN;
50654 }
50655 break;
50656
50657 case LCK_PREAD:
50658 case LCK_READ:
50659 status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
50660 if (status)
50661 goto out;
50662 _unlock_resource(lock2, *lockid);
50663 break;
50664
50665 case LCK_WRITE:
50666 status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
50667 if (status)
50668 goto out;
50669 _unlock_resource(lock1, *lockid);
50670 break;
50671
50672 default:
50673 status = -1;
50674 errno = EINVAL;
50675 break;
50676 }
50677out:
50678 *lockid = mode;
50679 return status;
50680}
50681
50682static int _sync_unlock(const char *resource, int lockid)
50683{
50684 int status = 0;
50685 char lock1[strlen(resource)+3];
50686 char lock2[strlen(resource)+3];
50687
50688 snprintf(lock1, sizeof(lock1), "%s-1", resource);
50689 snprintf(lock2, sizeof(lock2), "%s-2", resource);
50690
50691 _unlock_resource(lock1, lockid);
50692 _unlock_resource(lock2, lockid);
50693
50694 return status;
50695}
50696
50697/* We are always quorate ! */
50698static int _is_quorate()
50699{
50700 return 1;
50701}
50702
50703static int _get_main_cluster_fd(void)
50704{
50705 int select_fd;
50706
50707 cpg_fd_get(cpg_handle, &select_fd);
50708 return select_fd;
50709}
50710
50711static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
50712 const char *csid,
50713 struct local_client **new_client)
50714{
50715 cluster_client = fd;
50716 *new_client = NULL;
50717 cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
50718 return 1;
50719}
50720
50721static int _cluster_send_message(const void *buf, int msglen, const char *csid,
50722 const char *errtext)
50723{
50724 struct iovec iov[2];
50725 SaAisErrorT err;
50726 int target_node;
50727
50728 if (csid)
50729 memcpy(&target_node, csid, OPENAIS_CSID_LEN);
50730 else
50731 target_node = 0;
50732
50733 iov[0].iov_base = &target_node;
50734 iov[0].iov_len = sizeof(int);
50735 iov[1].iov_base = (char *)buf;
50736 iov[1].iov_len = msglen;
50737
50738 err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
50739 return ais_to_errno(err);
50740}
50741
50742/* We don't have a cluster name to report here */
50743static int _get_cluster_name(char *buf, int buflen)
50744{
50745 strncpy(buf, "OpenAIS", buflen);
50746 return 0;
50747}
50748
50749static struct cluster_ops _cluster_openais_ops = {
50750 .name = "openais",
50751 .cluster_init_completed = NULL,
50752 .cluster_send_message = _cluster_send_message,
50753 .name_from_csid = _name_from_csid,
50754 .csid_from_name = _csid_from_name,
50755 .get_num_nodes = _get_num_nodes,
50756 .cluster_fd_callback = _cluster_fd_callback,
50757 .get_main_cluster_fd = _get_main_cluster_fd,
50758 .cluster_do_node_callback = _cluster_do_node_callback,
50759 .is_quorate = _is_quorate,
50760 .get_our_csid = _get_our_csid,
50761 .add_up_node = _add_up_node,
50762 .reread_config = NULL,
50763 .cluster_closedown = _cluster_closedown,
50764 .get_cluster_name = _get_cluster_name,
50765 .sync_lock = _sync_lock,
50766 .sync_unlock = _sync_unlock,
50767};
50768
50769struct cluster_ops *init_openais_cluster(void)
50770{
50771 if (!_init_cluster())
50772 return &_cluster_openais_ops;
50773
50774 return NULL;
50775}
50776\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007653\013062740170\0021073\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
50777 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
50778 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
50779 *
50780 * This file is part of LVM2.
50781 *
50782 * This copyrighted material is made available to anyone wishing to use,
50783 * modify, copy, or redistribute it subject to the terms and conditions
50784 * of the GNU General Public License v.2.
50785 *
50786 * You should have received a copy of the GNU General Public License
50787 * along with this program; if not, write to the Free Software Foundation,
50788 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
50789 */
50790
50791#ifndef _CLVMD_H
50792#define _CLVMD_H
50793
50794#define CLVMD_MAJOR_VERSION 0
50795#define CLVMD_MINOR_VERSION 2
50796#define CLVMD_PATCH_VERSION 1
50797
50798/* Default time (in seconds) we will wait for all remote commands to execute
50799 before declaring them dead */
50800#define DEFAULT_CMD_TIMEOUT 60
50801
50802/* One of these for each reply we get from command execution on a node */
50803struct node_reply {
50804 char node[MAX_CLUSTER_MEMBER_NAME_LEN];
50805 char *replymsg;
50806 int status;
50807 struct node_reply *next;
50808};
50809
50810typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
50811
50812/*
50813 * These exist for the use of local sockets only when we are
50814 * collecting responses from all cluster nodes
50815 */
50816struct localsock_bits {
50817 struct node_reply *replies;
50818 int num_replies;
50819 int expected_replies;
50820 time_t sent_time; /* So we can check for timeouts */
50821 int in_progress; /* Only execute one cmd at a time per client */
50822 int sent_out; /* Flag to indicate that a command was sent
50823 to remote nodes */
50824 void *private; /* Private area for command processor use */
50825 void *cmd; /* Whole command as passed down local socket */
50826 int cmd_len; /* Length of above */
50827 int pipe; /* Pipe to send PRE completion status down */
50828 int finished; /* Flag to tell subthread to exit */
50829 int all_success; /* Set to 0 if any node (or the pre_command)
50830 failed */
50831 int cleanup_needed; /* helper for cleanup_zombie */
50832 struct local_client *pipe_client;
50833 pthread_t threadid;
50834 enum { PRE_COMMAND, POST_COMMAND } state;
50835 pthread_mutex_t mutex; /* Main thread and worker synchronisation */
50836 pthread_cond_t cond;
50837};
50838
50839/* Entries for PIPE clients */
50840struct pipe_bits {
50841 struct local_client *client; /* Actual (localsock) client */
50842 pthread_t threadid; /* Our own copy of the thread id */
50843};
50844
50845/* Entries for Network socket clients */
50846struct netsock_bits {
50847 void *private;
50848 int flags;
50849};
50850
50851typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
50852 const char *csid,
50853 struct local_client ** new_client);
50854
50855/* One of these for each fd we are listening on */
50856struct local_client {
50857 int fd;
50858 enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
50859 LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
50860 struct local_client *next;
50861 unsigned short xid;
50862 fd_callback_t callback;
50863 uint8_t removeme;
50864
50865 union {
50866 struct localsock_bits localsock;
50867 struct pipe_bits pipe;
50868 struct netsock_bits net;
50869 } bits;
50870};
50871
50872#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args)
50873
50874#ifndef max
50875#define max(a,b) ((a)>(b)?(a):(b))
50876#endif
50877
50878/* The real command processor is in clvmd-command.c */
50879extern int do_command(struct local_client *client, struct clvm_header *msg,
50880 int msglen, char **buf, int buflen, int *retlen);
50881
50882/* Pre and post command routines are called only on the local node */
50883extern int do_pre_command(struct local_client *client);
50884extern int do_post_command(struct local_client *client);
50885extern void cmd_client_cleanup(struct local_client *client);
50886extern int add_client(struct local_client *new_client);
50887
50888extern void clvmd_cluster_init_completed(void);
50889extern void process_message(struct local_client *client, char *buf,
50890 int len, const char *csid);
50891extern void debuglog(const char *fmt, ... )
50892 __attribute__ ((format(printf, 1, 2)));
50893
50894void clvmd_set_debug(debug_t new_de);
50895debug_t clvmd_get_debug(void);
50896int clvmd_get_foreground(void);
50897
50898int sync_lock(const char *resource, int mode, int flags, int *lockid);
50899int sync_unlock(const char *resource, int lockid);
50900
50901#endif
50902\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/clvmd-singlenode.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000022647\013062740170\0023213\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
50903 * Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
50904 *
50905 * This file is part of LVM2.
50906 *
50907 * This copyrighted material is made available to anyone wishing to use,
50908 * modify, copy, or redistribute it subject to the terms and conditions
50909 * of the GNU Lesser General Public License v.2.1.
50910 *
50911 * You should have received a copy of the GNU Lesser General Public License
50912 * along with this program; if not, write to the Free Software Foundation,
50913 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
50914 */
50915
50916#include "clvmd-common.h"
50917
50918#include <pthread.h>
50919
50920#include "locking.h"
50921#include "clvm.h"
50922#include "clvmd-comms.h"
50923#include "clvmd.h"
50924
50925#include <sys/un.h>
50926#include <sys/socket.h>
50927#include <fcntl.h>
50928
50929static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
50930static int listen_fd = -1;
50931
50932static struct dm_hash_table *_locks;
50933static int _lockid;
50934
50935static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
50936/* Using one common condition for all locks for simplicity */
50937static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
50938
50939struct lock {
50940 struct dm_list list;
50941 int lockid;
50942 int mode;
50943};
50944
50945static void close_comms(void)
50946{
50947 if (listen_fd != -1 && close(listen_fd))
50948 stack;
50949 (void)unlink(SINGLENODE_CLVMD_SOCKNAME);
50950 listen_fd = -1;
50951}
50952
50953static int init_comms(void)
50954{
50955 mode_t old_mask;
50956 struct sockaddr_un addr = { .sun_family = AF_UNIX };
50957
50958 if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
50959 sizeof(addr.sun_path))) {
50960 DEBUGLOG("%s: singlenode socket name too long.",
50961 SINGLENODE_CLVMD_SOCKNAME);
50962 return -1;
50963 }
50964
50965 close_comms();
50966
50967 (void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
50968 old_mask = umask(0077);
50969
50970 listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
50971 if (listen_fd < 0) {
50972 DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
50973 goto error;
50974 }
50975 /* Set Close-on-exec */
50976 if (fcntl(listen_fd, F_SETFD, 1)) {
50977 DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
50978 goto error;
50979 }
50980
50981 if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
50982 DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
50983 goto error;
50984 }
50985 if (listen(listen_fd, 10) < 0) {
50986 DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
50987 goto error;
50988 }
50989
50990 umask(old_mask);
50991 (void) dm_prepare_selinux_context(NULL, 0);
50992 return 0;
50993error:
50994 umask(old_mask);
50995 (void) dm_prepare_selinux_context(NULL, 0);
50996 close_comms();
50997 return -1;
50998}
50999
51000static int _init_cluster(void)
51001{
51002 int r;
51003
51004 if (!(_locks = dm_hash_create(128))) {
51005 DEBUGLOG("Failed to allocate single-node hash table.\n");
51006 return 1;
51007 }
51008
51009 r = init_comms();
51010 if (r) {
51011 dm_hash_destroy(_locks);
51012 _locks = NULL;
51013 return r;
51014 }
51015
51016 DEBUGLOG("Single-node cluster initialised.\n");
51017 return 0;
51018}
51019
51020static void _cluster_closedown(void)
51021{
51022 close_comms();
51023
51024 /* If there is any awaited resource, kill it softly */
51025 pthread_mutex_lock(&_lock_mutex);
51026 dm_hash_destroy(_locks);
51027 _locks = NULL;
51028 _lockid = 0;
51029 pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
51030 pthread_mutex_unlock(&_lock_mutex);
51031}
51032
51033static void _get_our_csid(char *csid)
51034{
51035 int nodeid = 1;
51036 memcpy(csid, &nodeid, sizeof(int));
51037}
51038
51039static int _csid_from_name(char *csid, const char *name)
51040{
51041 return 1;
51042}
51043
51044static int _name_from_csid(const char *csid, char *name)
51045{
51046 strcpy(name, "SINGLENODE");
51047 return 0;
51048}
51049
51050static int _get_num_nodes(void)
51051{
51052 return 1;
51053}
51054
51055/* Node is now known to be running a clvmd */
51056static void _add_up_node(const char *csid)
51057{
51058}
51059
51060/* Call a callback for each node, so the caller knows whether it's up or down */
51061static int _cluster_do_node_callback(struct local_client *master_client,
51062 void (*callback)(struct local_client *,
51063 const char *csid, int node_up))
51064{
51065 return 0;
51066}
51067
51068int _lock_file(const char *file, uint32_t flags);
51069
51070static const char *_get_mode(int mode)
51071{
51072 switch (mode) {
51073 case LCK_NULL: return "NULL";
51074 case LCK_READ: return "READ";
51075 case LCK_PREAD: return "PREAD";
51076 case LCK_WRITE: return "WRITE";
51077 case LCK_EXCL: return "EXCLUSIVE";
51078 case LCK_UNLOCK: return "UNLOCK";
51079 default: return "????";
51080 }
51081}
51082
51083/* Real locking */
51084static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
51085{
51086 /* DLM table of allowed transition states */
51087 static const int _dlm_table[6][6] = {
51088 /* Mode NL CR CW PR PW EX */
51089 /* NL */ { 1, 1, 1, 1, 1, 1},
51090 /* CR */ { 1, 1, 1, 1, 1, 0},
51091 /* CW */ { 1, 1, 1, 0, 0, 0},
51092 /* PR */ { 1, 1, 0, 1, 0, 0},
51093 /* PW */ { 1, 1, 0, 0, 0, 0},
51094 /* EX */ { 1, 0, 0, 0, 0, 0}
51095 };
51096
51097 struct lock *lck = NULL, *lckt;
51098 struct dm_list *head;
51099
51100 DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
51101 resource, flags,
51102 (flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
51103 ((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
51104 (LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
51105 (flags & LCKF_CONVERT) ? "CONVERT" : "",
51106 _get_mode(mode), mode);
51107
51108 mode &= LCK_TYPE_MASK;
51109 pthread_mutex_lock(&_lock_mutex);
51110
51111retry:
51112 if (!(head = dm_hash_lookup(_locks, resource))) {
51113 if (flags & LCKF_CONVERT) {
51114 /* In real DLM, lock is identified only by lockid, resource is not used */
51115 DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
51116 goto_bad;
51117 }
51118 /* Add new locked resource */
51119 if (!(head = dm_malloc(sizeof(struct dm_list))) ||
51120 !dm_hash_insert(_locks, resource, head)) {
51121 dm_free(head);
51122 goto_bad;
51123 }
51124
51125 dm_list_init(head);
51126 } else /* Update/convert locked resource */
51127 dm_list_iterate_items(lck, head) {
51128 /* Check is all locks are compatible with requested lock */
51129 if (flags & LCKF_CONVERT) {
51130 if (lck->lockid != *lockid)
51131 continue;
51132
51133 DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
51134 resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
51135 dm_list_iterate_items(lckt, head) {
51136 if ((lckt->lockid != *lockid) &&
51137 !_dlm_table[mode][lckt->mode]) {
51138 if (!(flags & LCKF_NOQUEUE) &&
51139 /* TODO: Real dlm uses here conversion queues */
51140 !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
51141 _locks) /* End of the game? */
51142 goto retry;
51143 goto bad;
51144 }
51145 }
51146 lck->mode = mode; /* Lock is now converted */
51147 goto out;
51148 } else if (!_dlm_table[mode][lck->mode]) {
51149 DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
51150 resource, lck->lockid, _get_mode(lck->mode));
51151 if (!(flags & LCKF_NOQUEUE) &&
51152 !pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
51153 _locks) { /* End of the game? */
51154 DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
51155 resource, _get_mode(mode));
51156 goto retry;
51157 }
51158 goto bad;
51159 }
51160 }
51161
51162 if (!(flags & LCKF_CONVERT)) {
51163 if (!(lck = dm_malloc(sizeof(struct lock))))
51164 goto_bad;
51165
51166 *lockid = lck->lockid = ++_lockid;
51167 lck->mode = mode;
51168 dm_list_add(head, &lck->list);
51169 }
51170out:
51171 pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
51172 pthread_mutex_unlock(&_lock_mutex);
51173 DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
51174 resource, lck->lockid, _get_mode(lck->mode));
51175
51176 return 0;
51177bad:
51178 pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
51179 pthread_mutex_unlock(&_lock_mutex);
51180 DEBUGLOG("Failed to lock resource %s\n", resource);
51181
51182 return 1; /* fail */
51183}
51184
51185static int _unlock_resource(const char *resource, int lockid)
51186{
51187 struct lock *lck;
51188 struct dm_list *head;
51189 int r = 1;
51190
51191 if (lockid < 0) {
51192 DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
51193 resource, lockid);
51194 return 1;
51195 }
51196
51197 DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
51198 pthread_mutex_lock(&_lock_mutex);
51199 pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
51200
51201 if (!(head = dm_hash_lookup(_locks, resource))) {
51202 pthread_mutex_unlock(&_lock_mutex);
51203 DEBUGLOG("Resource %s is not locked.\n", resource);
51204 return 1;
51205 }
51206
51207 dm_list_iterate_items(lck, head)
51208 if (lck->lockid == lockid) {
51209 dm_list_del(&lck->list);
51210 dm_free(lck);
51211 r = 0;
51212 goto out;
51213 }
51214
51215 DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid);
51216out:
51217 if (dm_list_empty(head)) {
51218 //DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid);
51219 dm_hash_remove(_locks, resource);
51220 dm_free(head);
51221 }
51222
51223 pthread_mutex_unlock(&_lock_mutex);
51224
51225 return r;
51226}
51227
51228static int _is_quorate(void)
51229{
51230 return 1;
51231}
51232
51233static int _get_main_cluster_fd(void)
51234{
51235 return listen_fd;
51236}
51237
51238static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
51239 const char *csid,
51240 struct local_client **new_client)
51241{
51242 return 1;
51243}
51244
51245static int _cluster_send_message(const void *buf, int msglen,
51246 const char *csid,
51247 const char *errtext)
51248{
51249 return 0;
51250}
51251
51252static int _get_cluster_name(char *buf, int buflen)
51253{
51254 return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1;
51255}
51256
51257static struct cluster_ops _cluster_singlenode_ops = {
51258 .name = "singlenode",
51259 .cluster_init_completed = NULL,
51260 .cluster_send_message = _cluster_send_message,
51261 .name_from_csid = _name_from_csid,
51262 .csid_from_name = _csid_from_name,
51263 .get_num_nodes = _get_num_nodes,
51264 .cluster_fd_callback = _cluster_fd_callback,
51265 .get_main_cluster_fd = _get_main_cluster_fd,
51266 .cluster_do_node_callback = _cluster_do_node_callback,
51267 .is_quorate = _is_quorate,
51268 .get_our_csid = _get_our_csid,
51269 .add_up_node = _add_up_node,
51270 .reread_config = NULL,
51271 .cluster_closedown = _cluster_closedown,
51272 .get_cluster_name = _get_cluster_name,
51273 .sync_lock = _lock_resource,
51274 .sync_unlock = _unlock_resource,
51275};
51276
51277struct cluster_ops *init_singlenode_cluster(void)
51278{
51279 if (!_init_cluster())
51280 return &_cluster_singlenode_ops;
51281
51282 return NULL;
51283}
51284\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/clvmd/lvm-functions.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000056274\013062740170\0022570\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
51285 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
51286 * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
51287 *
51288 * This file is part of LVM2.
51289 *
51290 * This copyrighted material is made available to anyone wishing to use,
51291 * modify, copy, or redistribute it subject to the terms and conditions
51292 * of the GNU General Public License v.2.
51293 *
51294 * You should have received a copy of the GNU General Public License
51295 * along with this program; if not, write to the Free Software Foundation,
51296 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51297 */
51298
51299#include "clvmd-common.h"
51300
51301#include <pthread.h>
51302
51303#include "clvm.h"
51304#include "clvmd-comms.h"
51305#include "clvmd.h"
51306#include "lvm-functions.h"
51307
51308/* LVM2 headers */
51309#include "toolcontext.h"
51310#include "lvmcache.h"
51311#include "lvm-globals.h"
51312#include "activate.h"
51313#include "archiver.h"
51314#include "memlock.h"
51315
51316#include <syslog.h>
51317
51318static struct cmd_context *cmd = NULL;
51319static struct dm_hash_table *lv_hash = NULL;
51320static pthread_mutex_t lv_hash_lock;
51321static pthread_mutex_t lvm_lock;
51322static char last_error[1024];
51323
51324struct lv_info {
51325 int lock_id;
51326 int lock_mode;
51327};
51328
51329static const char *decode_full_locking_cmd(uint32_t cmdl)
51330{
51331 static char buf[128];
51332 const char *type;
51333 const char *scope;
51334 const char *command;
51335
51336 switch (cmdl & LCK_TYPE_MASK) {
51337 case LCK_NULL:
51338 type = "NULL";
51339 break;
51340 case LCK_READ:
51341 type = "READ";
51342 break;
51343 case LCK_PREAD:
51344 type = "PREAD";
51345 break;
51346 case LCK_WRITE:
51347 type = "WRITE";
51348 break;
51349 case LCK_EXCL:
51350 type = "EXCL";
51351 break;
51352 case LCK_UNLOCK:
51353 type = "UNLOCK";
51354 break;
51355 default:
51356 type = "unknown";
51357 break;
51358 }
51359
51360 switch (cmdl & LCK_SCOPE_MASK) {
51361 case LCK_VG:
51362 scope = "VG";
51363 command = "LCK_VG";
51364 break;
51365 case LCK_LV:
51366 scope = "LV";
51367 switch (cmdl & LCK_MASK) {
51368 case LCK_LV_EXCLUSIVE & LCK_MASK:
51369 command = "LCK_LV_EXCLUSIVE";
51370 break;
51371 case LCK_LV_SUSPEND & LCK_MASK:
51372 command = "LCK_LV_SUSPEND";
51373 break;
51374 case LCK_LV_RESUME & LCK_MASK:
51375 command = "LCK_LV_RESUME";
51376 break;
51377 case LCK_LV_ACTIVATE & LCK_MASK:
51378 command = "LCK_LV_ACTIVATE";
51379 break;
51380 case LCK_LV_DEACTIVATE & LCK_MASK:
51381 command = "LCK_LV_DEACTIVATE";
51382 break;
51383 default:
51384 command = "unknown";
51385 break;
51386 }
51387 break;
51388 default:
51389 scope = "unknown";
51390 command = "unknown";
51391 break;
51392 }
51393
51394 sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope,
51395 cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
51396 cmdl & LCK_HOLD ? "|HOLD" : "",
51397 cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
51398 cmdl & LCK_CACHE ? "|CACHE" : "");
51399
51400 return buf;
51401}
51402
51403/*
51404 * Only processes 8 bits: excludes LCK_CACHE.
51405 */
51406static const char *decode_locking_cmd(unsigned char cmdl)
51407{
51408 return decode_full_locking_cmd((uint32_t) cmdl);
51409}
51410
51411static const char *decode_flags(unsigned char flags)
51412{
51413 static char buf[128];
51414 int len;
51415
51416 len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s%s)", flags,
51417 flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
51418 flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
51419 flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
51420 flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
51421 flags & LCK_TEST_MODE ? "TEST|" : "",
51422 flags & LCK_CONVERT_MODE ? "CONVERT|" : "",
51423 flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
51424 flags & LCK_REVERT_MODE ? "REVERT|" : "");
51425
51426 if (len > 1)
51427 buf[len - 2] = ' ';
51428 else
51429 buf[0] = '\0';
51430
51431 return buf;
51432}
51433
51434char *get_last_lvm_error(void)
51435{
51436 return last_error;
51437}
51438
51439/*
51440 * Hash lock info helpers
51441 */
51442static struct lv_info *lookup_info(const char *resource)
51443{
51444 struct lv_info *lvi;
51445
51446 pthread_mutex_lock(&lv_hash_lock);
51447 lvi = dm_hash_lookup(lv_hash, resource);
51448 pthread_mutex_unlock(&lv_hash_lock);
51449
51450 return lvi;
51451}
51452
51453static int insert_info(const char *resource, struct lv_info *lvi)
51454{
51455 int ret;
51456
51457 pthread_mutex_lock(&lv_hash_lock);
51458 ret = dm_hash_insert(lv_hash, resource, lvi);
51459 pthread_mutex_unlock(&lv_hash_lock);
51460
51461 return ret;
51462}
51463
51464static void remove_info(const char *resource)
51465{
51466 int num_open;
51467
51468 pthread_mutex_lock(&lv_hash_lock);
51469 dm_hash_remove(lv_hash, resource);
51470
51471 /* When last lock is remove, validate there are not left opened devices */
51472 if (!dm_hash_get_first(lv_hash)) {
51473 if (critical_section())
51474 log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section.");
51475 if ((num_open = dev_cache_check_for_open_devices()))
51476 log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open);
51477 }
51478
51479 pthread_mutex_unlock(&lv_hash_lock);
51480}
51481
51482/*
51483 * Return the mode a lock is currently held at (or -1 if not held)
51484 */
51485static int get_current_lock(char *resource)
51486{
51487 struct lv_info *lvi;
51488
51489 if ((lvi = lookup_info(resource)))
51490 return lvi->lock_mode;
51491
51492 return -1;
51493}
51494
51495
51496void init_lvhash(void)
51497{
51498 /* Create hash table for keeping LV locks & status */
51499 lv_hash = dm_hash_create(1024);
51500 pthread_mutex_init(&lv_hash_lock, NULL);
51501 pthread_mutex_init(&lvm_lock, NULL);
51502}
51503
51504/* Called at shutdown to tidy the lockspace */
51505void destroy_lvhash(void)
51506{
51507 struct dm_hash_node *v;
51508 struct lv_info *lvi;
51509 char *resource;
51510 int status;
51511
51512 pthread_mutex_lock(&lv_hash_lock);
51513
51514 dm_hash_iterate(v, lv_hash) {
51515 lvi = dm_hash_get_data(lv_hash, v);
51516 resource = dm_hash_get_key(lv_hash, v);
51517
51518 if ((status = sync_unlock(resource, lvi->lock_id)))
51519 DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
51520 status, strerror(errno));
51521 dm_free(lvi);
51522 }
51523
51524 dm_hash_destroy(lv_hash);
51525 lv_hash = NULL;
51526
51527 pthread_mutex_unlock(&lv_hash_lock);
51528}
51529
51530/* Gets a real lock and keeps the info in the hash table */
51531static int hold_lock(char *resource, int mode, int flags)
51532{
51533 int status;
51534 int saved_errno;
51535 struct lv_info *lvi;
51536
51537 /* Mask off invalid options */
51538 flags &= LCKF_NOQUEUE | LCKF_CONVERT;
51539
51540 lvi = lookup_info(resource);
51541
51542 if (lvi) {
51543 if (lvi->lock_mode == mode) {
51544 DEBUGLOG("hold_lock, lock mode %d already held\n",
51545 mode);
51546 return 0;
51547 }
51548 if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
51549 DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
51550 "ignoring LCK_WRITE request\n");
51551 return 0;
51552 }
51553 }
51554
51555 /* Only allow explicit conversions */
51556 if (lvi && !(flags & LCKF_CONVERT)) {
51557 errno = EBUSY;
51558 return -1;
51559 }
51560 if (lvi) {
51561 /* Already exists - convert it */
51562 status = sync_lock(resource, mode, flags, &lvi->lock_id);
51563 saved_errno = errno;
51564 if (!status)
51565 lvi->lock_mode = mode;
51566 else
51567 DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
51568 strerror(errno));
51569 errno = saved_errno;
51570 } else {
51571 if (!(lvi = dm_malloc(sizeof(struct lv_info)))) {
51572 errno = ENOMEM;
51573 return -1;
51574 }
51575
51576 lvi->lock_mode = mode;
51577 lvi->lock_id = 0;
51578 status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
51579 saved_errno = errno;
51580 if (status) {
51581 dm_free(lvi);
51582 DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
51583 strerror(errno));
51584 } else
51585 if (!insert_info(resource, lvi)) {
51586 errno = ENOMEM;
51587 return -1;
51588 }
51589
51590 errno = saved_errno;
51591 }
51592 return status;
51593}
51594
51595/* Unlock and remove it from the hash table */
51596static int hold_unlock(char *resource)
51597{
51598 struct lv_info *lvi;
51599 int status;
51600 int saved_errno;
51601
51602 if (!(lvi = lookup_info(resource))) {
51603 DEBUGLOG("hold_unlock, lock not already held\n");
51604 return 0;
51605 }
51606
51607 status = sync_unlock(resource, lvi->lock_id);
51608 saved_errno = errno;
51609 if (!status) {
51610 remove_info(resource);
51611 dm_free(lvi);
51612 } else {
51613 DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
51614 strerror(errno));
51615 }
51616
51617 errno = saved_errno;
51618 return status;
51619}
51620
51621/* Watch the return codes here.
51622 liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
51623 libdlm API functions return 0 for success, -1 for failure and do set errno.
51624 These functions here return 0 for success or >0 for failure (where the retcode is errno)
51625*/
51626
51627/* Activate LV exclusive or non-exclusive */
51628static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode)
51629{
51630 int oldmode;
51631 int status;
51632 int activate_lv;
51633 int exclusive = 0;
51634 struct lvinfo lvi;
51635
51636 /* Is it already open ? */
51637 oldmode = get_current_lock(resource);
51638 if (oldmode == mode && (command & LCK_CLUSTER_VG)) {
51639 DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
51640 return 0; /* Nothing to do */
51641 }
51642
51643 /* Does the config file want us to activate this LV ? */
51644 if (!lv_activation_filter(cmd, resource, &activate_lv, NULL))
51645 return EIO;
51646
51647 if (!activate_lv)
51648 return 0; /* Success, we did nothing! */
51649
51650 /* Do we need to activate exclusively? */
51651 if ((activate_lv == 2) || (mode == LCK_EXCL)) {
51652 exclusive = 1;
51653 mode = LCK_EXCL;
51654 }
51655
51656 /*
51657 * Try to get the lock if it's a clustered volume group.
51658 * Use lock conversion only if requested, to prevent implicit conversion
51659 * of exclusive lock to shared one during activation.
51660 */
51661 if (!test_mode() && command & LCK_CLUSTER_VG) {
51662 status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? LCKF_CONVERT:0));
51663 if (status) {
51664 /* Return an LVM-sensible error for this.
51665 * Forcing EIO makes the upper level return this text
51666 * rather than the strerror text for EAGAIN.
51667 */
51668 if (errno == EAGAIN) {
51669 sprintf(last_error, "Volume is busy on another node");
51670 errno = EIO;
51671 }
51672 return errno;
51673 }
51674 }
51675
51676 /* If it's suspended then resume it */
51677 if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0))
51678 goto error;
51679
51680 if (lvi.suspended) {
51681 critical_section_inc(cmd, "resuming");
51682 if (!lv_resume(cmd, resource, 0, NULL)) {
51683 critical_section_dec(cmd, "resumed");
51684 goto error;
51685 }
51686 }
51687
51688 /* Now activate it */
51689 if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
51690 goto error;
51691
51692 return 0;
51693
51694error:
51695 if (!test_mode() && (oldmode == -1 || oldmode != mode))
51696 (void)hold_unlock(resource);
51697 return EIO;
51698}
51699
51700/* Resume the LV if it was active */
51701static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags)
51702{
51703 int oldmode, origin_only, exclusive, revert;
51704
51705 /* Is it open ? */
51706 oldmode = get_current_lock(resource);
51707 if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
51708 DEBUGLOG("do_resume_lv, lock not already held\n");
51709 return 0; /* We don't need to do anything */
51710 }
51711 origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
51712 exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
51713 revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
51714
51715 if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert, NULL))
51716 return EIO;
51717
51718 return 0;
51719}
51720
51721/* Suspend the device if active */
51722static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags)
51723{
51724 int oldmode;
51725 unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
51726 unsigned exclusive;
51727
51728 /* Is it open ? */
51729 oldmode = get_current_lock(resource);
51730 if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
51731 DEBUGLOG("do_suspend_lv, lock not already held\n");
51732 return 0; /* Not active, so it's OK */
51733 }
51734
51735 exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
51736
51737 /* Always call lv_suspend to read commited and precommited data */
51738 if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive, NULL, NULL))
51739 return EIO;
51740
51741 return 0;
51742}
51743
51744static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags)
51745{
51746 int oldmode;
51747 int status;
51748
51749 /* Is it open ? */
51750 oldmode = get_current_lock(resource);
51751 if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
51752 DEBUGLOG("do_deactivate_lock, lock not already held\n");
51753 return 0; /* We don't need to do anything */
51754 }
51755
51756 if (!lv_deactivate(cmd, resource, NULL))
51757 return EIO;
51758
51759 if (!test_mode() && command & LCK_CLUSTER_VG) {
51760 status = hold_unlock(resource);
51761 if (status)
51762 return errno;
51763 }
51764
51765 return 0;
51766}
51767
51768const char *do_lock_query(char *resource)
51769{
51770 int mode;
51771 const char *type;
51772
51773 mode = get_current_lock(resource);
51774 switch (mode) {
51775 case LCK_NULL: type = "NL"; break;
51776 case LCK_READ: type = "CR"; break;
51777 case LCK_PREAD:type = "PR"; break;
51778 case LCK_WRITE:type = "PW"; break;
51779 case LCK_EXCL: type = "EX"; break;
51780 default: type = NULL;
51781 }
51782
51783 DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "--");
51784
51785 return type;
51786}
51787
51788/* This is the LOCK_LV part that happens on all nodes in the cluster -
51789 it is responsible for the interaction with device-mapper and LVM */
51790int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
51791{
51792 int status = 0;
51793
51794 DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
51795 resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
51796
51797 if (!cmd->initialized.config || config_files_changed(cmd)) {
51798 /* Reinitialise various settings inc. logging, filters */
51799 if (do_refresh_cache()) {
51800 log_error("Updated config file invalid. Aborting.");
51801 return EINVAL;
51802 }
51803 }
51804
51805 pthread_mutex_lock(&lvm_lock);
51806 init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
51807
51808 if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
51809 init_mirror_in_sync(1);
51810
51811 if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE)
51812 init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
51813 else {
51814 if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
51815 init_dmeventd_monitor(1);
51816 else
51817 init_dmeventd_monitor(0);
51818 }
51819
51820 cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
51821
51822 /* clvmd should never try to read suspended device */
51823 init_ignore_suspended_devices(1);
51824
51825 switch (command & LCK_MASK) {
51826 case LCK_LV_EXCLUSIVE:
51827 status = do_activate_lv(resource, command, lock_flags, LCK_EXCL);
51828 break;
51829
51830 case LCK_LV_SUSPEND:
51831 status = do_suspend_lv(resource, command, lock_flags);
51832 break;
51833
51834 case LCK_UNLOCK:
51835 case LCK_LV_RESUME: /* if active */
51836 status = do_resume_lv(resource, command, lock_flags);
51837 break;
51838
51839 case LCK_LV_ACTIVATE:
51840 status = do_activate_lv(resource, command, lock_flags, LCK_READ);
51841 break;
51842
51843 case LCK_LV_DEACTIVATE:
51844 status = do_deactivate_lv(resource, command, lock_flags);
51845 break;
51846
51847 default:
51848 DEBUGLOG("Invalid LV command 0x%x\n", command);
51849 status = EINVAL;
51850 break;
51851 }
51852
51853 if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
51854 init_mirror_in_sync(0);
51855
51856 cmd->partial_activation = 0;
51857
51858 /* clean the pool for another command */
51859 dm_pool_empty(cmd->mem);
51860 init_test(0);
51861 pthread_mutex_unlock(&lvm_lock);
51862
51863 DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
51864 return status;
51865}
51866
51867/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
51868int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
51869{
51870 /* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
51871 lock out on this node (because we are the node modifying the metadata)
51872 before suspending cluster-wide.
51873 LCKF_CONVERT is used always, local node is going to modify metadata
51874 */
51875 if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
51876 (command & LCK_CLUSTER_VG)) {
51877 DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
51878 resource, decode_locking_cmd(command), decode_flags(lock_flags));
51879
51880 if (!(lock_flags & LCK_TEST_MODE) &&
51881 hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
51882 return errno;
51883 }
51884 return 0;
51885}
51886
51887/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
51888int post_lock_lv(unsigned char command, unsigned char lock_flags,
51889 char *resource)
51890{
51891 int status;
51892 unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
51893
51894 /* Opposite of above, done on resume after a metadata update */
51895 if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
51896 (command & LCK_CLUSTER_VG)) {
51897 int oldmode;
51898
51899 DEBUGLOG("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
51900 resource, decode_locking_cmd(command), decode_flags(lock_flags));
51901
51902 /* If the lock state is PW then restore it to what it was */
51903 oldmode = get_current_lock(resource);
51904 if (oldmode == LCK_WRITE) {
51905 struct lvinfo lvi;
51906
51907 pthread_mutex_lock(&lvm_lock);
51908 status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
51909 pthread_mutex_unlock(&lvm_lock);
51910 if (!status)
51911 return EIO;
51912
51913 if (!(lock_flags & LCK_TEST_MODE)) {
51914 if (lvi.exists) {
51915 if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
51916 return errno;
51917 } else if (hold_unlock(resource))
51918 return errno;
51919 }
51920 }
51921 }
51922 return 0;
51923}
51924
51925/* Check if a VG is in use by LVM1 so we don't stomp on it */
51926int do_check_lvm1(const char *vgname)
51927{
51928 int status;
51929
51930 status = check_lvm1_vg_inactive(cmd, vgname);
51931
51932 return status == 1 ? 0 : EBUSY;
51933}
51934
51935int do_refresh_cache(void)
51936{
51937 DEBUGLOG("Refreshing context\n");
51938 log_notice("Refreshing context");
51939
51940 pthread_mutex_lock(&lvm_lock);
51941
51942 if (!refresh_toolcontext(cmd)) {
51943 pthread_mutex_unlock(&lvm_lock);
51944 return -1;
51945 }
51946
51947 init_full_scan_done(0);
51948 init_ignore_suspended_devices(1);
51949 lvmcache_force_next_label_scan();
51950 lvmcache_label_scan(cmd);
51951 dm_pool_empty(cmd->mem);
51952
51953 pthread_mutex_unlock(&lvm_lock);
51954
51955 return 0;
51956}
51957
51958/*
51959 * Handle VG lock - drop metadata or update lvmcache state
51960 */
51961void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
51962{
51963 uint32_t lock_cmd = command;
51964 char *vgname = resource + 2;
51965
51966 lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
51967
51968 /*
51969 * Check if LCK_CACHE should be set. All P_ locks except # are cache related.
51970 */
51971 if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
51972 lock_cmd |= LCK_CACHE;
51973
51974 DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
51975 resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section());
51976
51977 /* P_#global causes a full cache refresh */
51978 if (!strcmp(resource, "P_" VG_GLOBAL)) {
51979 do_refresh_cache();
51980 return;
51981 }
51982
51983 pthread_mutex_lock(&lvm_lock);
51984 init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
51985
51986 switch (lock_cmd) {
51987 case LCK_VG_COMMIT:
51988 DEBUGLOG("vg_commit notification for VG %s\n", vgname);
51989 lvmcache_commit_metadata(vgname);
51990 break;
51991 case LCK_VG_REVERT:
51992 DEBUGLOG("vg_revert notification for VG %s\n", vgname);
51993 lvmcache_drop_metadata(vgname, 1);
51994 break;
51995 case LCK_VG_DROP_CACHE:
51996 default:
51997 DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
51998 lvmcache_drop_metadata(vgname, 0);
51999 }
52000
52001 init_test(0);
52002 pthread_mutex_unlock(&lvm_lock);
52003}
52004
52005/*
52006 * Ideally, clvmd should be started before any LVs are active
52007 * but this may not be the case...
52008 * I suppose this also comes in handy if clvmd crashes, not that it would!
52009 */
52010static int get_initial_state(struct dm_hash_table *excl_uuid)
52011{
52012 int lock_mode;
52013 char lv[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */
52014 char uuid[65];
52015 char line[255];
52016 char *lvs_cmd;
52017 const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH;
52018 FILE *lvs;
52019
52020 if (dm_asprintf(&lvs_cmd, "%s lvs --config 'log{command_names=0 prefix=\"\"}' "
52021 "--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
52022 lvm_binary) < 0)
52023 return_0;
52024
52025 /* FIXME: Maybe link and use liblvm2cmd directly instead of fork */
52026 if (!(lvs = popen(lvs_cmd, "r"))) {
52027 dm_free(lvs_cmd);
52028 return 0;
52029 }
52030
52031 while (fgets(line, sizeof(line), lvs)) {
52032 if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) {
52033
52034 /* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
52035 if (strlen(vg) == 38 && /* is is a valid UUID ? */
52036 (flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
52037 vg_flags[5] == 'c') { /* is it clustered ? */
52038 /* Convert hyphen-separated UUIDs into one */
52039 memcpy(&uuid[0], &vg[0], 6);
52040 memcpy(&uuid[6], &vg[7], 4);
52041 memcpy(&uuid[10], &vg[12], 4);
52042 memcpy(&uuid[14], &vg[17], 4);
52043 memcpy(&uuid[18], &vg[22], 4);
52044 memcpy(&uuid[22], &vg[27], 4);
52045 memcpy(&uuid[26], &vg[32], 6);
52046 memcpy(&uuid[32], &lv[0], 6);
52047 memcpy(&uuid[38], &lv[7], 4);
52048 memcpy(&uuid[42], &lv[12], 4);
52049 memcpy(&uuid[46], &lv[17], 4);
52050 memcpy(&uuid[50], &lv[22], 4);
52051 memcpy(&uuid[54], &lv[27], 4);
52052 memcpy(&uuid[58], &lv[32], 6);
52053 uuid[64] = '\0';
52054
52055 /* Look for this lock in the list of EX locks
52056 we were passed on the command-line */
52057 lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ?
52058 LCK_EXCL : LCK_READ;
52059
52060 DEBUGLOG("getting initial lock for %s\n", uuid);
52061 if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE))
52062 DEBUGLOG("Failed to hold lock %s\n", uuid);
52063 }
52064 }
52065 }
52066 if (pclose(lvs))
52067 DEBUGLOG("lvs pclose failed: %s\n", strerror(errno));
52068
52069 dm_free(lvs_cmd);
52070
52071 return 1;
52072}
52073
52074static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
52075 const char *message)
52076{
52077
52078 /* Send messages to the normal LVM2 logging system too,
52079 so we get debug output when it's asked for.
52080 We need to NULL the function ptr otherwise it will just call
52081 back into here! */
52082 init_log_fn(NULL);
52083 print_log(level, file, line, dm_errno, "%s", message);
52084 init_log_fn(lvm2_log_fn);
52085
52086 /*
52087 * Ignore non-error messages, but store the latest one for returning
52088 * to the user.
52089 */
52090 if (level != _LOG_ERR && level != _LOG_FATAL)
52091 return;
52092
52093 strncpy(last_error, message, sizeof(last_error));
52094 last_error[sizeof(last_error)-1] = '\0';
52095}
52096
52097/* This checks some basic cluster-LVM configuration stuff */
52098static void check_config(void)
52099{
52100 int locking_type;
52101
52102 locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
52103
52104 if (locking_type == 3) /* compiled-in cluster support */
52105 return;
52106
52107 if (locking_type == 2) { /* External library, check name */
52108 const char *libname;
52109
52110 libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL);
52111 if (libname && strstr(libname, "liblvm2clusterlock.so"))
52112 return;
52113
52114 log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
52115 return;
52116 }
52117 log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
52118}
52119
52120/* Backups up the LVM metadata if it's changed */
52121void lvm_do_backup(const char *vgname)
52122{
52123 struct volume_group * vg;
52124 int consistent = 0;
52125
52126 DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
52127
52128 pthread_mutex_lock(&lvm_lock);
52129
52130 vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, WARN_PV_READ, &consistent);
52131
52132 if (vg && consistent)
52133 check_current_backup(vg);
52134 else
52135 log_error("Error backing up metadata, can't find VG for group %s", vgname);
52136
52137 release_vg(vg);
52138 dm_pool_empty(cmd->mem);
52139
52140 pthread_mutex_unlock(&lvm_lock);
52141}
52142
52143struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
52144{
52145 struct lv_info *lvi;
52146
52147 *name = NULL;
52148 if (!v)
52149 v = dm_hash_get_first(lv_hash);
52150
52151 do {
52152 if (v) {
52153 lvi = dm_hash_get_data(lv_hash, v);
52154 DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
52155
52156 if (lvi->lock_mode == LCK_EXCL) {
52157 *name = dm_hash_get_key(lv_hash, v);
52158 }
52159 v = dm_hash_get_next(lv_hash, v);
52160 }
52161 } while (v && !*name);
52162
52163 if (*name)
52164 DEBUGLOG("returning EXclusive UUID %s\n", *name);
52165 return v;
52166}
52167
52168void lvm_do_fs_unlock(void)
52169{
52170 pthread_mutex_lock(&lvm_lock);
52171 DEBUGLOG("Syncing device names\n");
52172 fs_unlock();
52173 pthread_mutex_unlock(&lvm_lock);
52174}
52175
52176/* Called to initialise the LVM context of the daemon */
52177int init_clvm(struct dm_hash_table *excl_uuid)
52178{
52179 /* Use LOG_DAEMON for syslog messages instead of LOG_USER */
52180 init_syslog(LOG_DAEMON);
52181 openlog("clvmd", LOG_PID, LOG_DAEMON);
52182
52183 /* Initialise already held locks */
52184 if (!get_initial_state(excl_uuid))
52185 log_error("Cannot load initial lock states.");
52186
52187 if (!udev_init_library_context())
52188 stack;
52189
52190 if (!(cmd = create_toolcontext(1, NULL, 0, 1, 1, 1))) {
52191 log_error("Failed to allocate command context");
52192 udev_fin_library_context();
52193 return 0;
52194 }
52195
52196 if (stored_errno()) {
52197 destroy_toolcontext(cmd);
52198 return 0;
52199 }
52200
52201 cmd->cmd_line = "clvmd";
52202
52203 /* Check lvm.conf is setup for cluster-LVM */
52204 check_config();
52205 init_ignore_suspended_devices(1);
52206
52207 /* Trap log messages so we can pass them back to the user */
52208 init_log_fn(lvm2_log_fn);
52209 memlock_inc_daemon(cmd);
52210
52211 return 1;
52212}
52213
52214void destroy_lvm(void)
52215{
52216 if (cmd) {
52217 memlock_dec_daemon(cmd);
52218 destroy_toolcontext(cmd);
52219 udev_fin_library_context();
52220 cmd = NULL;
52221 }
52222}
52223\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020316\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/local.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001235\013062740170\0021562\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
52224 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
52225 *
52226 * This copyrighted material is made available to anyone wishing to use,
52227 * modify, copy, or redistribute it subject to the terms and conditions
52228 * of the GNU Lesser General Public License v.2.1.
52229 *
52230 * You should have received a copy of the GNU Lesser General Public License
52231 * along with this program; if not, write to the Free Software Foundation,
52232 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
52233 */
52234#ifndef _LVM_CLOG_LOCAL_H
52235#define _LVM_CLOG_LOCAL_H
52236
52237int init_local(void);
52238void cleanup_local(void);
52239
52240int kernel_send(struct dm_ulog_request *rq);
52241
52242#endif /* _LVM_CLOG_LOCAL_H */
52243\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/link_mon.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005750\013062740170\0022277\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
52244 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
52245 *
52246 * This copyrighted material is made available to anyone wishing to use,
52247 * modify, copy, or redistribute it subject to the terms and conditions
52248 * of the GNU Lesser General Public License v.2.1.
52249 *
52250 * You should have received a copy of the GNU Lesser General Public License
52251 * along with this program; if not, write to the Free Software Foundation,
52252 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
52253 */
52254#include "logging.h"
52255#include "link_mon.h"
52256
52257#include <errno.h>
52258#include <poll.h>
52259#include <stdlib.h>
52260
52261struct link_callback {
52262 int fd;
52263 const char *name;
52264 void *data;
52265 int (*callback)(void *data);
52266
52267 struct link_callback *next;
52268};
52269
52270static unsigned used_pfds = 0;
52271static unsigned free_pfds = 0;
52272static struct pollfd *pfds = NULL;
52273static struct link_callback *callbacks = NULL;
52274
52275int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
52276{
52277 unsigned i;
52278 struct link_callback *lc;
52279
52280 for (i = 0; i < used_pfds; i++) {
52281 if (fd == pfds[i].fd) {
52282 LOG_ERROR("links_register: Duplicate file descriptor");
52283 return -EINVAL;
52284 }
52285 }
52286
52287 lc = malloc(sizeof(*lc));
52288 if (!lc)
52289 return -ENOMEM;
52290
52291 lc->fd = fd;
52292 lc->name = name;
52293 lc->data = data;
52294 lc->callback = callback;
52295
52296 if (!free_pfds) {
52297 struct pollfd *tmp;
52298 tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
52299 if (!tmp) {
52300 free(lc);
52301 return -ENOMEM;
52302 }
52303
52304 pfds = tmp;
52305 free_pfds = used_pfds + 1;
52306 }
52307
52308 free_pfds--;
52309 pfds[used_pfds].fd = fd;
52310 pfds[used_pfds].events = POLLIN;
52311 pfds[used_pfds].revents = 0;
52312 used_pfds++;
52313
52314 lc->next = callbacks;
52315 callbacks = lc;
52316 LOG_DBG("Adding %s/%d", lc->name, lc->fd);
52317 LOG_DBG(" used_pfds = %u, free_pfds = %u",
52318 used_pfds, free_pfds);
52319
52320 return 0;
52321}
52322
52323int links_unregister(int fd)
52324{
52325 unsigned i;
52326 struct link_callback *p, *c;
52327
52328 for (i = 0; i < used_pfds; i++)
52329 if (fd == pfds[i].fd) {
52330 /* entire struct is copied (overwritten) */
52331 pfds[i] = pfds[used_pfds - 1];
52332 used_pfds--;
52333 free_pfds++;
52334 }
52335
52336 for (p = NULL, c = callbacks; c; p = c, c = c->next)
52337 if (fd == c->fd) {
52338 LOG_DBG("Freeing up %s/%d", c->name, c->fd);
52339 LOG_DBG(" used_pfds = %u, free_pfds = %u",
52340 used_pfds, free_pfds);
52341 if (p)
52342 p->next = c->next;
52343 else
52344 callbacks = c->next;
52345 free(c);
52346 break;
52347 }
52348
52349 return 0;
52350}
52351
52352int links_monitor(void)
52353{
52354 unsigned i;
52355 int r;
52356
52357 for (i = 0; i < used_pfds; i++) {
52358 pfds[i].revents = 0;
52359 }
52360
52361 r = poll(pfds, used_pfds, -1);
52362 if (r <= 0)
52363 return r;
52364
52365 r = 0;
52366 /* FIXME: handle POLLHUP */
52367 for (i = 0; i < used_pfds; i++)
52368 if (pfds[i].revents & POLLIN) {
52369 LOG_DBG("Data ready on %d", pfds[i].fd);
52370
52371 /* FIXME: Add this back return 1;*/
52372 r++;
52373 }
52374
52375 return r;
52376}
52377
52378int links_issue_callbacks(void)
52379{
52380 unsigned i;
52381 struct link_callback *lc;
52382
52383 for (i = 0; i < used_pfds; i++)
52384 if (pfds[i].revents & POLLIN)
52385 for (lc = callbacks; lc; lc = lc->next)
52386 if (pfds[i].fd == lc->fd) {
52387 LOG_DBG("Issuing callback on %s/%d",
52388 lc->name, lc->fd);
52389 lc->callback(lc->data);
52390 break;
52391 }
52392 return 0;
52393}
52394\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/cluster.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000144207\013062740170\0022153\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
52395 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
52396 *
52397 * This copyrighted material is made available to anyone wishing to use,
52398 * modify, copy, or redistribute it subject to the terms and conditions
52399 * of the GNU Lesser General Public License v.2.1.
52400 *
52401 * You should have received a copy of the GNU Lesser General Public License
52402 * along with this program; if not, write to the Free Software Foundation,
52403 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
52404 */
52405#include "logging.h"
52406#include "cluster.h"
52407#include "common.h"
52408#include "compat.h"
52409#include "functions.h"
52410#include "link_mon.h"
52411#include "local.h"
52412#include "xlate.h"
52413
52414#include <corosync/cpg.h>
52415#include <errno.h>
52416#include <signal.h>
52417#include <unistd.h>
52418#if CMIRROR_HAS_CHECKPOINT
52419#include <openais/saAis.h>
52420#include <openais/saCkpt.h>
52421
52422/* Open AIS error codes */
52423#define str_ais_error(x) \
52424 ((x) == SA_AIS_OK) ? "SA_AIS_OK" : \
52425 ((x) == SA_AIS_ERR_LIBRARY) ? "SA_AIS_ERR_LIBRARY" : \
52426 ((x) == SA_AIS_ERR_VERSION) ? "SA_AIS_ERR_VERSION" : \
52427 ((x) == SA_AIS_ERR_INIT) ? "SA_AIS_ERR_INIT" : \
52428 ((x) == SA_AIS_ERR_TIMEOUT) ? "SA_AIS_ERR_TIMEOUT" : \
52429 ((x) == SA_AIS_ERR_TRY_AGAIN) ? "SA_AIS_ERR_TRY_AGAIN" : \
52430 ((x) == SA_AIS_ERR_INVALID_PARAM) ? "SA_AIS_ERR_INVALID_PARAM" : \
52431 ((x) == SA_AIS_ERR_NO_MEMORY) ? "SA_AIS_ERR_NO_MEMORY" : \
52432 ((x) == SA_AIS_ERR_BAD_HANDLE) ? "SA_AIS_ERR_BAD_HANDLE" : \
52433 ((x) == SA_AIS_ERR_BUSY) ? "SA_AIS_ERR_BUSY" : \
52434 ((x) == SA_AIS_ERR_ACCESS) ? "SA_AIS_ERR_ACCESS" : \
52435 ((x) == SA_AIS_ERR_NOT_EXIST) ? "SA_AIS_ERR_NOT_EXIST" : \
52436 ((x) == SA_AIS_ERR_NAME_TOO_LONG) ? "SA_AIS_ERR_NAME_TOO_LONG" : \
52437 ((x) == SA_AIS_ERR_EXIST) ? "SA_AIS_ERR_EXIST" : \
52438 ((x) == SA_AIS_ERR_NO_SPACE) ? "SA_AIS_ERR_NO_SPACE" : \
52439 ((x) == SA_AIS_ERR_INTERRUPT) ? "SA_AIS_ERR_INTERRUPT" : \
52440 ((x) == SA_AIS_ERR_NAME_NOT_FOUND) ? "SA_AIS_ERR_NAME_NOT_FOUND" : \
52441 ((x) == SA_AIS_ERR_NO_RESOURCES) ? "SA_AIS_ERR_NO_RESOURCES" : \
52442 ((x) == SA_AIS_ERR_NOT_SUPPORTED) ? "SA_AIS_ERR_NOT_SUPPORTED" : \
52443 ((x) == SA_AIS_ERR_BAD_OPERATION) ? "SA_AIS_ERR_BAD_OPERATION" : \
52444 ((x) == SA_AIS_ERR_FAILED_OPERATION) ? "SA_AIS_ERR_FAILED_OPERATION" : \
52445 ((x) == SA_AIS_ERR_MESSAGE_ERROR) ? "SA_AIS_ERR_MESSAGE_ERROR" : \
52446 ((x) == SA_AIS_ERR_QUEUE_FULL) ? "SA_AIS_ERR_QUEUE_FULL" : \
52447 ((x) == SA_AIS_ERR_QUEUE_NOT_AVAILABLE) ? "SA_AIS_ERR_QUEUE_NOT_AVAILABLE" : \
52448 ((x) == SA_AIS_ERR_BAD_FLAGS) ? "SA_AIS_ERR_BAD_FLAGS" : \
52449 ((x) == SA_AIS_ERR_TOO_BIG) ? "SA_AIS_ERR_TOO_BIG" : \
52450 ((x) == SA_AIS_ERR_NO_SECTIONS) ? "SA_AIS_ERR_NO_SECTIONS" : \
52451 "ais_error_unknown"
52452#else
52453#define str_ais_error(x) \
52454 ((x) == CS_OK) ? "CS_OK" : \
52455 ((x) == CS_ERR_LIBRARY) ? "CS_ERR_LIBRARY" : \
52456 ((x) == CS_ERR_VERSION) ? "CS_ERR_VERSION" : \
52457 ((x) == CS_ERR_INIT) ? "CS_ERR_INIT" : \
52458 ((x) == CS_ERR_TIMEOUT) ? "CS_ERR_TIMEOUT" : \
52459 ((x) == CS_ERR_TRY_AGAIN) ? "CS_ERR_TRY_AGAIN" : \
52460 ((x) == CS_ERR_INVALID_PARAM) ? "CS_ERR_INVALID_PARAM" : \
52461 ((x) == CS_ERR_NO_MEMORY) ? "CS_ERR_NO_MEMORY" : \
52462 ((x) == CS_ERR_BAD_HANDLE) ? "CS_ERR_BAD_HANDLE" : \
52463 ((x) == CS_ERR_BUSY) ? "CS_ERR_BUSY" : \
52464 ((x) == CS_ERR_ACCESS) ? "CS_ERR_ACCESS" : \
52465 ((x) == CS_ERR_NOT_EXIST) ? "CS_ERR_NOT_EXIST" : \
52466 ((x) == CS_ERR_NAME_TOO_LONG) ? "CS_ERR_NAME_TOO_LONG" : \
52467 ((x) == CS_ERR_EXIST) ? "CS_ERR_EXIST" : \
52468 ((x) == CS_ERR_NO_SPACE) ? "CS_ERR_NO_SPACE" : \
52469 ((x) == CS_ERR_INTERRUPT) ? "CS_ERR_INTERRUPT" : \
52470 ((x) == CS_ERR_NAME_NOT_FOUND) ? "CS_ERR_NAME_NOT_FOUND" : \
52471 ((x) == CS_ERR_NO_RESOURCES) ? "CS_ERR_NO_RESOURCES" : \
52472 ((x) == CS_ERR_NOT_SUPPORTED) ? "CS_ERR_NOT_SUPPORTED" : \
52473 ((x) == CS_ERR_BAD_OPERATION) ? "CS_ERR_BAD_OPERATION" : \
52474 ((x) == CS_ERR_FAILED_OPERATION) ? "CS_ERR_FAILED_OPERATION" : \
52475 ((x) == CS_ERR_MESSAGE_ERROR) ? "CS_ERR_MESSAGE_ERROR" : \
52476 ((x) == CS_ERR_QUEUE_FULL) ? "CS_ERR_QUEUE_FULL" : \
52477 ((x) == CS_ERR_QUEUE_NOT_AVAILABLE) ? "CS_ERR_QUEUE_NOT_AVAILABLE" : \
52478 ((x) == CS_ERR_BAD_FLAGS) ? "CS_ERR_BAD_FLAGS" : \
52479 ((x) == CS_ERR_TOO_BIG) ? "CS_ERR_TOO_BIG" : \
52480 ((x) == CS_ERR_NO_SECTIONS) ? "CS_ERR_NO_SECTIONS" : \
52481 ((x) == CS_ERR_CONTEXT_NOT_FOUND) ? "CS_ERR_CONTEXT_NOT_FOUND" : \
52482 ((x) == CS_ERR_TOO_MANY_GROUPS) ? "CS_ERR_TOO_MANY_GROUPS" : \
52483 ((x) == CS_ERR_SECURITY) ? "CS_ERR_SECURITY" : \
52484 "cs_error_unknown"
52485#endif
52486
52487#define _RQ_TYPE(x) \
52488 ((x) == DM_ULOG_CHECKPOINT_READY) ? "DM_ULOG_CHECKPOINT_READY": \
52489 ((x) == DM_ULOG_MEMBER_JOIN) ? "DM_ULOG_MEMBER_JOIN": \
52490 RQ_TYPE((x) & ~DM_ULOG_RESPONSE)
52491
52492static uint32_t my_cluster_id = 0xDEAD;
52493#if CMIRROR_HAS_CHECKPOINT
52494static SaCkptHandleT ckpt_handle = 0;
52495static SaCkptCallbacksT callbacks = { 0, 0 };
52496static SaVersionT version = { 'B', 1, 1 };
52497#endif
52498
52499#define DEBUGGING_HISTORY 100
52500#define DEBUGGING_BUFLEN 128
52501#define LOG_SPRINT(cc, f, arg...) do { \
52502 cc->idx++; \
52503 cc->idx = cc->idx % DEBUGGING_HISTORY; \
52504 snprintf(cc->debugging[cc->idx], DEBUGGING_BUFLEN, f, ## arg); \
52505 } while (0)
52506
52507static int log_resp_rec = 0;
52508
52509#define RECOVERING_REGION_SECTION_SIZE 64
52510struct checkpoint_data {
52511 uint32_t requester;
52512 char uuid[CPG_MAX_NAME_LENGTH];
52513
52514 int bitmap_size; /* in bytes */
52515 char *sync_bits;
52516 char *clean_bits;
52517 char *recovering_region;
52518 struct checkpoint_data *next;
52519};
52520
52521#define INVALID 0
52522#define VALID 1
52523#define LEAVING 2
52524
52525#define MAX_CHECKPOINT_REQUESTERS 10
52526struct clog_cpg {
52527 struct dm_list list;
52528
52529 uint32_t lowest_id;
52530 cpg_handle_t handle;
52531 struct cpg_name name;
52532 uint64_t luid;
52533
52534 /* Are we the first, or have we received checkpoint? */
52535 int state;
52536 int cpg_state; /* FIXME: debugging */
52537 int free_me;
52538 int delay;
52539 int resend_requests;
52540 struct dm_list startup_list;
52541 struct dm_list working_list;
52542
52543 int checkpoints_needed;
52544 uint32_t checkpoint_requesters[MAX_CHECKPOINT_REQUESTERS];
52545 struct checkpoint_data *checkpoint_list;
52546 int idx;
52547 char debugging[DEBUGGING_HISTORY][DEBUGGING_BUFLEN];
52548};
52549
52550static struct dm_list clog_cpg_list;
52551
52552/*
52553 * cluster_send
52554 * @rq
52555 *
52556 * Returns: 0 on success, -Exxx on error
52557 */
52558int cluster_send(struct clog_request *rq)
52559{
52560 int r;
52561 int found = 0;
52562 struct iovec iov;
52563 struct clog_cpg *entry;
52564
52565 dm_list_iterate_items(entry, &clog_cpg_list)
52566 if (!strncmp(entry->name.value, rq->u_rq.uuid,
52567 CPG_MAX_NAME_LENGTH)) {
52568 found = 1;
52569 break;
52570 }
52571
52572 if (!found) {
52573 rq->u_rq.error = -ENOENT;
52574 return -ENOENT;
52575 }
52576
52577 /*
52578 * Once the request heads for the cluster, the luid looses
52579 * all its meaning.
52580 */
52581 rq->u_rq.luid = 0;
52582
52583 iov.iov_base = rq;
52584 iov.iov_len = sizeof(struct clog_request) + rq->u_rq.data_size;
52585
52586 rq->u.version[0] = xlate64(CLOG_TFR_VERSION);
52587 rq->u.version[1] = CLOG_TFR_VERSION;
52588
52589 r = clog_request_to_network(rq);
52590 if (r < 0)
52591 /* FIXME: Better error code for byteswap failure? */
52592 return -EINVAL;
52593
52594 if (entry->cpg_state != VALID)
52595 return -EINVAL;
52596
52597#if CMIRROR_HAS_CHECKPOINT
52598 do {
52599 int count = 0;
52600
52601 r = cpg_mcast_joined(entry->handle, CPG_TYPE_AGREED, &iov, 1);
52602 if (r != SA_AIS_ERR_TRY_AGAIN)
52603 break;
52604 count++;
52605 if (count < 10)
52606 LOG_PRINT("[%s] Retry #%d of cpg_mcast_joined: %s",
52607 SHORT_UUID(rq->u_rq.uuid), count,
52608 str_ais_error(r));
52609 else if ((count < 100) && !(count % 10))
52610 LOG_ERROR("[%s] Retry #%d of cpg_mcast_joined: %s",
52611 SHORT_UUID(rq->u_rq.uuid), count,
52612 str_ais_error(r));
52613 else if ((count < 1000) && !(count % 100))
52614 LOG_ERROR("[%s] Retry #%d of cpg_mcast_joined: %s",
52615 SHORT_UUID(rq->u_rq.uuid), count,
52616 str_ais_error(r));
52617 else if ((count < 10000) && !(count % 1000))
52618 LOG_ERROR("[%s] Retry #%d of cpg_mcast_joined: %s - "
52619 "OpenAIS not handling the load?",
52620 SHORT_UUID(rq->u_rq.uuid), count,
52621 str_ais_error(r));
52622 usleep(1000);
52623 } while (1);
52624#else
52625 r = cpg_mcast_joined(entry->handle, CPG_TYPE_AGREED, &iov, 1);
52626#endif
52627 if (r == CS_OK)
52628 return 0;
52629
52630 /* error codes found in openais/cpg.h */
52631 LOG_ERROR("cpg_mcast_joined error: %d", r);
52632
52633 rq->u_rq.error = -EBADE;
52634 return -EBADE;
52635}
52636
52637static struct clog_request *get_matching_rq(struct clog_request *rq,
52638 struct dm_list *l)
52639{
52640 struct clog_request *match, *n;
52641
52642 dm_list_iterate_items_gen_safe(match, n, l, u.list)
52643 if (match->u_rq.seq == rq->u_rq.seq) {
52644 dm_list_del(&match->u.list);
52645 return match;
52646 }
52647
52648 return NULL;
52649}
52650
52651static char rq_buffer[DM_ULOG_REQUEST_SIZE];
52652static int handle_cluster_request(struct clog_cpg *entry __attribute__((unused)),
52653 struct clog_request *rq, int server)
52654{
52655 int r = 0;
52656 struct clog_request *tmp = (struct clog_request *)rq_buffer;
52657
52658 /*
52659 * We need a separate dm_ulog_request struct, one that can carry
52660 * a return payload. Otherwise, the memory address after
52661 * rq will be altered - leading to problems
52662 */
52663 memset(rq_buffer, 0, sizeof(rq_buffer));
52664 memcpy(tmp, rq, sizeof(struct clog_request) + rq->u_rq.data_size);
52665
52666 /*
52667 * With resumes, we only handle our own.
52668 * Resume is a special case that requires
52669 * local action (to set up CPG), followed by
52670 * a cluster action to co-ordinate reading
52671 * the disk and checkpointing
52672 */
52673 if (tmp->u_rq.request_type == DM_ULOG_RESUME) {
52674 if (tmp->originator == my_cluster_id) {
52675 r = do_request(tmp, server);
52676
52677 r = kernel_send(&tmp->u_rq);
52678 if (r < 0)
52679 LOG_ERROR("Failed to send resume response to kernel");
52680 }
52681 return r;
52682 }
52683
52684 r = do_request(tmp, server);
52685
52686 if (server &&
52687 (tmp->u_rq.request_type != DM_ULOG_CLEAR_REGION) &&
52688 (tmp->u_rq.request_type != DM_ULOG_POSTSUSPEND)) {
52689 tmp->u_rq.request_type |= DM_ULOG_RESPONSE;
52690
52691 /*
52692 * Errors from previous functions are in the rq struct.
52693 */
52694 r = cluster_send(tmp);
52695 if (r < 0)
52696 LOG_ERROR("cluster_send failed: %s", strerror(-r));
52697 }
52698
52699 return r;
52700}
52701
52702static int handle_cluster_response(struct clog_cpg *entry,
52703 struct clog_request *rq)
52704{
52705 int r = 0;
52706 struct clog_request *orig_rq;
52707
52708 /*
52709 * If I didn't send it, then I don't care about the response
52710 */
52711 if (rq->originator != my_cluster_id)
52712 return 0;
52713
52714 rq->u_rq.request_type &= ~DM_ULOG_RESPONSE;
52715 orig_rq = get_matching_rq(rq, &entry->working_list);
52716
52717 if (!orig_rq) {
52718 /* Unable to find match for response */
52719
52720 LOG_ERROR("[%s] No match for cluster response: %s:%u",
52721 SHORT_UUID(rq->u_rq.uuid),
52722 _RQ_TYPE(rq->u_rq.request_type),
52723 rq->u_rq.seq);
52724
52725 LOG_ERROR("Current local list:");
52726 if (dm_list_empty(&entry->working_list))
52727 LOG_ERROR(" [none]");
52728
52729 dm_list_iterate_items_gen(orig_rq, &entry->working_list, u.list)
52730 LOG_ERROR(" [%s] %s:%u",
52731 SHORT_UUID(orig_rq->u_rq.uuid),
52732 _RQ_TYPE(orig_rq->u_rq.request_type),
52733 orig_rq->u_rq.seq);
52734
52735 return -EINVAL;
52736 }
52737
52738 if (log_resp_rec > 0) {
52739 LOG_COND(log_resend_requests,
52740 "[%s] Response received to %s/#%u",
52741 SHORT_UUID(rq->u_rq.uuid),
52742 _RQ_TYPE(rq->u_rq.request_type),
52743 rq->u_rq.seq);
52744 log_resp_rec--;
52745 }
52746
52747 /* FIXME: Ensure memcpy cannot explode */
52748 memcpy(orig_rq, rq, sizeof(*rq) + rq->u_rq.data_size);
52749
52750 r = kernel_send(&orig_rq->u_rq);
52751 if (r)
52752 LOG_ERROR("Failed to send response to kernel");
52753
52754 free(orig_rq);
52755 return r;
52756}
52757
52758static struct clog_cpg *find_clog_cpg(cpg_handle_t handle)
52759{
52760 struct clog_cpg *match;
52761
52762 dm_list_iterate_items(match, &clog_cpg_list)
52763 if (match->handle == handle)
52764 return match;
52765
52766 return NULL;
52767}
52768
52769/*
52770 * prepare_checkpoint
52771 * @entry: clog_cpg describing the log
52772 * @cp_requester: nodeid requesting the checkpoint
52773 *
52774 * Creates and fills in a new checkpoint_data struct.
52775 *
52776 * Returns: checkpoint_data on success, NULL on error
52777 */
52778static struct checkpoint_data *prepare_checkpoint(struct clog_cpg *entry,
52779 uint32_t cp_requester)
52780{
52781 int r;
52782 struct checkpoint_data *new;
52783
52784 if (entry->state != VALID) {
52785 /*
52786 * We can't store bitmaps yet, because the log is not
52787 * valid yet.
52788 */
52789 LOG_ERROR("Forced to refuse checkpoint for nodeid %u - log not valid yet",
52790 cp_requester);
52791 return NULL;
52792 }
52793
52794 new = malloc(sizeof(*new));
52795 if (!new) {
52796 LOG_ERROR("Unable to create checkpoint data for %u",
52797 cp_requester);
52798 return NULL;
52799 }
52800 memset(new, 0, sizeof(*new));
52801 new->requester = cp_requester;
52802 strncpy(new->uuid, entry->name.value, entry->name.length);
52803
52804 new->bitmap_size = push_state(entry->name.value, entry->luid,
52805 "clean_bits",
52806 &new->clean_bits, cp_requester);
52807 if (new->bitmap_size <= 0) {
52808 LOG_ERROR("Failed to store clean_bits to checkpoint for node %u",
52809 new->requester);
52810 free(new);
52811 return NULL;
52812 }
52813
52814 new->bitmap_size = push_state(entry->name.value, entry->luid,
52815 "sync_bits",
52816 &new->sync_bits, cp_requester);
52817 if (new->bitmap_size <= 0) {
52818 LOG_ERROR("Failed to store sync_bits to checkpoint for node %u",
52819 new->requester);
52820 free(new->clean_bits);
52821 free(new);
52822 return NULL;
52823 }
52824
52825 r = push_state(entry->name.value, entry->luid,
52826 "recovering_region",
52827 &new->recovering_region, cp_requester);
52828 if (r <= 0) {
52829 LOG_ERROR("Failed to store recovering_region to checkpoint for node %u",
52830 new->requester);
52831 free(new->sync_bits);
52832 free(new->clean_bits);
52833 free(new);
52834 return NULL;
52835 }
52836 LOG_DBG("[%s] Checkpoint prepared for node %u:",
52837 SHORT_UUID(new->uuid), new->requester);
52838 LOG_DBG(" bitmap_size = %d", new->bitmap_size);
52839
52840 return new;
52841}
52842
52843/*
52844 * free_checkpoint
52845 * @cp: the checkpoint_data struct to free
52846 *
52847 */
52848static void free_checkpoint(struct checkpoint_data *cp)
52849{
52850 free(cp->recovering_region);
52851 free(cp->sync_bits);
52852 free(cp->clean_bits);
52853 free(cp);
52854}
52855
52856#if CMIRROR_HAS_CHECKPOINT
52857static int export_checkpoint(struct checkpoint_data *cp)
52858{
52859 SaCkptCheckpointCreationAttributesT attr;
52860 SaCkptCheckpointHandleT h;
52861 SaCkptSectionIdT section_id;
52862 SaCkptSectionCreationAttributesT section_attr;
52863 SaCkptCheckpointOpenFlagsT flags;
52864 SaNameT name;
52865 SaAisErrorT rv;
52866 struct clog_request *rq;
52867 int len, r = 0;
52868 char buf[32];
52869
52870 LOG_DBG("Sending checkpointed data to %u", cp->requester);
52871
52872 len = snprintf((char *)(name.value), SA_MAX_NAME_LENGTH,
52873 "bitmaps_%s_%u", SHORT_UUID(cp->uuid), cp->requester);
52874 name.length = (SaUint16T)len;
52875
52876 len = (int)strlen(cp->recovering_region) + 1;
52877
52878 attr.creationFlags = SA_CKPT_WR_ALL_REPLICAS;
52879 attr.checkpointSize = cp->bitmap_size * 2 + len;
52880
52881 attr.retentionDuration = SA_TIME_MAX;
52882 attr.maxSections = 4; /* don't know why we need +1 */
52883
52884 attr.maxSectionSize = (cp->bitmap_size > len) ? cp->bitmap_size : len;
52885 attr.maxSectionIdSize = 22;
52886
52887 flags = SA_CKPT_CHECKPOINT_READ |
52888 SA_CKPT_CHECKPOINT_WRITE |
52889 SA_CKPT_CHECKPOINT_CREATE;
52890
52891open_retry:
52892 rv = saCkptCheckpointOpen(ckpt_handle, &name, &attr, flags, 0, &h);
52893 if (rv == SA_AIS_ERR_TRY_AGAIN) {
52894 LOG_ERROR("export_checkpoint: ckpt open retry");
52895 usleep(1000);
52896 goto open_retry;
52897 }
52898
52899 if (rv == SA_AIS_ERR_EXIST) {
52900 LOG_DBG("export_checkpoint: checkpoint already exists");
52901 return -EEXIST;
52902 }
52903
52904 if (rv != SA_AIS_OK) {
52905 LOG_ERROR("[%s] Failed to open checkpoint for %u: %s",
52906 SHORT_UUID(cp->uuid), cp->requester,
52907 str_ais_error(rv));
52908 return -EIO; /* FIXME: better error */
52909 }
52910
52911 /*
52912 * Add section for sync_bits
52913 */
52914 section_id.idLen = (SaUint16T)snprintf(buf, 32, "sync_bits");
52915 section_id.id = (unsigned char *)buf;
52916 section_attr.sectionId = &section_id;
52917 section_attr.expirationTime = SA_TIME_END;
52918
52919sync_create_retry:
52920 rv = saCkptSectionCreate(h, &section_attr,
52921 cp->sync_bits, cp->bitmap_size);
52922 if (rv == SA_AIS_ERR_TRY_AGAIN) {
52923 LOG_ERROR("Sync checkpoint section create retry");
52924 usleep(1000);
52925 goto sync_create_retry;
52926 }
52927
52928 if (rv == SA_AIS_ERR_EXIST) {
52929 LOG_DBG("Sync checkpoint section already exists");
52930 saCkptCheckpointClose(h);
52931 return -EEXIST;
52932 }
52933
52934 if (rv != SA_AIS_OK) {
52935 LOG_ERROR("Sync checkpoint section creation failed: %s",
52936 str_ais_error(rv));
52937 saCkptCheckpointClose(h);
52938 return -EIO; /* FIXME: better error */
52939 }
52940
52941 /*
52942 * Add section for clean_bits
52943 */
52944 section_id.idLen = snprintf(buf, 32, "clean_bits");
52945 section_id.id = (unsigned char *)buf;
52946 section_attr.sectionId = &section_id;
52947 section_attr.expirationTime = SA_TIME_END;
52948
52949clean_create_retry:
52950 rv = saCkptSectionCreate(h, &section_attr, cp->clean_bits, cp->bitmap_size);
52951 if (rv == SA_AIS_ERR_TRY_AGAIN) {
52952 LOG_ERROR("Clean checkpoint section create retry");
52953 usleep(1000);
52954 goto clean_create_retry;
52955 }
52956
52957 if (rv == SA_AIS_ERR_EXIST) {
52958 LOG_DBG("Clean checkpoint section already exists");
52959 saCkptCheckpointClose(h);
52960 return -EEXIST;
52961 }
52962
52963 if (rv != SA_AIS_OK) {
52964 LOG_ERROR("Clean checkpoint section creation failed: %s",
52965 str_ais_error(rv));
52966 saCkptCheckpointClose(h);
52967 return -EIO; /* FIXME: better error */
52968 }
52969
52970 /*
52971 * Add section for recovering_region
52972 */
52973 section_id.idLen = snprintf(buf, 32, "recovering_region");
52974 section_id.id = (unsigned char *)buf;
52975 section_attr.sectionId = &section_id;
52976 section_attr.expirationTime = SA_TIME_END;
52977
52978rr_create_retry:
52979 rv = saCkptSectionCreate(h, &section_attr, cp->recovering_region,
52980 strlen(cp->recovering_region) + 1);
52981 if (rv == SA_AIS_ERR_TRY_AGAIN) {
52982 LOG_ERROR("RR checkpoint section create retry");
52983 usleep(1000);
52984 goto rr_create_retry;
52985 }
52986
52987 if (rv == SA_AIS_ERR_EXIST) {
52988 LOG_DBG("RR checkpoint section already exists");
52989 saCkptCheckpointClose(h);
52990 return -EEXIST;
52991 }
52992
52993 if (rv != SA_AIS_OK) {
52994 LOG_ERROR("RR checkpoint section creation failed: %s",
52995 str_ais_error(rv));
52996 saCkptCheckpointClose(h);
52997 return -EIO; /* FIXME: better error */
52998 }
52999
53000 LOG_DBG("export_checkpoint: closing checkpoint");
53001 saCkptCheckpointClose(h);
53002
53003 rq = malloc(DM_ULOG_REQUEST_SIZE);
53004 if (!rq) {
53005 LOG_ERROR("export_checkpoint: Unable to allocate transfer structs");
53006 return -ENOMEM;
53007 }
53008 memset(rq, 0, sizeof(*rq));
53009
53010 dm_list_init(&rq->u.list);
53011 rq->u_rq.request_type = DM_ULOG_CHECKPOINT_READY;
53012 rq->originator = cp->requester; /* FIXME: hack to overload meaning of originator */
53013 strncpy(rq->u_rq.uuid, cp->uuid, CPG_MAX_NAME_LENGTH);
53014 rq->u_rq.seq = my_cluster_id;
53015
53016 r = cluster_send(rq);
53017 if (r)
53018 LOG_ERROR("Failed to send checkpoint ready notice: %s",
53019 strerror(-r));
53020
53021 free(rq);
53022 return 0;
53023}
53024
53025#else
53026static int export_checkpoint(struct checkpoint_data *cp)
53027{
53028 int r, rq_size;
53029 struct clog_request *rq;
53030
53031 rq_size = sizeof(*rq);
53032 rq_size += RECOVERING_REGION_SECTION_SIZE;
53033 rq_size += cp->bitmap_size * 2; /* clean|sync_bits */
53034
53035 rq = malloc(rq_size);
53036 if (!rq) {
53037 LOG_ERROR("export_checkpoint: "
53038 "Unable to allocate transfer structs");
53039 return -ENOMEM;
53040 }
53041 memset(rq, 0, rq_size);
53042
53043 dm_list_init(&rq->u.list);
53044 rq->u_rq.request_type = DM_ULOG_CHECKPOINT_READY;
53045 rq->originator = cp->requester;
53046 strncpy(rq->u_rq.uuid, cp->uuid, CPG_MAX_NAME_LENGTH);
53047 rq->u_rq.seq = my_cluster_id;
53048 rq->u_rq.data_size = rq_size - sizeof(*rq);
53049
53050 /* Sync bits */
53051 memcpy(rq->u_rq.data, cp->sync_bits, cp->bitmap_size);
53052
53053 /* Clean bits */
53054 memcpy(rq->u_rq.data + cp->bitmap_size, cp->clean_bits, cp->bitmap_size);
53055
53056 /* Recovering region */
53057 memcpy(rq->u_rq.data + (cp->bitmap_size * 2), cp->recovering_region,
53058 strlen(cp->recovering_region));
53059
53060 r = cluster_send(rq);
53061 if (r)
53062 LOG_ERROR("Failed to send checkpoint ready notice: %s",
53063 strerror(-r));
53064
53065 free(rq);
53066 return 0;
53067}
53068#endif /* CMIRROR_HAS_CHECKPOINT */
53069
53070#if CMIRROR_HAS_CHECKPOINT
53071static int import_checkpoint(struct clog_cpg *entry, int no_read,
53072 struct clog_request *rq __attribute__((unused)))
53073{
53074 int rtn = 0;
53075 SaCkptCheckpointHandleT h;
53076 SaCkptSectionIterationHandleT itr;
53077 SaCkptSectionDescriptorT desc;
53078 SaCkptIOVectorElementT iov;
53079 SaNameT name;
53080 SaAisErrorT rv;
53081 char *bitmap = NULL;
53082 int len;
53083
53084 bitmap = malloc(1024*1024);
53085 if (!bitmap)
53086 return -ENOMEM;
53087
53088 len = snprintf((char *)(name.value), SA_MAX_NAME_LENGTH, "bitmaps_%s_%u",
53089 SHORT_UUID(entry->name.value), my_cluster_id);
53090 name.length = (SaUint16T)len;
53091
53092open_retry:
53093 rv = saCkptCheckpointOpen(ckpt_handle, &name, NULL,
53094 SA_CKPT_CHECKPOINT_READ, 0, &h);
53095 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53096 LOG_ERROR("import_checkpoint: ckpt open retry");
53097 usleep(1000);
53098 goto open_retry;
53099 }
53100
53101 if (rv != SA_AIS_OK) {
53102 LOG_ERROR("[%s] Failed to open checkpoint: %s",
53103 SHORT_UUID(entry->name.value), str_ais_error(rv));
53104 free(bitmap);
53105 return -EIO; /* FIXME: better error */
53106 }
53107
53108unlink_retry:
53109 rv = saCkptCheckpointUnlink(ckpt_handle, &name);
53110 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53111 LOG_ERROR("import_checkpoint: ckpt unlink retry");
53112 usleep(1000);
53113 goto unlink_retry;
53114 }
53115
53116 if (no_read) {
53117 LOG_DBG("Checkpoint for this log already received");
53118 goto no_read;
53119 }
53120
53121init_retry:
53122 rv = saCkptSectionIterationInitialize(h, SA_CKPT_SECTIONS_ANY,
53123 SA_TIME_END, &itr);
53124 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53125 LOG_ERROR("import_checkpoint: sync create retry");
53126 usleep(1000);
53127 goto init_retry;
53128 }
53129
53130 if (rv != SA_AIS_OK) {
53131 LOG_ERROR("[%s] Sync checkpoint section creation failed: %s",
53132 SHORT_UUID(entry->name.value), str_ais_error(rv));
53133 free(bitmap);
53134 return -EIO; /* FIXME: better error */
53135 }
53136
53137 len = 0;
53138 while (1) {
53139 rv = saCkptSectionIterationNext(itr, &desc);
53140 if (rv == SA_AIS_OK)
53141 len++;
53142 else if ((rv == SA_AIS_ERR_NO_SECTIONS) && len)
53143 break;
53144 else if (rv != SA_AIS_ERR_TRY_AGAIN) {
53145 LOG_ERROR("saCkptSectionIterationNext failure: %d", rv);
53146 break;
53147 }
53148 }
53149 saCkptSectionIterationFinalize(itr);
53150 if (len != 3) {
53151 LOG_ERROR("import_checkpoint: %d checkpoint sections found",
53152 len);
53153 usleep(1000);
53154 goto init_retry;
53155 }
53156 saCkptSectionIterationInitialize(h, SA_CKPT_SECTIONS_ANY,
53157 SA_TIME_END, &itr);
53158
53159 while (1) {
53160 rv = saCkptSectionIterationNext(itr, &desc);
53161 if (rv == SA_AIS_ERR_NO_SECTIONS)
53162 break;
53163
53164 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53165 LOG_ERROR("import_checkpoint: ckpt iternext retry");
53166 usleep(1000);
53167 continue;
53168 }
53169
53170 if (rv != SA_AIS_OK) {
53171 LOG_ERROR("import_checkpoint: clean checkpoint section "
53172 "creation failed: %s", str_ais_error(rv));
53173 rtn = -EIO; /* FIXME: better error */
53174 goto fail;
53175 }
53176
53177 if (!desc.sectionSize) {
53178 LOG_ERROR("Checkpoint section empty");
53179 continue;
53180 }
53181
53182 memset(bitmap, 0, sizeof(*bitmap));
53183 iov.sectionId = desc.sectionId;
53184 iov.dataBuffer = bitmap;
53185 iov.dataSize = desc.sectionSize;
53186 iov.dataOffset = 0;
53187
53188 read_retry:
53189 rv = saCkptCheckpointRead(h, &iov, 1, NULL);
53190 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53191 LOG_ERROR("ckpt read retry");
53192 usleep(1000);
53193 goto read_retry;
53194 }
53195
53196 if (rv != SA_AIS_OK) {
53197 LOG_ERROR("import_checkpoint: ckpt read error: %s",
53198 str_ais_error(rv));
53199 rtn = -EIO; /* FIXME: better error */
53200 goto fail;
53201 }
53202
53203 if (iov.readSize) {
53204 if (pull_state(entry->name.value, entry->luid,
53205 (char *)desc.sectionId.id, bitmap,
53206 iov.readSize)) {
53207 LOG_ERROR("Error loading state");
53208 rtn = -EIO;
53209 goto fail;
53210 }
53211 } else {
53212 /* Need to request new checkpoint */
53213 rtn = -EAGAIN;
53214 goto fail;
53215 }
53216 }
53217
53218fail:
53219 saCkptSectionIterationFinalize(itr);
53220no_read:
53221 saCkptCheckpointClose(h);
53222
53223 free(bitmap);
53224 return rtn;
53225}
53226
53227#else
53228static int import_checkpoint(struct clog_cpg *entry, int no_read,
53229 struct clog_request *rq)
53230{
53231 int bitmap_size;
53232
53233 if (no_read) {
53234 LOG_DBG("Checkpoint for this log already received");
53235 return 0;
53236 }
53237
53238 bitmap_size = (rq->u_rq.data_size - RECOVERING_REGION_SECTION_SIZE) / 2;
53239 if (bitmap_size < 0) {
53240 LOG_ERROR("Checkpoint has invalid payload size.");
53241 return -EINVAL;
53242 }
53243
53244 if (pull_state(entry->name.value, entry->luid, "sync_bits",
53245 rq->u_rq.data, bitmap_size) ||
53246 pull_state(entry->name.value, entry->luid, "clean_bits",
53247 rq->u_rq.data + bitmap_size, bitmap_size) ||
53248 pull_state(entry->name.value, entry->luid, "recovering_region",
53249 rq->u_rq.data + (bitmap_size * 2),
53250 RECOVERING_REGION_SECTION_SIZE)) {
53251 LOG_ERROR("Error loading bitmap state from checkpoint.");
53252 return -EIO;
53253 }
53254 return 0;
53255}
53256#endif /* CMIRROR_HAS_CHECKPOINT */
53257
53258static void do_checkpoints(struct clog_cpg *entry, int leaving)
53259{
53260 struct checkpoint_data *cp;
53261
53262 for (cp = entry->checkpoint_list; cp;) {
53263 /*
53264 * FIXME: Check return code. Could send failure
53265 * notice in rq in export_checkpoint function
53266 * by setting rq->error
53267 */
53268 switch (export_checkpoint(cp)) {
53269 case -EEXIST:
53270 LOG_SPRINT(entry, "[%s] Checkpoint for %u already handled%s",
53271 SHORT_UUID(entry->name.value), cp->requester,
53272 (leaving) ? "(L)": "");
53273 LOG_COND(log_checkpoint,
53274 "[%s] Checkpoint for %u already handled%s",
53275 SHORT_UUID(entry->name.value), cp->requester,
53276 (leaving) ? "(L)": "");
53277 entry->checkpoint_list = cp->next;
53278 free_checkpoint(cp);
53279 cp = entry->checkpoint_list;
53280 break;
53281 case 0:
53282 LOG_SPRINT(entry, "[%s] Checkpoint data available for node %u%s",
53283 SHORT_UUID(entry->name.value), cp->requester,
53284 (leaving) ? "(L)": "");
53285 LOG_COND(log_checkpoint,
53286 "[%s] Checkpoint data available for node %u%s",
53287 SHORT_UUID(entry->name.value), cp->requester,
53288 (leaving) ? "(L)": "");
53289 entry->checkpoint_list = cp->next;
53290 free_checkpoint(cp);
53291 cp = entry->checkpoint_list;
53292 break;
53293 default:
53294 /* FIXME: Skipping will cause list corruption */
53295 LOG_ERROR("[%s] Failed to export checkpoint for %u%s",
53296 SHORT_UUID(entry->name.value), cp->requester,
53297 (leaving) ? "(L)": "");
53298 }
53299 }
53300}
53301
53302static int resend_requests(struct clog_cpg *entry)
53303{
53304 int r = 0;
53305 struct clog_request *rq, *n;
53306
53307 if (!entry->resend_requests || entry->delay)
53308 return 0;
53309
53310 if (entry->state != VALID)
53311 return 0;
53312
53313 entry->resend_requests = 0;
53314
53315 dm_list_iterate_items_gen_safe(rq, n, &entry->working_list, u.list) {
53316 dm_list_del(&rq->u.list);
53317
53318 if (strcmp(entry->name.value, rq->u_rq.uuid)) {
53319 LOG_ERROR("[%s] Stray request from another log (%s)",
53320 SHORT_UUID(entry->name.value),
53321 SHORT_UUID(rq->u_rq.uuid));
53322 free(rq);
53323 continue;
53324 }
53325
53326 switch (rq->u_rq.request_type) {
53327 case DM_ULOG_SET_REGION_SYNC:
53328 /*
53329 * Some requests simply do not need to be resent.
53330 * If it is a request that just changes log state,
53331 * then it doesn't need to be resent (everyone makes
53332 * updates).
53333 */
53334 LOG_COND(log_resend_requests,
53335 "[%s] Skipping resend of %s/#%u...",
53336 SHORT_UUID(entry->name.value),
53337 _RQ_TYPE(rq->u_rq.request_type),
53338 rq->u_rq.seq);
53339 LOG_SPRINT(entry, "### No resend: [%s] %s/%u ###",
53340 SHORT_UUID(entry->name.value),
53341 _RQ_TYPE(rq->u_rq.request_type),
53342 rq->u_rq.seq);
53343
53344 rq->u_rq.data_size = 0;
53345 if (kernel_send(&rq->u_rq))
53346 LOG_ERROR("Failed to respond to kernel [%s]",
53347 RQ_TYPE(rq->u_rq.request_type));
53348 break;
53349
53350 default:
53351 /*
53352 * If an action or a response is required, then
53353 * the request must be resent.
53354 */
53355 LOG_COND(log_resend_requests,
53356 "[%s] Resending %s(#%u) due to new server(%u)",
53357 SHORT_UUID(entry->name.value),
53358 _RQ_TYPE(rq->u_rq.request_type),
53359 rq->u_rq.seq, entry->lowest_id);
53360 LOG_SPRINT(entry, "*** Resending: [%s] %s/%u ***",
53361 SHORT_UUID(entry->name.value),
53362 _RQ_TYPE(rq->u_rq.request_type),
53363 rq->u_rq.seq);
53364 r = cluster_send(rq);
53365 if (r < 0)
53366 LOG_ERROR("Failed resend");
53367 }
53368 free(rq);
53369 }
53370
53371 return r;
53372}
53373
53374static int do_cluster_work(void *data __attribute__((unused)))
53375{
53376 int r = CS_OK;
53377 struct clog_cpg *entry, *tmp;
53378
53379 dm_list_iterate_items_safe(entry, tmp, &clog_cpg_list) {
53380 r = cpg_dispatch(entry->handle, CS_DISPATCH_ALL);
53381 if (r != CS_OK) {
53382 if ((r == CS_ERR_BAD_HANDLE) &&
53383 ((entry->state == INVALID) ||
53384 (entry->state == LEAVING)))
53385 /* It's ok if we've left the cluster */
53386 r = CS_OK;
53387 else
53388 LOG_ERROR("cpg_dispatch failed: %s",
53389 str_ais_error(r));
53390 }
53391
53392 if (entry->free_me) {
53393 free(entry);
53394 continue;
53395 }
53396 do_checkpoints(entry, 0);
53397
53398 resend_requests(entry);
53399 }
53400
53401 return (r == CS_OK) ? 0 : -1; /* FIXME: good error number? */
53402}
53403
53404static int flush_startup_list(struct clog_cpg *entry)
53405{
53406 int r = 0;
53407 int i_was_server;
53408 struct clog_request *rq, *n;
53409 struct checkpoint_data *new;
53410
53411 dm_list_iterate_items_gen_safe(rq, n, &entry->startup_list, u.list) {
53412 dm_list_del(&rq->u.list);
53413
53414 if (rq->u_rq.request_type == DM_ULOG_MEMBER_JOIN) {
53415 new = prepare_checkpoint(entry, rq->originator);
53416 if (!new) {
53417 /*
53418 * FIXME: Need better error handling. Other nodes
53419 * will be trying to send the checkpoint too, and we
53420 * must continue processing the list; so report error
53421 * but continue.
53422 */
53423 LOG_ERROR("Failed to prepare checkpoint for %u!!!",
53424 rq->originator);
53425 free(rq);
53426 continue;
53427 }
53428 LOG_SPRINT(entry, "[%s] Checkpoint prepared for %u",
53429 SHORT_UUID(entry->name.value), rq->originator);
53430 LOG_COND(log_checkpoint, "[%s] Checkpoint prepared for %u",
53431 SHORT_UUID(entry->name.value), rq->originator);
53432 new->next = entry->checkpoint_list;
53433 entry->checkpoint_list = new;
53434 } else {
53435 LOG_DBG("[%s] Processing delayed request: %s",
53436 SHORT_UUID(rq->u_rq.uuid),
53437 _RQ_TYPE(rq->u_rq.request_type));
53438 i_was_server = (rq->pit_server == my_cluster_id) ? 1 : 0;
53439 r = handle_cluster_request(entry, rq, i_was_server);
53440
53441 if (r)
53442 /*
53443 * FIXME: If we error out here, we will never get
53444 * another opportunity to retry these requests
53445 */
53446 LOG_ERROR("Error while processing delayed CPG message");
53447 }
53448 free(rq);
53449 }
53450
53451 return 0;
53452}
53453
53454static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gname __attribute__((unused)),
53455 uint32_t nodeid, uint32_t pid __attribute__((unused)),
53456 void *msg, size_t msg_len)
53457{
53458 int i;
53459 int r = 0;
53460 int i_am_server;
53461 int response = 0;
53462 struct clog_request *rq = msg;
53463 struct clog_request *tmp_rq, *tmp_rq2;
53464 struct clog_cpg *match;
53465
53466 match = find_clog_cpg(handle);
53467 if (!match) {
53468 LOG_ERROR("Unable to find clog_cpg for cluster message");
53469 return;
53470 }
53471
53472 /*
53473 * Perform necessary endian and version compatibility conversions
53474 */
53475 if (clog_request_from_network(rq, msg_len) < 0)
53476 /* Any error messages come from 'clog_request_from_network' */
53477 return;
53478
53479 if ((nodeid == my_cluster_id) &&
53480 !(rq->u_rq.request_type & DM_ULOG_RESPONSE) &&
53481 (rq->u_rq.request_type != DM_ULOG_RESUME) &&
53482 (rq->u_rq.request_type != DM_ULOG_CLEAR_REGION) &&
53483 (rq->u_rq.request_type != DM_ULOG_CHECKPOINT_READY)) {
53484 tmp_rq = malloc(DM_ULOG_REQUEST_SIZE);
53485 if (!tmp_rq) {
53486 /*
53487 * FIXME: It may be possible to continue... but we
53488 * would not be able to resend any messages that might
53489 * be necessary during membership changes
53490 */
53491 LOG_ERROR("[%s] Unable to record request: -ENOMEM",
53492 SHORT_UUID(rq->u_rq.uuid));
53493 return;
53494 }
53495 memcpy(tmp_rq, rq, sizeof(*rq) + rq->u_rq.data_size);
53496 dm_list_init(&tmp_rq->u.list);
53497 dm_list_add(&match->working_list, &tmp_rq->u.list);
53498 }
53499
53500 if (rq->u_rq.request_type == DM_ULOG_POSTSUSPEND) {
53501 /*
53502 * If the server (lowest_id) indicates it is leaving,
53503 * then we must resend any outstanding requests. However,
53504 * we do not want to resend them if the next server in
53505 * line is in the process of leaving.
53506 */
53507 if (nodeid == my_cluster_id) {
53508 LOG_COND(log_resend_requests, "[%s] I am leaving.1.....",
53509 SHORT_UUID(rq->u_rq.uuid));
53510 } else {
53511 if (nodeid < my_cluster_id) {
53512 if (nodeid == match->lowest_id) {
53513 match->resend_requests = 1;
53514 LOG_COND(log_resend_requests, "[%s] %u is leaving, resend required%s",
53515 SHORT_UUID(rq->u_rq.uuid), nodeid,
53516 (dm_list_empty(&match->working_list)) ? " -- working_list empty": "");
53517
53518 dm_list_iterate_items_gen(tmp_rq, &match->working_list, u.list)
53519 LOG_COND(log_resend_requests,
53520 "[%s] %s/%u",
53521 SHORT_UUID(tmp_rq->u_rq.uuid),
53522 _RQ_TYPE(tmp_rq->u_rq.request_type),
53523 tmp_rq->u_rq.seq);
53524 }
53525
53526 match->delay++;
53527 LOG_COND(log_resend_requests, "[%s] %u is leaving, delay = %d",
53528 SHORT_UUID(rq->u_rq.uuid), nodeid, match->delay);
53529 }
53530 rq->originator = nodeid; /* don't really need this, but nice for debug */
53531 goto out;
53532 }
53533 }
53534
53535 /*
53536 * We can receive messages after we do a cpg_leave but before we
53537 * get our config callback. However, since we can't respond after
53538 * leaving, we simply return.
53539 */
53540 if (match->state == LEAVING)
53541 return;
53542
53543 i_am_server = (my_cluster_id == match->lowest_id) ? 1 : 0;
53544
53545 if (rq->u_rq.request_type == DM_ULOG_CHECKPOINT_READY) {
53546 if (my_cluster_id == rq->originator) {
53547 /* Redundant checkpoints ignored if match->valid */
53548 LOG_SPRINT(match, "[%s] CHECKPOINT_READY notification from %u",
53549 SHORT_UUID(rq->u_rq.uuid), nodeid);
53550 if (import_checkpoint(match,
53551 (match->state != INVALID), rq)) {
53552 LOG_SPRINT(match,
53553 "[%s] Failed to import checkpoint from %u",
53554 SHORT_UUID(rq->u_rq.uuid), nodeid);
53555 LOG_ERROR("[%s] Failed to import checkpoint from %u",
53556 SHORT_UUID(rq->u_rq.uuid), nodeid);
53557 kill(getpid(), SIGUSR1);
53558 /* Could we retry? */
53559 goto out;
53560 } else if (match->state == INVALID) {
53561 LOG_SPRINT(match,
53562 "[%s] Checkpoint data received from %u. Log is now valid",
53563 SHORT_UUID(match->name.value), nodeid);
53564 LOG_COND(log_checkpoint,
53565 "[%s] Checkpoint data received from %u. Log is now valid",
53566 SHORT_UUID(match->name.value), nodeid);
53567 match->state = VALID;
53568
53569 flush_startup_list(match);
53570 } else {
53571 LOG_SPRINT(match,
53572 "[%s] Redundant checkpoint from %u ignored.",
53573 SHORT_UUID(rq->u_rq.uuid), nodeid);
53574 }
53575 }
53576 goto out;
53577 }
53578
53579 if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
53580 response = 1;
53581 r = handle_cluster_response(match, rq);
53582 } else {
53583 rq->originator = nodeid;
53584
53585 if (match->state == LEAVING) {
53586 LOG_ERROR("[%s] Ignoring %s from %u. Reason: I'm leaving",
53587 SHORT_UUID(rq->u_rq.uuid), _RQ_TYPE(rq->u_rq.request_type),
53588 rq->originator);
53589 goto out;
53590 }
53591
53592 if (match->state == INVALID) {
53593 LOG_DBG("Log not valid yet, storing request");
53594 if (!(tmp_rq2 = malloc(DM_ULOG_REQUEST_SIZE))) {
53595 LOG_ERROR("cpg_message_callback: Unable to"
53596 " allocate transfer structs");
53597 r = -ENOMEM; /* FIXME: Better error #? */
53598 goto out;
53599 }
53600
53601 memcpy(tmp_rq2, rq, sizeof(*rq) + rq->u_rq.data_size);
53602 tmp_rq2->pit_server = match->lowest_id;
53603 dm_list_init(&tmp_rq2->u.list);
53604 dm_list_add(&match->startup_list, &tmp_rq2->u.list);
53605 goto out;
53606 }
53607
53608 r = handle_cluster_request(match, rq, i_am_server);
53609 }
53610
53611 /*
53612 * If the log is now valid, we can queue the checkpoints
53613 */
53614 for (i = match->checkpoints_needed; i; ) {
53615 struct checkpoint_data *new;
53616
53617 if (log_get_state(&rq->u_rq) != LOG_RESUMED) {
53618 LOG_DBG("[%s] Withholding checkpoints until log is valid (%s from %u)",
53619 SHORT_UUID(rq->u_rq.uuid), _RQ_TYPE(rq->u_rq.request_type), nodeid);
53620 break;
53621 }
53622
53623 i--;
53624 new = prepare_checkpoint(match, match->checkpoint_requesters[i]);
53625 if (!new) {
53626 /* FIXME: Need better error handling */
53627 LOG_ERROR("[%s] Failed to prepare checkpoint for %u!!!",
53628 SHORT_UUID(rq->u_rq.uuid), match->checkpoint_requesters[i]);
53629 break;
53630 }
53631 LOG_SPRINT(match, "[%s] Checkpoint prepared for %u* (%s)",
53632 SHORT_UUID(rq->u_rq.uuid), match->checkpoint_requesters[i],
53633 (log_get_state(&rq->u_rq) != LOG_RESUMED)? "LOG_RESUMED": "LOG_SUSPENDED");
53634 LOG_COND(log_checkpoint, "[%s] Checkpoint prepared for %u*",
53635 SHORT_UUID(rq->u_rq.uuid), match->checkpoint_requesters[i]);
53636 match->checkpoints_needed--;
53637
53638 new->next = match->checkpoint_list;
53639 match->checkpoint_list = new;
53640 }
53641
53642out:
53643 /* nothing happens after this point. It is just for debugging */
53644 if (r) {
53645 LOG_ERROR("[%s] Error while processing CPG message, %s: %s",
53646 SHORT_UUID(rq->u_rq.uuid),
53647 _RQ_TYPE(rq->u_rq.request_type & ~DM_ULOG_RESPONSE),
53648 strerror(-r));
53649 LOG_ERROR("[%s] Response : %s", SHORT_UUID(rq->u_rq.uuid),
53650 (response) ? "YES" : "NO");
53651 LOG_ERROR("[%s] Originator: %u",
53652 SHORT_UUID(rq->u_rq.uuid), rq->originator);
53653 if (response)
53654 LOG_ERROR("[%s] Responder : %u",
53655 SHORT_UUID(rq->u_rq.uuid), nodeid);
53656
53657 LOG_ERROR("HISTORY::");
53658 for (i = 0; i < DEBUGGING_HISTORY; i++) {
53659 match->idx++;
53660 match->idx = match->idx % DEBUGGING_HISTORY;
53661 if (match->debugging[match->idx][0] == '\0')
53662 continue;
53663 LOG_ERROR("%d:%d) %s", i, match->idx,
53664 match->debugging[match->idx]);
53665 }
53666 } else if (!(rq->u_rq.request_type & DM_ULOG_RESPONSE) ||
53667 (rq->originator == my_cluster_id)) {
53668 if (!response)
53669 LOG_SPRINT(match, "SEQ#=%u, UUID=%s, TYPE=%s, ORIG=%u, RESP=%s",
53670 rq->u_rq.seq, SHORT_UUID(rq->u_rq.uuid),
53671 _RQ_TYPE(rq->u_rq.request_type),
53672 rq->originator, (response) ? "YES" : "NO");
53673 else
53674 LOG_SPRINT(match, "SEQ#=%u, UUID=%s, TYPE=%s, ORIG=%u, RESP=%s, RSPR=%u, error=%d",
53675 rq->u_rq.seq, SHORT_UUID(rq->u_rq.uuid),
53676 _RQ_TYPE(rq->u_rq.request_type),
53677 rq->originator, (response) ? "YES" : "NO",
53678 nodeid, rq->u_rq.error);
53679 }
53680}
53681
53682static void cpg_join_callback(struct clog_cpg *match,
53683 const struct cpg_address *joined,
53684 const struct cpg_address *member_list,
53685 size_t member_list_entries)
53686{
53687 unsigned i;
53688 uint32_t my_pid = (uint32_t)getpid();
53689 uint32_t lowest = match->lowest_id;
53690 struct clog_request *rq;
53691 char dbuf[64] = { 0 };
53692 char *dbuf_p = dbuf;
53693 size_t dbuf_rem = sizeof dbuf;
53694
53695 /* Assign my_cluster_id */
53696 if ((my_cluster_id == 0xDEAD) && (joined->pid == my_pid))
53697 my_cluster_id = joined->nodeid;
53698
53699 /* Am I the very first to join? */
53700 if (member_list_entries == 1) {
53701 match->lowest_id = joined->nodeid;
53702 match->state = VALID;
53703 }
53704
53705 /* If I am part of the joining list, I do not send checkpoints */
53706 if (joined->nodeid == my_cluster_id)
53707 goto out;
53708
53709 for (i = 0; i < member_list_entries - 1; i++) {
53710 int written = snprintf(dbuf_p, dbuf_rem, "%u-", member_list[i].nodeid);
53711 if (written < 0) continue; /* impossible */
53712 if ((unsigned)written >= dbuf_rem) {
53713 dbuf_rem = 0;
53714 break;
53715 }
53716 dbuf_rem -= written;
53717 dbuf_p += written;
53718 }
53719 snprintf(dbuf_p, dbuf_rem, "(%u)", joined->nodeid);
53720 LOG_COND(log_checkpoint, "[%s] Joining node, %u needs checkpoint [%s]",
53721 SHORT_UUID(match->name.value), joined->nodeid, dbuf);
53722
53723 /*
53724 * FIXME: remove checkpoint_requesters/checkpoints_needed, and use
53725 * the startup_list interface exclusively
53726 */
53727 if (dm_list_empty(&match->startup_list) && (match->state == VALID) &&
53728 (match->checkpoints_needed < MAX_CHECKPOINT_REQUESTERS)) {
53729 match->checkpoint_requesters[match->checkpoints_needed++] = joined->nodeid;
53730 goto out;
53731 }
53732
53733 rq = malloc(DM_ULOG_REQUEST_SIZE);
53734 if (!rq) {
53735 LOG_ERROR("cpg_config_callback: "
53736 "Unable to allocate transfer structs");
53737 LOG_ERROR("cpg_config_callback: "
53738 "Unable to perform checkpoint");
53739 goto out;
53740 }
53741 rq->u_rq.request_type = DM_ULOG_MEMBER_JOIN;
53742 rq->originator = joined->nodeid;
53743 dm_list_init(&rq->u.list);
53744 dm_list_add(&match->startup_list, &rq->u.list);
53745
53746out:
53747 /* Find the lowest_id, i.e. the server */
53748 match->lowest_id = member_list[0].nodeid;
53749 for (i = 0; i < member_list_entries; i++)
53750 if (match->lowest_id > member_list[i].nodeid)
53751 match->lowest_id = member_list[i].nodeid;
53752
53753 if (lowest == 0xDEAD)
53754 LOG_COND(log_membership_change, "[%s] Server change <none> -> %u (%u %s)",
53755 SHORT_UUID(match->name.value), match->lowest_id,
53756 joined->nodeid, (member_list_entries == 1) ?
53757 "is first to join" : "joined");
53758 else if (lowest != match->lowest_id)
53759 LOG_COND(log_membership_change, "[%s] Server change %u -> %u (%u joined)",
53760 SHORT_UUID(match->name.value), lowest,
53761 match->lowest_id, joined->nodeid);
53762 else
53763 LOG_COND(log_membership_change, "[%s] Server unchanged at %u (%u joined)",
53764 SHORT_UUID(match->name.value),
53765 lowest, joined->nodeid);
53766 LOG_SPRINT(match, "+++ UUID=%s %u join +++",
53767 SHORT_UUID(match->name.value), joined->nodeid);
53768}
53769
53770static void cpg_leave_callback(struct clog_cpg *match,
53771 const struct cpg_address *left,
53772 const struct cpg_address *member_list,
53773 size_t member_list_entries)
53774{
53775 unsigned i;
53776 int j, fd;
53777 uint32_t lowest = match->lowest_id;
53778 struct clog_request *rq, *n;
53779 struct checkpoint_data *p_cp, *c_cp;
53780
53781 LOG_SPRINT(match, "--- UUID=%s %u left ---",
53782 SHORT_UUID(match->name.value), left->nodeid);
53783
53784 /* Am I leaving? */
53785 if (my_cluster_id == left->nodeid) {
53786 LOG_DBG("Finalizing leave...");
53787 dm_list_del(&match->list);
53788
53789 cpg_fd_get(match->handle, &fd);
53790 links_unregister(fd);
53791
53792 cluster_postsuspend(match->name.value, match->luid);
53793
53794 dm_list_iterate_items_gen_safe(rq, n, &match->working_list, u.list) {
53795 dm_list_del(&rq->u.list);
53796
53797 if (rq->u_rq.request_type == DM_ULOG_POSTSUSPEND)
53798 if (kernel_send(&rq->u_rq))
53799 LOG_ERROR("Failed to respond to kernel [%s]",
53800 RQ_TYPE(rq->u_rq.request_type));
53801 free(rq);
53802 }
53803
53804 cpg_finalize(match->handle);
53805
53806 match->free_me = 1;
53807 match->lowest_id = 0xDEAD;
53808 match->state = INVALID;
53809 }
53810
53811 /* Remove any pending checkpoints for the leaving node. */
53812 for (p_cp = NULL, c_cp = match->checkpoint_list;
53813 c_cp && (c_cp->requester != left->nodeid);
53814 p_cp = c_cp, c_cp = c_cp->next);
53815 if (c_cp) {
53816 if (p_cp)
53817 p_cp->next = c_cp->next;
53818 else
53819 match->checkpoint_list = c_cp->next;
53820
53821 LOG_COND(log_checkpoint,
53822 "[%s] Removing pending checkpoint (%u is leaving)",
53823 SHORT_UUID(match->name.value), left->nodeid);
53824 free_checkpoint(c_cp);
53825 }
53826 dm_list_iterate_items_gen_safe(rq, n, &match->startup_list, u.list) {
53827 if ((rq->u_rq.request_type == DM_ULOG_MEMBER_JOIN) &&
53828 (rq->originator == left->nodeid)) {
53829 LOG_COND(log_checkpoint,
53830 "[%s] Removing pending ckpt from startup list (%u is leaving)",
53831 SHORT_UUID(match->name.value), left->nodeid);
53832 dm_list_del(&rq->u.list);
53833 free(rq);
53834 }
53835 }
53836 for (i = 0, j = 0; (int) i < match->checkpoints_needed; i++, j++) {
53837 match->checkpoint_requesters[j] = match->checkpoint_requesters[i];
53838 if (match->checkpoint_requesters[i] == left->nodeid) {
53839 LOG_ERROR("[%s] Removing pending ckpt from needed list (%u is leaving)",
53840 SHORT_UUID(match->name.value), left->nodeid);
53841 j--;
53842 }
53843 }
53844 match->checkpoints_needed = j;
53845
53846 if (left->nodeid < my_cluster_id) {
53847 match->delay = (match->delay > 0) ? match->delay - 1 : 0;
53848 if (!match->delay && dm_list_empty(&match->working_list))
53849 match->resend_requests = 0;
53850 LOG_COND(log_resend_requests, "[%s] %u has left, delay = %d%s",
53851 SHORT_UUID(match->name.value), left->nodeid,
53852 match->delay, (dm_list_empty(&match->working_list)) ?
53853 " -- working_list empty": "");
53854 }
53855
53856 /* Find the lowest_id, i.e. the server */
53857 if (!member_list_entries) {
53858 match->lowest_id = 0xDEAD;
53859 LOG_COND(log_membership_change, "[%s] Server change %u -> <none> "
53860 "(%u is last to leave)",
53861 SHORT_UUID(match->name.value), left->nodeid,
53862 left->nodeid);
53863 return;
53864 }
53865
53866 match->lowest_id = member_list[0].nodeid;
53867 for (i = 0; i < member_list_entries; i++)
53868 if (match->lowest_id > member_list[i].nodeid)
53869 match->lowest_id = member_list[i].nodeid;
53870
53871 if (lowest != match->lowest_id) {
53872 LOG_COND(log_membership_change, "[%s] Server change %u -> %u (%u left)",
53873 SHORT_UUID(match->name.value), lowest,
53874 match->lowest_id, left->nodeid);
53875 } else
53876 LOG_COND(log_membership_change, "[%s] Server unchanged at %u (%u left)",
53877 SHORT_UUID(match->name.value), lowest, left->nodeid);
53878
53879 if ((match->state == INVALID) && !match->free_me) {
53880 /*
53881 * If all CPG members are waiting for checkpoints and they
53882 * are all present in my startup_list, then I was the first to
53883 * join and I must assume control.
53884 *
53885 * We do not normally end up here, but if there was a quick
53886 * 'resume -> suspend -> resume' across the cluster, we may
53887 * have initially thought we were not the first to join because
53888 * of the presence of out-going (and unable to respond) members.
53889 */
53890
53891 i = 1; /* We do not have a DM_ULOG_MEMBER_JOIN entry of our own */
53892 dm_list_iterate_items_gen(rq, &match->startup_list, u.list)
53893 if (rq->u_rq.request_type == DM_ULOG_MEMBER_JOIN)
53894 i++;
53895
53896 if (i == member_list_entries) {
53897 /*
53898 * Last node who could have given me a checkpoint just left.
53899 * Setting log state to VALID and acting as 'first join'.
53900 */
53901 match->state = VALID;
53902 flush_startup_list(match);
53903 }
53904 }
53905}
53906
53907static void cpg_config_callback(cpg_handle_t handle, const struct cpg_name *gname __attribute__((unused)),
53908 const struct cpg_address *member_list,
53909 size_t member_list_entries,
53910 const struct cpg_address *left_list,
53911 size_t left_list_entries,
53912 const struct cpg_address *joined_list,
53913 size_t joined_list_entries)
53914{
53915 struct clog_cpg *match;
53916 int found = 0;
53917
53918 dm_list_iterate_items(match, &clog_cpg_list)
53919 if (match->handle == handle) {
53920 found = 1;
53921 break;
53922 }
53923
53924 if (!found) {
53925 LOG_ERROR("Unable to find match for CPG config callback");
53926 return;
53927 }
53928
53929 if ((joined_list_entries + left_list_entries) > 1)
53930 LOG_ERROR("[%s] More than one node joining/leaving",
53931 SHORT_UUID(match->name.value));
53932
53933 if (joined_list_entries)
53934 cpg_join_callback(match, joined_list,
53935 member_list, member_list_entries);
53936 else
53937 cpg_leave_callback(match, left_list,
53938 member_list, member_list_entries);
53939}
53940
53941cpg_callbacks_t cpg_callbacks = {
53942 .cpg_deliver_fn = cpg_message_callback,
53943 .cpg_confchg_fn = cpg_config_callback,
53944};
53945
53946/*
53947 * remove_checkpoint
53948 * @entry
53949 *
53950 * Returns: 1 if checkpoint removed, 0 if no checkpoints, -EXXX on error
53951 */
53952static int remove_checkpoint(struct clog_cpg *entry)
53953{
53954#if CMIRROR_HAS_CHECKPOINT
53955 int len;
53956 SaNameT name;
53957 SaAisErrorT rv;
53958 SaCkptCheckpointHandleT h;
53959
53960 len = snprintf((char *)(name.value), SA_MAX_NAME_LENGTH, "bitmaps_%s_%u",
53961 SHORT_UUID(entry->name.value), my_cluster_id);
53962 name.length = len;
53963
53964open_retry:
53965 rv = saCkptCheckpointOpen(ckpt_handle, &name, NULL,
53966 SA_CKPT_CHECKPOINT_READ, 0, &h);
53967 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53968 LOG_ERROR("abort_startup: ckpt open retry");
53969 usleep(1000);
53970 goto open_retry;
53971 }
53972
53973 if (rv != SA_AIS_OK)
53974 return 0;
53975
53976 LOG_DBG("[%s] Removing checkpoint", SHORT_UUID(entry->name.value));
53977unlink_retry:
53978 rv = saCkptCheckpointUnlink(ckpt_handle, &name);
53979 if (rv == SA_AIS_ERR_TRY_AGAIN) {
53980 LOG_ERROR("abort_startup: ckpt unlink retry");
53981 usleep(1000);
53982 goto unlink_retry;
53983 }
53984
53985 if (rv != SA_AIS_OK) {
53986 LOG_ERROR("[%s] Failed to unlink checkpoint: %s",
53987 SHORT_UUID(entry->name.value), str_ais_error(rv));
53988 return -EIO;
53989 }
53990
53991 saCkptCheckpointClose(h);
53992
53993 return 1;
53994#else
53995 /* No checkpoint to remove, so 'success' */
53996 return 1;
53997#endif
53998}
53999
54000int create_cluster_cpg(char *uuid, uint64_t luid)
54001{
54002 int r;
54003 size_t size;
54004 struct clog_cpg *new = NULL;
54005 struct clog_cpg *tmp;
54006
54007 dm_list_iterate_items(tmp, &clog_cpg_list)
54008 if (!strncmp(tmp->name.value, uuid, CPG_MAX_NAME_LENGTH)) {
54009 LOG_ERROR("Log entry already exists: %s", uuid);
54010 return -EEXIST;
54011 }
54012
54013 new = malloc(sizeof(*new));
54014 if (!new) {
54015 LOG_ERROR("Unable to allocate memory for clog_cpg");
54016 return -ENOMEM;
54017 }
54018 memset(new, 0, sizeof(*new));
54019 dm_list_init(&new->list);
54020 new->lowest_id = 0xDEAD;
54021 dm_list_init(&new->startup_list);
54022 dm_list_init(&new->working_list);
54023
54024 size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
54025 CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
54026 strncpy(new->name.value, uuid, size);
54027 new->name.length = (uint32_t)size;
54028 new->luid = luid;
54029
54030 /*
54031 * Ensure there are no stale checkpoints around before we join
54032 */
54033 if (remove_checkpoint(new) == 1)
54034 LOG_COND(log_checkpoint,
54035 "[%s] Removing checkpoints left from previous session",
54036 SHORT_UUID(new->name.value));
54037
54038 r = cpg_initialize(&new->handle, &cpg_callbacks);
54039 if (r != CS_OK) {
54040 LOG_ERROR("cpg_initialize failed: Cannot join cluster");
54041 free(new);
54042 return -EPERM;
54043 }
54044
54045 r = cpg_join(new->handle, &new->name);
54046 if (r != CS_OK) {
54047 LOG_ERROR("cpg_join failed: Cannot join cluster");
54048 free(new);
54049 return -EPERM;
54050 }
54051
54052 new->cpg_state = VALID;
54053 dm_list_add(&clog_cpg_list, &new->list);
54054 LOG_DBG("New handle: %llu", (unsigned long long)new->handle);
54055 LOG_DBG("New name: %s", new->name.value);
54056
54057 /* FIXME: better variable */
54058 cpg_fd_get(new->handle, &r);
54059 links_register(r, "cluster", do_cluster_work, NULL);
54060
54061 return 0;
54062}
54063
54064static void abort_startup(struct clog_cpg *del)
54065{
54066 struct clog_request *rq, *n;
54067
54068 LOG_DBG("[%s] CPG teardown before checkpoint received",
54069 SHORT_UUID(del->name.value));
54070
54071 dm_list_iterate_items_gen_safe(rq, n, &del->startup_list, u.list) {
54072 dm_list_del(&rq->u.list);
54073
54074 LOG_DBG("[%s] Ignoring request from %u: %s",
54075 SHORT_UUID(del->name.value), rq->originator,
54076 _RQ_TYPE(rq->u_rq.request_type));
54077 free(rq);
54078 }
54079
54080 remove_checkpoint(del);
54081}
54082
54083static int _destroy_cluster_cpg(struct clog_cpg *del)
54084{
54085 int r;
54086 int state;
54087
54088 LOG_COND(log_resend_requests, "[%s] I am leaving.2.....",
54089 SHORT_UUID(del->name.value));
54090
54091 /*
54092 * We must send any left over checkpoints before
54093 * leaving. If we don't, an incoming node could
54094 * be stuck with no checkpoint and stall.
54095 do_checkpoints(del); --- THIS COULD BE CAUSING OUR PROBLEMS:
54096
54097 - Incoming node deletes old checkpoints before joining
54098 - A stale checkpoint is issued here by leaving node
54099 - (leaving node leaves)
54100 - Incoming node joins cluster and finds stale checkpoint.
54101 - (leaving node leaves - option 2)
54102 */
54103 do_checkpoints(del, 1);
54104
54105 state = del->state;
54106
54107 del->cpg_state = INVALID;
54108 del->state = LEAVING;
54109
54110 /*
54111 * If the state is VALID, we might be processing the
54112 * startup list. If so, we certainly don't want to
54113 * clear the startup_list here by calling abort_startup
54114 */
54115 if (!dm_list_empty(&del->startup_list) && (state != VALID))
54116 abort_startup(del);
54117
54118 r = cpg_leave(del->handle, &del->name);
54119 if (r != CS_OK)
54120 LOG_ERROR("Error leaving CPG!");
54121 return 0;
54122}
54123
54124int destroy_cluster_cpg(char *uuid)
54125{
54126 struct clog_cpg *del, *tmp;
54127
54128 dm_list_iterate_items_safe(del, tmp, &clog_cpg_list)
54129 if (!strncmp(del->name.value, uuid, CPG_MAX_NAME_LENGTH))
54130 _destroy_cluster_cpg(del);
54131
54132 return 0;
54133}
54134
54135int init_cluster(void)
54136{
54137#if CMIRROR_HAS_CHECKPOINT
54138 SaAisErrorT rv;
54139
54140 rv = saCkptInitialize(&ckpt_handle, &callbacks, &version);
54141
54142 if (rv != SA_AIS_OK)
54143 return EXIT_CLUSTER_CKPT_INIT;
54144#endif
54145 dm_list_init(&clog_cpg_list);
54146 return 0;
54147}
54148
54149void cleanup_cluster(void)
54150{
54151#if CMIRROR_HAS_CHECKPOINT
54152 SaAisErrorT err;
54153
54154 err = saCkptFinalize(ckpt_handle);
54155 if (err != SA_AIS_OK)
54156 LOG_ERROR("Failed to finalize checkpoint handle");
54157#endif
54158}
54159
54160void cluster_debug(void)
54161{
54162 struct checkpoint_data *cp;
54163 struct clog_cpg *entry;
54164 struct clog_request *rq;
54165 int i;
54166
54167 LOG_ERROR("");
54168 LOG_ERROR("CLUSTER COMPONENT DEBUGGING::");
54169 dm_list_iterate_items(entry, &clog_cpg_list) {
54170 LOG_ERROR("%s::", SHORT_UUID(entry->name.value));
54171 LOG_ERROR(" lowest_id : %u", entry->lowest_id);
54172 LOG_ERROR(" state : %s", (entry->state == INVALID) ?
54173 "INVALID" : (entry->state == VALID) ? "VALID" :
54174 (entry->state == LEAVING) ? "LEAVING" : "UNKNOWN");
54175 LOG_ERROR(" cpg_state : %d", entry->cpg_state);
54176 LOG_ERROR(" free_me : %d", entry->free_me);
54177 LOG_ERROR(" delay : %d", entry->delay);
54178 LOG_ERROR(" resend_requests : %d", entry->resend_requests);
54179 LOG_ERROR(" checkpoints_needed: %d", entry->checkpoints_needed);
54180 for (i = 0, cp = entry->checkpoint_list;
54181 i < MAX_CHECKPOINT_REQUESTERS; i++)
54182 if (cp)
54183 cp = cp->next;
54184 else
54185 break;
54186 LOG_ERROR(" CKPTs waiting : %d", i);
54187 LOG_ERROR(" Working list:");
54188 dm_list_iterate_items_gen(rq, &entry->working_list, u.list)
54189 LOG_ERROR(" %s/%u", _RQ_TYPE(rq->u_rq.request_type),
54190 rq->u_rq.seq);
54191
54192 LOG_ERROR(" Startup list:");
54193 dm_list_iterate_items_gen(rq, &entry->startup_list, u.list)
54194 LOG_ERROR(" %s/%u", _RQ_TYPE(rq->u_rq.request_type),
54195 rq->u_rq.seq);
54196
54197 LOG_ERROR("Command History:");
54198 for (i = 0; i < DEBUGGING_HISTORY; i++) {
54199 entry->idx++;
54200 entry->idx = entry->idx % DEBUGGING_HISTORY;
54201 if (entry->debugging[entry->idx][0] == '\0')
54202 continue;
54203 LOG_ERROR("%d:%d) %s", i, entry->idx,
54204 entry->debugging[entry->idx]);
54205 }
54206 }
54207}
54208\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/compat.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001257\013062740170\0021757\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54209 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
54210 *
54211 * This copyrighted material is made available to anyone wishing to use,
54212 * modify, copy, or redistribute it subject to the terms and conditions
54213 * of the GNU Lesser General Public License v.2.1.
54214 */
54215#ifndef _LVM_CLOG_COMPAT_H
54216#define _LVM_CLOG_COMPAT_H
54217
54218/*
54219 * The intermachine communication structure version are:
54220 * 0: Unused
54221 * 1: Never in the wild
54222 * 2: RHEL 5.2
54223 * 3: RHEL 5.3
54224 * 4: RHEL 5.4, RHEL 5.5
54225 * 5: RHEL 6, Current Upstream Format
54226 */
54227#define CLOG_TFR_VERSION 5
54228
54229int clog_request_to_network(struct clog_request *rq);
54230int clog_request_from_network(void *data, size_t data_len);
54231
54232#endif /* _LVM_CLOG_COMPAT_H */
54233\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/functions.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002150\013062740170\0022475\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54234 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54235 *
54236 * This copyrighted material is made available to anyone wishing to use,
54237 * modify, copy, or redistribute it subject to the terms and conditions
54238 * of the GNU Lesser General Public License v.2.1.
54239 *
54240 * You should have received a copy of the GNU Lesser General Public License
54241 * along with this program; if not, write to the Free Software Foundation,
54242 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54243 */
54244#ifndef _LVM_CLOG_FUNCTIONS_H
54245#define _LVM_CLOG_FUNCTIONS_H
54246
54247#include "dm-log-userspace.h"
54248#include "cluster.h"
54249
54250#define LOG_RESUMED 1
54251#define LOG_SUSPENDED 2
54252
54253int local_resume(struct dm_ulog_request *rq);
54254int cluster_postsuspend(char *, uint64_t);
54255
54256int do_request(struct clog_request *rq, int server);
54257int push_state(const char *uuid, uint64_t luid,
54258 const char *which, char **buf, uint32_t debug_who);
54259int pull_state(const char *uuid, uint64_t luid,
54260 const char *which, char *buf, int size);
54261
54262int log_get_state(struct dm_ulog_request *rq);
54263int log_status(void);
54264void log_debug(void);
54265
54266#endif /* _LVM_CLOG_FUNCTIONS_H */
54267\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/common.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002274\013062740170\0021764\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54268 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54269 *
54270 * This copyrighted material is made available to anyone wishing to use,
54271 * modify, copy, or redistribute it subject to the terms and conditions
54272 * of the GNU Lesser General Public License v.2.1.
54273 *
54274 * You should have received a copy of the GNU Lesser General Public License
54275 * along with this program; if not, write to the Free Software Foundation,
54276 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54277 */
54278#ifndef _LVM_CLOG_COMMON_H
54279#define _LVM_CLOG_COMMON_H
54280
54281/*
54282 * If there are problems when forking off to become a daemon,
54283 * the child will exist with one of these codes. This allows
54284 * the parent to know the reason for the failure and print it
54285 * to the launching terminal.
54286 *
54287 * #define EXIT_SUCCESS 0 (from stdlib.h)
54288 * #define EXIT_FAILURE 1 (from stdlib.h)
54289 */
54290#define EXIT_LOCKFILE 2
54291#define EXIT_KERNEL_SOCKET 3 /* Failed netlink socket create */
54292#define EXIT_KERNEL_BIND 4
54293#define EXIT_KERNEL_SETSOCKOPT 5
54294#define EXIT_CLUSTER_CKPT_INIT 6 /* Failed to init checkpoint */
54295#define EXIT_QUEUE_NOMEM 7
54296
54297#define DM_ULOG_REQUEST_SIZE 1024
54298
54299#endif /* _LVM_CLOG_COMMON_H */
54300\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/logging.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002427\013062740170\0022115\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54301 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54302 *
54303 * This copyrighted material is made available to anyone wishing to use,
54304 * modify, copy, or redistribute it subject to the terms and conditions
54305 * of the GNU Lesser General Public License v.2.1.
54306 *
54307 * You should have received a copy of the GNU Lesser General Public License
54308 * along with this program; if not, write to the Free Software Foundation,
54309 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54310 */
54311#include "logging.h"
54312
54313const char *__rq_types_off_by_one[] = {
54314 "DM_ULOG_CTR",
54315 "DM_ULOG_DTR",
54316 "DM_ULOG_PRESUSPEND",
54317 "DM_ULOG_POSTSUSPEND",
54318 "DM_ULOG_RESUME",
54319 "DM_ULOG_GET_REGION_SIZE",
54320 "DM_ULOG_IS_CLEAN",
54321 "DM_ULOG_IN_SYNC",
54322 "DM_ULOG_FLUSH",
54323 "DM_ULOG_MARK_REGION",
54324 "DM_ULOG_CLEAR_REGION",
54325 "DM_ULOG_GET_RESYNC_WORK",
54326 "DM_ULOG_SET_REGION_SYNC",
54327 "DM_ULOG_GET_SYNC_COUNT",
54328 "DM_ULOG_STATUS_INFO",
54329 "DM_ULOG_STATUS_TABLE",
54330 "DM_ULOG_IS_REMOTE_RECOVERING",
54331 NULL
54332};
54333
54334int log_tabbing = 0;
54335int log_is_open = 0;
54336
54337/*
54338 * Variables for various conditional logging
54339 */
54340#ifdef MEMB
54341int log_membership_change = 1;
54342#else
54343int log_membership_change = 0;
54344#endif
54345
54346#ifdef CKPT
54347int log_checkpoint = 1;
54348#else
54349int log_checkpoint = 0;
54350#endif
54351
54352#ifdef RESEND
54353int log_resend_requests = 1;
54354#else
54355int log_resend_requests = 0;
54356#endif
54357\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/cluster.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004254\013062740170\0022155\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54358 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54359 *
54360 * This copyrighted material is made available to anyone wishing to use,
54361 * modify, copy, or redistribute it subject to the terms and conditions
54362 * of the GNU Lesser General Public License v.2.1.
54363 *
54364 * You should have received a copy of the GNU Lesser General Public License
54365 * along with this program; if not, write to the Free Software Foundation,
54366 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54367 */
54368#ifndef _LVM_CLOG_CLUSTER_H
54369#define _LVM_CLOG_CLUSTER_H
54370
54371#include "dm-log-userspace.h"
54372#include "libdevmapper.h"
54373
54374#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
54375#define DM_ULOG_CHECKPOINT_READY 21
54376#define DM_ULOG_MEMBER_JOIN 22
54377
54378/*
54379 * There is other information in addition to what can
54380 * be found in the dm_ulog_request structure that we
54381 * need for processing. 'clog_request' is the wrapping
54382 * structure we use to make the additional fields
54383 * available.
54384 */
54385struct clog_request {
54386 /*
54387 * If we don't use a union, the structure size will
54388 * vary between 32-bit and 64-bit machines. So, we
54389 * pack two 64-bit version numbers in there to force
54390 * the size of the structure to be the same.
54391 *
54392 * The two version numbers also help us with endian
54393 * issues. The first is always little endian, while
54394 * the second is in native format of the sending
54395 * machine. If the two are equal, there is no need
54396 * to do endian conversions.
54397 */
54398 union {
54399 uint64_t version[2]; /* LE version and native version */
54400 struct dm_list list;
54401 } u;
54402
54403 /*
54404 * 'originator' is the machine from which the requests
54405 * was made.
54406 */
54407 uint32_t originator;
54408
54409 /*
54410 * 'pit_server' is the "point-in-time" server for the
54411 * request. (I.e. The machine that was the server at
54412 * the time the request was issued - only important during
54413 * startup.
54414 */
54415 uint32_t pit_server;
54416
54417 /*
54418 * The request from the kernel that is being processed
54419 */
54420 struct dm_ulog_request u_rq;
54421};
54422
54423int init_cluster(void);
54424void cleanup_cluster(void);
54425void cluster_debug(void);
54426
54427int create_cluster_cpg(char *uuid, uint64_t luid);
54428int destroy_cluster_cpg(char *uuid);
54429
54430int cluster_send(struct clog_request *rq);
54431
54432#endif /* _LVM_CLOG_CLUSTER_H */
54433\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/link_mon.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001367\013062740170\0022304\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54434 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54435 *
54436 * This copyrighted material is made available to anyone wishing to use,
54437 * modify, copy, or redistribute it subject to the terms and conditions
54438 * of the GNU Lesser General Public License v.2.1.
54439 *
54440 * You should have received a copy of the GNU Lesser General Public License
54441 * along with this program; if not, write to the Free Software Foundation,
54442 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54443 */
54444#ifndef _LVM_CLOG_LINK_MON_H
54445#define _LVM_CLOG_LINK_MON_H
54446
54447int links_register(int fd, const char *name, int (*callback)(void *data), void *data);
54448int links_unregister(int fd);
54449int links_monitor(void);
54450int links_issue_callbacks(void);
54451
54452#endif /* _LVM_CLOG_LINK_MON_H */
54453\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/local.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000023522\013062740170\0021560\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54454 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54455 *
54456 * This copyrighted material is made available to anyone wishing to use,
54457 * modify, copy, or redistribute it subject to the terms and conditions
54458 * of the GNU Lesser General Public License v.2.1.
54459 *
54460 * You should have received a copy of the GNU Lesser General Public License
54461 * along with this program; if not, write to the Free Software Foundation,
54462 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54463 */
54464#include "logging.h"
54465#include "common.h"
54466#include "functions.h"
54467#include "link_mon.h"
54468#include "local.h"
54469
54470#include <errno.h>
54471#include <sys/socket.h>
54472#include <linux/connector.h>
54473#include <linux/netlink.h>
54474#include <unistd.h>
54475
54476#ifndef CN_IDX_DM
54477/* Kernel 2.6.31 is required to run this code */
54478#define CN_IDX_DM 0x7 /* Device Mapper */
54479#define CN_VAL_DM_USERSPACE_LOG 0x1
54480#endif
54481
54482static int cn_fd = -1; /* Connector (netlink) socket fd */
54483static char recv_buf[2048];
54484static char send_buf[2048];
54485
54486
54487/* FIXME: merge this function with kernel_send_helper */
54488static int kernel_ack(uint32_t seq, int error)
54489{
54490 int r;
54491 struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
54492 struct cn_msg *msg = NLMSG_DATA(nlh);
54493
54494 if (error < 0) {
54495 LOG_ERROR("Programmer error: error codes must be positive");
54496 return -EINVAL;
54497 }
54498
54499 memset(send_buf, 0, sizeof(send_buf));
54500
54501 nlh->nlmsg_seq = 0;
54502 nlh->nlmsg_pid = getpid();
54503 nlh->nlmsg_type = NLMSG_DONE;
54504 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
54505 nlh->nlmsg_flags = 0;
54506
54507 msg->len = 0;
54508 msg->id.idx = CN_IDX_DM;
54509 msg->id.val = CN_VAL_DM_USERSPACE_LOG;
54510 msg->seq = seq;
54511 msg->ack = error;
54512
54513 r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
54514 /* FIXME: do better error processing */
54515 if (r <= 0)
54516 return -EBADE;
54517
54518 return 0;
54519}
54520
54521
54522/*
54523 * kernel_recv
54524 * @rq: the newly allocated request from kernel
54525 *
54526 * Read requests from the kernel and allocate space for the new request.
54527 * If there is no request from the kernel, *rq is NULL.
54528 *
54529 * This function is not thread safe due to returned stack pointer. In fact,
54530 * the returned pointer must not be in-use when this function is called again.
54531 *
54532 * Returns: 0 on success, -EXXX on error
54533 */
54534static int kernel_recv(struct clog_request **rq)
54535{
54536 int r = 0;
54537 ssize_t len;
54538 char *foo;
54539 struct cn_msg *msg;
54540 struct dm_ulog_request *u_rq;
54541 struct nlmsghdr *nlmsg_h;
54542
54543 *rq = NULL;
54544 memset(recv_buf, 0, sizeof(recv_buf));
54545
54546 len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
54547 if (len < 0) {
54548 LOG_ERROR("Failed to recv message from kernel");
54549 r = -errno;
54550 goto fail;
54551 }
54552
54553 nlmsg_h = (struct nlmsghdr *)recv_buf;
54554 switch (nlmsg_h->nlmsg_type) {
54555 case NLMSG_ERROR:
54556 LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
54557 r = -EBADE;
54558 goto fail;
54559 case NLMSG_DONE:
54560 msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
54561 len -= (ssize_t)sizeof(struct nlmsghdr);
54562
54563 if (len < (ssize_t)sizeof(struct cn_msg)) {
54564 LOG_ERROR("Incomplete request from kernel received");
54565 r = -EBADE;
54566 goto fail;
54567 }
54568
54569 if (msg->len > DM_ULOG_REQUEST_SIZE) {
54570 LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
54571 msg->len, DM_ULOG_REQUEST_SIZE);
54572 r = -EBADE;
54573 goto fail;
54574 }
54575
54576 if (!msg->len)
54577 LOG_ERROR("Zero length message received");
54578
54579 len -= (ssize_t)sizeof(struct cn_msg);
54580
54581 if (len < msg->len)
54582 LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
54583
54584 msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
54585 u_rq = (struct dm_ulog_request *)msg->data;
54586
54587 if (!u_rq->request_type) {
54588 LOG_DBG("Bad transmission, requesting resend [%u]",
54589 msg->seq);
54590 r = -EAGAIN;
54591
54592 if (kernel_ack(msg->seq, EAGAIN)) {
54593 LOG_ERROR("Failed to NACK kernel transmission [%u]",
54594 msg->seq);
54595 r = -EBADE;
54596 }
54597 }
54598
54599 /*
54600 * Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
54601 * worth of space that precede the request structure from the
54602 * kernel. Since that space isn't going to be used again, we
54603 * can take it for our purposes; rather than allocating a whole
54604 * new structure and doing a memcpy.
54605 *
54606 * We should really make sure 'clog_request' doesn't grow
54607 * beyond what is available to us, but we need only check it
54608 * once... perhaps at compile time?
54609 */
54610 foo = (char *)u_rq;
54611 foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
54612 *rq = (struct clog_request *) foo;
54613
54614 /* Clear the wrapper container fields */
54615 memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
54616 break;
54617 default:
54618 LOG_ERROR("Unknown nlmsg_type");
54619 r = -EBADE;
54620 }
54621
54622fail:
54623 if (r)
54624 *rq = NULL;
54625
54626 return (r == -EAGAIN) ? 0 : r;
54627}
54628
54629static int kernel_send_helper(void *data, uint16_t out_size)
54630{
54631 int r;
54632 struct nlmsghdr *nlh;
54633 struct cn_msg *msg;
54634
54635 memset(send_buf, 0, sizeof(send_buf));
54636
54637 nlh = (struct nlmsghdr *)send_buf;
54638 nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
54639 nlh->nlmsg_pid = getpid();
54640 nlh->nlmsg_type = NLMSG_DONE;
54641 nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
54642 nlh->nlmsg_flags = 0;
54643
54644 msg = NLMSG_DATA(nlh);
54645 memcpy(msg->data, data, out_size);
54646 msg->len = out_size;
54647 msg->id.idx = CN_IDX_DM;
54648 msg->id.val = CN_VAL_DM_USERSPACE_LOG;
54649 msg->seq = 0;
54650
54651 r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
54652 /* FIXME: do better error processing */
54653 if (r <= 0)
54654 return -EBADE;
54655
54656 return 0;
54657}
54658
54659/*
54660 * do_local_work
54661 *
54662 * Any processing errors are placed in the 'rq'
54663 * structure to be reported back to the kernel.
54664 * It may be pointless for this function to
54665 * return an int.
54666 *
54667 * Returns: 0 on success, -EXXX on failure
54668 */
54669static int do_local_work(void *data __attribute__((unused)))
54670{
54671 int r;
54672 struct clog_request *rq;
54673 struct dm_ulog_request *u_rq = NULL;
54674
54675 r = kernel_recv(&rq);
54676 if (r)
54677 return r;
54678
54679 if (!rq)
54680 return 0;
54681
54682 u_rq = &rq->u_rq;
54683 LOG_DBG("[%s] Request from kernel received: [%s/%u]",
54684 SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
54685 u_rq->seq);
54686 switch (u_rq->request_type) {
54687 case DM_ULOG_CTR:
54688 case DM_ULOG_DTR:
54689 case DM_ULOG_GET_REGION_SIZE:
54690 case DM_ULOG_IN_SYNC:
54691 case DM_ULOG_GET_SYNC_COUNT:
54692 case DM_ULOG_STATUS_TABLE:
54693 case DM_ULOG_PRESUSPEND:
54694 /* We do not specify ourselves as server here */
54695 r = do_request(rq, 0);
54696 if (r)
54697 LOG_DBG("Returning failed request to kernel [%s]",
54698 RQ_TYPE(u_rq->request_type));
54699 r = kernel_send(u_rq);
54700 if (r)
54701 LOG_ERROR("Failed to respond to kernel [%s]",
54702 RQ_TYPE(u_rq->request_type));
54703
54704 break;
54705 case DM_ULOG_RESUME:
54706 /*
54707 * Resume is a special case that requires a local
54708 * component to join the CPG, and a cluster component
54709 * to handle the request.
54710 */
54711 r = local_resume(u_rq);
54712 if (r) {
54713 LOG_DBG("Returning failed request to kernel [%s]",
54714 RQ_TYPE(u_rq->request_type));
54715 r = kernel_send(u_rq);
54716 if (r)
54717 LOG_ERROR("Failed to respond to kernel [%s]",
54718 RQ_TYPE(u_rq->request_type));
54719 break;
54720 }
54721 /* ELSE, fall through */
54722 case DM_ULOG_IS_CLEAN:
54723 case DM_ULOG_FLUSH:
54724 case DM_ULOG_MARK_REGION:
54725 case DM_ULOG_GET_RESYNC_WORK:
54726 case DM_ULOG_SET_REGION_SYNC:
54727 case DM_ULOG_STATUS_INFO:
54728 case DM_ULOG_IS_REMOTE_RECOVERING:
54729 case DM_ULOG_POSTSUSPEND:
54730 r = cluster_send(rq);
54731 if (r) {
54732 u_rq->data_size = 0;
54733 u_rq->error = r;
54734 if (kernel_send(u_rq))
54735 LOG_ERROR("Failed to respond to kernel [%s]",
54736 RQ_TYPE(u_rq->request_type));
54737 }
54738
54739 break;
54740 case DM_ULOG_CLEAR_REGION:
54741 r = kernel_ack(u_rq->seq, 0);
54742
54743 r = cluster_send(rq);
54744 if (r) {
54745 /*
54746 * FIXME: store error for delivery on flush
54747 * This would allow us to optimize MARK_REGION
54748 * too.
54749 */
54750 }
54751
54752 break;
54753 default:
54754 LOG_ERROR("Invalid log request received (%u), ignoring.",
54755 u_rq->request_type);
54756
54757 return 0;
54758 }
54759
54760 if (r && !u_rq->error)
54761 u_rq->error = r;
54762
54763 return r;
54764}
54765
54766/*
54767 * kernel_send
54768 * @u_rq: result to pass back to kernel
54769 *
54770 * This function returns the u_rq structure
54771 * (containing the results) to the kernel.
54772 * It then frees the structure.
54773 *
54774 * WARNING: should the structure be freed if
54775 * there is an error? I vote 'yes'. If the
54776 * kernel doesn't get the response, it should
54777 * resend the request.
54778 *
54779 * Returns: 0 on success, -EXXX on failure
54780 */
54781int kernel_send(struct dm_ulog_request *u_rq)
54782{
54783 int r;
54784 uint16_t size;
54785
54786 if (!u_rq)
54787 return -EINVAL;
54788
54789 size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
54790
54791 if (!u_rq->data_size && !u_rq->error) {
54792 /* An ACK is all that is needed */
54793
54794 /* FIXME: add ACK code */
54795 } else if (size > DM_ULOG_REQUEST_SIZE) {
54796 /*
54797 * If we gotten here, we've already overrun
54798 * our allotted space somewhere.
54799 *
54800 * We must do something, because the kernel
54801 * is waiting for a response.
54802 */
54803 LOG_ERROR("Not enough space to respond to server");
54804 u_rq->error = -ENOSPC;
54805 size = sizeof(struct dm_ulog_request);
54806 }
54807
54808 r = kernel_send_helper(u_rq, size);
54809 if (r)
54810 LOG_ERROR("Failed to send msg to kernel.");
54811
54812 return r;
54813}
54814
54815/*
54816 * init_local
54817 *
54818 * Initialize kernel communication socket (netlink)
54819 *
54820 * Returns: 0 on success, values from common.h on failure
54821 */
54822int init_local(void)
54823{
54824 int r = 0;
54825 unsigned opt;
54826 struct sockaddr_nl addr;
54827
54828 cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
54829 if (cn_fd < 0)
54830 return EXIT_KERNEL_SOCKET;
54831
54832 /* memset to fix valgrind complaint */
54833 memset(&addr, 0, sizeof(struct sockaddr_nl));
54834
54835 addr.nl_family = AF_NETLINK;
54836 addr.nl_groups = CN_IDX_DM;
54837 addr.nl_pid = 0;
54838
54839 r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
54840 if (r < 0) {
54841 if (close(cn_fd))
54842 LOG_ERROR("Failed to close socket: %s",
54843 strerror(errno));
54844 return EXIT_KERNEL_BIND;
54845 }
54846
54847 opt = addr.nl_groups;
54848 r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
54849 if (r) {
54850 if (close(cn_fd))
54851 LOG_ERROR("Failed to close socket: %s",
54852 strerror(errno));
54853 return EXIT_KERNEL_SETSOCKOPT;
54854 }
54855
54856 /*
54857 r = fcntl(cn_fd, F_SETFL, FNDELAY);
54858 */
54859
54860 links_register(cn_fd, "local", do_local_work, NULL);
54861
54862 return 0;
54863}
54864
54865/*
54866 * cleanup_local
54867 *
54868 * Clean up before exiting
54869 */
54870void cleanup_local(void)
54871{
54872 links_unregister(cn_fd);
54873 if (cn_fd >= 0 && close(cn_fd))
54874 LOG_ERROR("Failed to close socket: %s",
54875 strerror(errno));
54876}
54877\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/logging.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004201\013062740170\0022112\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54878 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54879 *
54880 * This copyrighted material is made available to anyone wishing to use,
54881 * modify, copy, or redistribute it subject to the terms and conditions
54882 * of the GNU Lesser General Public License v.2.1.
54883 *
54884 * You should have received a copy of the GNU Lesser General Public License
54885 * along with this program; if not, write to the Free Software Foundation,
54886 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54887 */
54888
54889#ifndef _LVM_CLOG_LOGGING_H
54890#define _LVM_CLOG_LOGGING_H
54891
54892#define _GNU_SOURCE
54893#define _FILE_OFFSET_BITS 64
54894
54895#include "configure.h"
54896#include <stdio.h>
54897#include <stdint.h>
54898#include <syslog.h>
54899
54900/* SHORT_UUID - print last 8 chars of a string */
54901#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
54902
54903extern const char *__rq_types_off_by_one[];
54904#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
54905
54906extern int log_tabbing;
54907extern int log_is_open;
54908extern int log_membership_change;
54909extern int log_checkpoint;
54910extern int log_resend_requests;
54911
54912#define LOG_OPEN(ident, option, facility) do { \
54913 openlog(ident, option, facility); \
54914 log_is_open = 1; \
54915 } while (0)
54916
54917#define LOG_CLOSE(void) do { \
54918 log_is_open = 0; \
54919 closelog(); \
54920 } while (0)
54921
54922#define LOG_OUTPUT(level, f, arg...) do { \
54923 int __i; \
54924 char __buffer[16]; \
54925 FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
54926 if (log_is_open) { \
54927 for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
54928 __buffer[__i] = '\t'; \
54929 __buffer[__i] = '\0'; \
54930 syslog(level, "%s" f "\n", __buffer, ## arg); \
54931 } else { \
54932 for (__i = 0; __i < log_tabbing; __i++) \
54933 fprintf(fp, "\t"); \
54934 fprintf(fp, f "\n", ## arg); \
54935 } \
54936 } while (0)
54937
54938
54939#ifdef DEBUG
54940#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
54941#else /* DEBUG */
54942#define LOG_DBG(f, arg...) do {} while (0)
54943#endif /* DEBUG */
54944
54945#define LOG_COND(__X, f, arg...) do {\
54946 if (__X) { \
54947 LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
54948 } \
54949 } while (0)
54950#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
54951#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
54952
54953#endif /* _LVM_CLOG_LOGGING_H */
54954\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/clogd.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013671\013062740170\0021562\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
54955 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
54956 *
54957 * This copyrighted material is made available to anyone wishing to use,
54958 * modify, copy, or redistribute it subject to the terms and conditions
54959 * of the GNU General Public License v.2.
54960 *
54961 * You should have received a copy of the GNU General Public License
54962 * along with this program; if not, write to the Free Software Foundation,
54963 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54964 */
54965#include "logging.h"
54966#include "common.h"
54967#include "functions.h"
54968#include "link_mon.h"
54969#include "local.h"
54970
54971#include <getopt.h>
54972#include <errno.h>
54973#include <fcntl.h>
54974#include <sys/socket.h>
54975#include <sys/stat.h>
54976#include <sys/wait.h>
54977#include <unistd.h>
54978
54979static volatile sig_atomic_t exit_now = 0;
54980/* FIXME Review signal handling. Should be volatile sig_atomic_t */
54981static sigset_t signal_mask;
54982static volatile sig_atomic_t signal_received;
54983
54984static void process_signals(void);
54985static void daemonize(void);
54986static void init_all(void);
54987static void cleanup_all(void);
54988
54989static void usage (FILE *dest)
54990{
54991 fprintf (dest, "Usage: cmirrord [options]\n"
54992 " -f, --foreground stay in the foreground, log to the terminal\n"
54993 " -h, --help print this help\n");
54994}
54995
54996int main(int argc, char *argv[])
54997{
54998 int foreground_mode = 0;
54999 struct option longopts[] = {
55000 { "foreground", no_argument, NULL, 'f' },
55001 { "help" , no_argument, NULL, 'h' },
55002 { 0, 0, 0, 0 }
55003 };
55004 int opt;
55005
55006 while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
55007 switch (opt) {
55008 case 'f':
55009 foreground_mode = 1;
55010 break;
55011 case 'h':
55012 usage (stdout);
55013 exit (0);
55014 default:
55015 usage (stderr);
55016 exit (2);
55017 }
55018 }
55019 if (optind < argc) {
55020 usage (stderr);
55021 exit (2);
55022 }
55023
55024 if (!foreground_mode)
55025 daemonize();
55026
55027 init_all();
55028
55029 /* Parent can now exit, we're ready to handle requests */
55030 if (!foreground_mode)
55031 kill(getppid(), SIGTERM);
55032
55033 LOG_PRINT("Starting cmirrord:");
55034 LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
55035 LOG_DBG(" Compiled with debugging.");
55036
55037 while (!exit_now) {
55038 links_monitor();
55039
55040 links_issue_callbacks();
55041
55042 process_signals();
55043 }
55044 exit(EXIT_SUCCESS);
55045}
55046
55047/*
55048 * parent_exit_handler: exit the parent
55049 * @sig: the signal
55050 *
55051 */
55052static void parent_exit_handler(int sig __attribute__((unused)))
55053{
55054 exit_now = 1;
55055}
55056
55057static void sig_handler(int sig)
55058{
55059 /* FIXME Races - don't touch signal_mask here. */
55060 sigaddset(&signal_mask, sig);
55061 signal_received = 1;
55062}
55063
55064static void process_signal(int sig){
55065 int r = 0;
55066
55067 switch(sig) {
55068 case SIGINT:
55069 case SIGQUIT:
55070 case SIGTERM:
55071 case SIGHUP:
55072 r += log_status();
55073 break;
55074 case SIGUSR1:
55075 case SIGUSR2:
55076 log_debug();
55077 /*local_debug();*/
55078 cluster_debug();
55079 return;
55080 default:
55081 LOG_PRINT("Unknown signal received... ignoring");
55082 return;
55083 }
55084
55085 if (!r) {
55086 LOG_DBG("No current cluster logs... safe to exit.");
55087 cleanup_all();
55088 exit(EXIT_SUCCESS);
55089 }
55090
55091 LOG_ERROR("Cluster logs exist. Refusing to exit.");
55092}
55093
55094static void process_signals(void)
55095{
55096 int x;
55097
55098 if (!signal_received)
55099 return;
55100
55101 signal_received = 0;
55102
55103 for (x = 1; x < _NSIG; x++) {
55104 if (sigismember(&signal_mask, x)) {
55105 sigdelset(&signal_mask, x);
55106 process_signal(x);
55107 }
55108 }
55109}
55110
55111static void remove_lockfile(void)
55112{
55113 if (unlink(CMIRRORD_PIDFILE))
55114 LOG_ERROR("Unable to remove \"" CMIRRORD_PIDFILE "\" %s", strerror(errno));
55115}
55116
55117/*
55118 * daemonize
55119 *
55120 * Performs the steps necessary to become a daemon.
55121 */
55122static void daemonize(void)
55123{
55124 int pid;
55125 int status;
55126 int devnull;
55127
55128 if ((devnull = open("/dev/null", O_RDWR)) == -1) {
55129 LOG_ERROR("Can't open /dev/null: %s", strerror(errno));
55130 exit(EXIT_FAILURE);
55131 }
55132
55133 signal(SIGTERM, &parent_exit_handler);
55134
55135 pid = fork();
55136
55137 if (pid < 0) {
55138 LOG_ERROR("Unable to fork()");
55139 exit(EXIT_FAILURE);
55140 }
55141
55142 if (pid) {
55143 /* Parent waits here for child to get going */
55144 while (!waitpid(pid, &status, WNOHANG) && !exit_now);
55145 if (exit_now)
55146 exit(EXIT_SUCCESS);
55147
55148 switch (WEXITSTATUS(status)) {
55149 case EXIT_LOCKFILE:
55150 LOG_ERROR("Failed to create lockfile");
55151 LOG_ERROR("Process already running?");
55152 break;
55153 case EXIT_KERNEL_SOCKET:
55154 LOG_ERROR("Unable to create netlink socket");
55155 break;
55156 case EXIT_KERNEL_BIND:
55157 LOG_ERROR("Unable to bind to netlink socket");
55158 break;
55159 case EXIT_KERNEL_SETSOCKOPT:
55160 LOG_ERROR("Unable to setsockopt on netlink socket");
55161 break;
55162 case EXIT_CLUSTER_CKPT_INIT:
55163 LOG_ERROR("Unable to initialize checkpoint service");
55164 LOG_ERROR("Has the cluster infrastructure been started?");
55165 break;
55166 case EXIT_FAILURE:
55167 LOG_ERROR("Failed to start: Generic error");
55168 break;
55169 default:
55170 LOG_ERROR("Failed to start: Unknown error");
55171 break;
55172 }
55173 exit(EXIT_FAILURE);
55174 }
55175
55176 setsid();
55177 if (chdir("/")) {
55178 LOG_ERROR("Failed to chdir /: %s", strerror(errno));
55179 exit(EXIT_FAILURE);
55180 }
55181
55182 umask(0);
55183
55184 if (close(0) || close(1) || close(2)) {
55185 LOG_ERROR("Failed to close terminal FDs");
55186 exit(EXIT_FAILURE);
55187 }
55188
55189 if ((dup2(devnull, 0) < 0) || /* reopen stdin */
55190 (dup2(devnull, 1) < 0) || /* reopen stdout */
55191 (dup2(devnull, 2) < 0)) /* reopen stderr */
55192 exit(EXIT_FAILURE);
55193
55194 if ((devnull > STDERR_FILENO) && close(devnull)) {
55195 LOG_ERROR("Failed to close descriptor %d: %s",
55196 devnull, strerror(errno));
55197 exit(EXIT_FAILURE);
55198 }
55199
55200 LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
55201}
55202
55203/*
55204 * init_all
55205 *
55206 * Initialize modules. Exit on failure.
55207 */
55208static void init_all(void)
55209{
55210 int r;
55211
55212 (void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
55213 if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
55214 exit(EXIT_LOCKFILE);
55215 (void) dm_prepare_selinux_context(NULL, 0);
55216
55217 atexit(remove_lockfile);
55218
55219 /* FIXME Replace with sigaction. (deprecated) */
55220 signal(SIGINT, &sig_handler);
55221 signal(SIGQUIT, &sig_handler);
55222 signal(SIGTERM, &sig_handler);
55223 signal(SIGHUP, &sig_handler);
55224 signal(SIGPIPE, SIG_IGN);
55225 signal(SIGUSR1, &sig_handler);
55226 signal(SIGUSR2, &sig_handler);
55227 sigemptyset(&signal_mask);
55228 signal_received = 0;
55229
55230 if ((r = init_local()) ||
55231 (r = init_cluster())) {
55232 exit(r);
55233 }
55234}
55235
55236/*
55237 * cleanup_all
55238 *
55239 * Clean up before exiting
55240 */
55241static void cleanup_all(void)
55242{
55243 cleanup_local();
55244 cleanup_cluster();
55245}
55246\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002230\013062740170\0022360\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
55247# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
55248#
55249# This file is part of LVM2.
55250#
55251# This copyrighted material is made available to anyone wishing to use,
55252# modify, copy, or redistribute it subject to the terms and conditions
55253# of the GNU General Public License v.2.
55254#
55255# You should have received a copy of the GNU General Public License
55256# along with this program; if not, write to the Free Software Foundation,
55257# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
55258
55259srcdir = @srcdir@
55260top_srcdir = @top_srcdir@
55261top_builddir = @top_builddir@
55262
55263CPG_LIBS = @CPG_LIBS@
55264CPG_CFLAGS = @CPG_CFLAGS@
55265SACKPT_LIBS = @SACKPT_LIBS@
55266SACKPT_CFLAGS = @SACKPT_CFLAGS@
55267
55268SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
55269
55270TARGETS = cmirrord
55271
55272include $(top_builddir)/make.tmpl
55273
55274LIBS += -ldevmapper
55275LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
55276CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS)
55277LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
55278
55279cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
55280 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
55281 $(LVMLIBS) $(LMLIBS) $(LIBS)
55282
55283install: $(TARGETS)
55284 $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
55285\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/compat.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011730\013062740170\0021747\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
55286 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
55287 *
55288 * This copyrighted material is made available to anyone wishing to use,
55289 * modify, copy, or redistribute it subject to the terms and conditions
55290 * of the GNU Lesser General Public License v.2.1.
55291 */
55292#include "logging.h"
55293#include "cluster.h"
55294#include "compat.h"
55295#include "xlate.h"
55296
55297#include <errno.h>
55298
55299/*
55300 * Older versions of the log daemon communicate with different
55301 * versions of the inter-machine communication structure, which
55302 * varies in size and fields. The older versions append the
55303 * standard upstream version of the structure to every request.
55304 * COMPAT_OFFSET is where the upstream structure starts.
55305 */
55306#define COMPAT_OFFSET 256
55307
55308static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute__((unused)))
55309{
55310 int i, end;
55311 int64_t *pi64;
55312 uint64_t *pu64;
55313 uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
55314
55315 if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
55316 switch (rq_type) {
55317 case DM_ULOG_CTR:
55318 case DM_ULOG_DTR:
55319 LOG_ERROR("Invalid response type in endian switch");
55320 exit(EXIT_FAILURE);
55321
55322 case DM_ULOG_PRESUSPEND:
55323 case DM_ULOG_POSTSUSPEND:
55324 case DM_ULOG_RESUME:
55325 case DM_ULOG_FLUSH:
55326 case DM_ULOG_MARK_REGION:
55327 case DM_ULOG_CLEAR_REGION:
55328 case DM_ULOG_SET_REGION_SYNC:
55329 case DM_ULOG_CHECKPOINT_READY:
55330 case DM_ULOG_MEMBER_JOIN:
55331 case DM_ULOG_STATUS_INFO:
55332 case DM_ULOG_STATUS_TABLE:
55333 /* No outbound data */
55334 break;
55335
55336 case DM_ULOG_GET_REGION_SIZE:
55337 case DM_ULOG_GET_SYNC_COUNT:
55338 pu64 = (uint64_t *)rq->u_rq.data;
55339 *pu64 = xlate64(*pu64);
55340 break;
55341 case DM_ULOG_IS_CLEAN:
55342 case DM_ULOG_IN_SYNC:
55343 pi64 = (int64_t *)rq->u_rq.data;
55344 *pi64 = xlate64(*pi64);
55345 break;
55346 case DM_ULOG_GET_RESYNC_WORK:
55347 case DM_ULOG_IS_REMOTE_RECOVERING:
55348 pi64 = (int64_t *)rq->u_rq.data;
55349 pu64 = ((uint64_t *)rq->u_rq.data) + 1;
55350 *pi64 = xlate64(*pi64);
55351 *pu64 = xlate64(*pu64);
55352 break;
55353 default:
55354 LOG_ERROR("Unknown request type, %u", rq_type);
55355 return;
55356 }
55357 } else {
55358 switch (rq_type) {
55359 case DM_ULOG_CTR:
55360 case DM_ULOG_DTR:
55361 LOG_ERROR("Invalid request type in endian switch");
55362 exit(EXIT_FAILURE);
55363
55364 case DM_ULOG_PRESUSPEND:
55365 case DM_ULOG_POSTSUSPEND:
55366 case DM_ULOG_RESUME:
55367 case DM_ULOG_GET_REGION_SIZE:
55368 case DM_ULOG_FLUSH:
55369 case DM_ULOG_GET_RESYNC_WORK:
55370 case DM_ULOG_GET_SYNC_COUNT:
55371 case DM_ULOG_STATUS_INFO:
55372 case DM_ULOG_STATUS_TABLE:
55373 case DM_ULOG_CHECKPOINT_READY:
55374 case DM_ULOG_MEMBER_JOIN:
55375 /* No incoming data */
55376 break;
55377 case DM_ULOG_IS_CLEAN:
55378 case DM_ULOG_IN_SYNC:
55379 case DM_ULOG_IS_REMOTE_RECOVERING:
55380 pu64 = (uint64_t *)rq->u_rq.data;
55381 *pu64 = xlate64(*pu64);
55382 break;
55383 case DM_ULOG_MARK_REGION:
55384 case DM_ULOG_CLEAR_REGION:
55385 end = rq->u_rq.data_size/sizeof(uint64_t);
55386
55387 pu64 = (uint64_t *)rq->u_rq.data;
55388 for (i = 0; i < end; i++)
55389 pu64[i] = xlate64(pu64[i]);
55390 break;
55391 case DM_ULOG_SET_REGION_SYNC:
55392 pu64 = (uint64_t *)rq->u_rq.data;
55393 pi64 = ((int64_t *)rq->u_rq.data) + 1;
55394 *pu64 = xlate64(*pu64);
55395 *pi64 = xlate64(*pi64);
55396 break;
55397 default:
55398 LOG_ERROR("Unknown request type, %u", rq_type);
55399 exit(EXIT_FAILURE);
55400 }
55401 }
55402}
55403
55404static int v5_endian_to_network(struct clog_request *rq)
55405{
55406 int size;
55407 struct dm_ulog_request *u_rq = &rq->u_rq;
55408
55409 size = sizeof(*rq) + u_rq->data_size;
55410
55411 u_rq->error = xlate32(u_rq->error);
55412 u_rq->seq = xlate32(u_rq->seq);
55413
55414 rq->originator = xlate32(rq->originator);
55415
55416 v5_data_endian_switch(rq, 1);
55417
55418 u_rq->request_type = xlate32(u_rq->request_type);
55419 u_rq->data_size = xlate32(u_rq->data_size);
55420
55421 return size;
55422}
55423
55424int clog_request_to_network(struct clog_request *rq)
55425{
55426 int r;
55427
55428 /* FIXME: Remove this safety check */
55429 if (rq->u.version[0] != xlate64(rq->u.version[1])) {
55430 LOG_ERROR("Programmer error: version[0] must be LE");
55431 exit(EXIT_FAILURE);
55432 }
55433
55434 /*
55435 * Are we already running in the endian mode we send
55436 * over the wire?
55437 */
55438 if (rq->u.version[0] == rq->u.version[1])
55439 return 0;
55440
55441 r = v5_endian_to_network(rq);
55442 if (r < 0)
55443 return r;
55444 return 0;
55445}
55446
55447static int v5_endian_from_network(struct clog_request *rq)
55448{
55449 int size;
55450 struct dm_ulog_request *u_rq = &rq->u_rq;
55451
55452 u_rq->error = xlate32(u_rq->error);
55453 u_rq->seq = xlate32(u_rq->seq);
55454 u_rq->request_type = xlate32(u_rq->request_type);
55455 u_rq->data_size = xlate32(u_rq->data_size);
55456
55457 rq->originator = xlate32(rq->originator);
55458
55459 size = sizeof(*rq) + u_rq->data_size;
55460
55461 v5_data_endian_switch(rq, 0);
55462
55463 return size;
55464}
55465
55466int clog_request_from_network(void *data, size_t data_len)
55467{
55468 uint64_t *vp = data;
55469 uint64_t version = xlate64(vp[0]);
55470 struct clog_request *rq = data;
55471
55472 switch (version) {
55473 case 5: /* Upstream */
55474 if (version == vp[0])
55475 return 0;
55476 break;
55477 case 4: /* RHEL 5.[45] */
55478 case 3: /* RHEL 5.3 */
55479 case 2: /* RHEL 5.2 */
55480 /* FIXME: still need to account for payload */
55481 if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
55482 return -ENOSPC;
55483
55484 rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
55485 break;
55486 default:
55487 LOG_ERROR("Unable to process cluster message: "
55488 "Incompatible version");
55489 return -EINVAL;
55490 }
55491
55492 v5_endian_from_network(rq);
55493 return 0;
55494}
55495\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/cmirrord/functions.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000133221\013062740170\0022474\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
55496 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
55497 *
55498 * This copyrighted material is made available to anyone wishing to use,
55499 * modify, copy, or redistribute it subject to the terms and conditions
55500 * of the GNU Lesser General Public License v.2.1.
55501 *
55502 * You should have received a copy of the GNU Lesser General Public License
55503 * along with this program; if not, write to the Free Software Foundation,
55504 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
55505 */
55506#include "logging.h"
55507#include "functions.h"
55508
55509#include <sys/sysmacros.h>
55510#include <dirent.h>
55511#include <errno.h>
55512#include <fcntl.h>
55513#include <signal.h>
55514#include <sys/stat.h>
55515#include <time.h>
55516#include <unistd.h>
55517
55518#define BYTE_SHIFT 3
55519
55520/*
55521 * Magic for persistent mirrors: "MiRr"
55522 * Following on-disk header information is stolen from
55523 * drivers/md/dm-log.c
55524 */
55525#define MIRROR_MAGIC 0x4D695272
55526#define MIRROR_DISK_VERSION 2
55527#define LOG_OFFSET 2
55528
55529#define RESYNC_HISTORY 50
55530#define RESYNC_BUFLEN 128
55531//static char resync_history[RESYNC_HISTORY][128];
55532//static int idx = 0;
55533#define LOG_SPRINT(_lc, f, arg...) do { \
55534 lc->idx++; \
55535 lc->idx = lc->idx % RESYNC_HISTORY; \
55536 snprintf(lc->resync_history[lc->idx], RESYNC_BUFLEN, f, ## arg); \
55537 } while (0)
55538
55539struct log_header {
55540 uint32_t magic;
55541 uint32_t version;
55542 uint64_t nr_regions;
55543};
55544
55545struct log_c {
55546 struct dm_list list;
55547
55548 char uuid[DM_UUID_LEN];
55549 uint64_t luid;
55550
55551 time_t delay; /* limits how fast a resume can happen after suspend */
55552 int touched;
55553 int in_sync; /* An in-sync that stays set until suspend/resume */
55554 uint32_t region_size;
55555 uint32_t region_count;
55556 uint64_t sync_count;
55557
55558 dm_bitset_t clean_bits;
55559 dm_bitset_t sync_bits;
55560 uint32_t recoverer;
55561 uint64_t recovering_region; /* -1 means not recovering */
55562 uint64_t skip_bit_warning; /* used to warn if region skipped */
55563 int sync_search;
55564
55565 int resume_override;
55566
55567 uint32_t block_on_error;
55568 enum sync {
55569 DEFAULTSYNC, /* Synchronize if necessary */
55570 NOSYNC, /* Devices known to be already in sync */
55571 FORCESYNC, /* Force a sync to happen */
55572 } sync;
55573
55574 uint32_t state; /* current operational state of the log */
55575
55576 struct dm_list mark_list;
55577
55578 uint32_t recovery_halted;
55579 struct recovery_request *recovery_request_list;
55580
55581 int disk_fd; /* -1 means no disk log */
55582 int log_dev_failed;
55583 uint64_t disk_nr_regions;
55584 size_t disk_size; /* size of disk_buffer in bytes */
55585 void *disk_buffer; /* aligned memory for O_DIRECT */
55586 int idx;
55587 char resync_history[RESYNC_HISTORY][RESYNC_BUFLEN];
55588};
55589
55590struct mark_entry {
55591 struct dm_list list;
55592 uint32_t nodeid;
55593 uint64_t region;
55594};
55595
55596struct recovery_request {
55597 uint64_t region;
55598 struct recovery_request *next;
55599};
55600
55601static DM_LIST_INIT(log_list);
55602static DM_LIST_INIT(log_pending_list);
55603
55604static int log_test_bit(dm_bitset_t bs, int bit)
55605{
55606 return dm_bit(bs, bit) ? 1 : 0;
55607}
55608
55609static void log_set_bit(struct log_c *lc, dm_bitset_t bs, int bit)
55610{
55611 dm_bit_set(bs, bit);
55612 lc->touched = 1;
55613}
55614
55615static void log_clear_bit(struct log_c *lc, dm_bitset_t bs, int bit)
55616{
55617 dm_bit_clear(bs, bit);
55618 lc->touched = 1;
55619}
55620
55621static uint64_t find_next_zero_bit(dm_bitset_t bs, unsigned start)
55622{
55623 for (; dm_bit(bs, start); start++)
55624 if (start >= *bs)
55625 return (uint64_t)-1;
55626
55627 return start;
55628}
55629
55630static uint64_t count_bits32(dm_bitset_t bs)
55631{
55632 unsigned i, size = bs[0]/(unsigned)DM_BITS_PER_INT + 1;
55633 unsigned count = 0;
55634
55635 for (i = 1; i <= size; i++)
55636 count += hweight32(bs[i]);
55637
55638 return (uint64_t)count;
55639}
55640
55641/*
55642 * get_log
55643 *
55644 * Returns: log if found, NULL otherwise
55645 */
55646static struct log_c *get_log(const char *uuid, uint64_t luid)
55647{
55648 struct log_c *lc;
55649
55650 dm_list_iterate_items(lc, &log_list)
55651 if (!strcmp(lc->uuid, uuid) &&
55652 (!luid || (luid == lc->luid)))
55653 return lc;
55654
55655 return NULL;
55656}
55657
55658/*
55659 * get_pending_log
55660 *
55661 * Pending logs are logs that have been 'clog_ctr'ed, but
55662 * have not joined the CPG (via clog_resume).
55663 *
55664 * Returns: log if found, NULL otherwise
55665 */
55666static struct log_c *get_pending_log(const char *uuid, uint64_t luid)
55667{
55668 struct log_c *lc;
55669
55670 dm_list_iterate_items(lc, &log_pending_list)
55671 if (!strcmp(lc->uuid, uuid) &&
55672 (!luid || (luid == lc->luid)))
55673 return lc;
55674
55675 return NULL;
55676}
55677
55678static void header_to_disk(struct log_header *mem, struct log_header *disk)
55679{
55680 memcpy(disk, mem, sizeof(struct log_header));
55681}
55682
55683static void header_from_disk(struct log_header *mem, struct log_header *disk)
55684{
55685 memcpy(mem, disk, sizeof(struct log_header));
55686}
55687
55688static int rw_log(struct log_c *lc, int do_write)
55689{
55690 int r;
55691
55692 r = (int)lseek(lc->disk_fd, 0, SEEK_SET);
55693 if (r < 0) {
55694 LOG_ERROR("[%s] rw_log: lseek failure: %s",
55695 SHORT_UUID(lc->uuid), strerror(errno));
55696 return -errno;
55697 }
55698
55699 if (do_write) {
55700 /* FIXME Cope with full set of non-error conditions */
55701 r = write(lc->disk_fd, lc->disk_buffer, lc->disk_size);
55702 if (r < 0) {
55703 LOG_ERROR("[%s] rw_log: write failure: %s",
55704 SHORT_UUID(lc->uuid), strerror(errno));
55705 return -EIO; /* Failed disk write */
55706 }
55707 return 0;
55708 }
55709
55710 /* Read */
55711 /* FIXME Cope with full set of non-error conditions */
55712 r = read(lc->disk_fd, lc->disk_buffer, lc->disk_size);
55713 if (r < 0)
55714 LOG_ERROR("[%s] rw_log: read failure: %s",
55715 SHORT_UUID(lc->uuid), strerror(errno));
55716 if (r != lc->disk_size)
55717 return -EIO; /* Failed disk read */
55718 return 0;
55719}
55720
55721/*
55722 * read_log
55723 * @lc
55724 *
55725 * Valid return codes:
55726 * -EINVAL: Invalid header, bits not copied
55727 * -EIO: Unable to read disk log
55728 * 0: Valid header, disk bit -> lc->clean_bits
55729 *
55730 * Returns: 0 on success, -EXXX on failure
55731 */
55732static int read_log(struct log_c *lc)
55733{
55734 struct log_header lh = { 0 };
55735 size_t bitset_size;
55736
55737 if (rw_log(lc, 0))
55738 return -EIO; /* Failed disk read */
55739
55740 header_from_disk(&lh, lc->disk_buffer);
55741 if (lh.magic != MIRROR_MAGIC)
55742 return -EINVAL;
55743
55744 lc->disk_nr_regions = lh.nr_regions;
55745
55746 /* Read disk bits into sync_bits */
55747 bitset_size = lc->region_count / 8;
55748 bitset_size += (lc->region_count % 8) ? 1 : 0;
55749
55750 /* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
55751 memcpy(lc->clean_bits + 1, (char *)lc->disk_buffer + 1024, bitset_size);
55752
55753 return 0;
55754}
55755
55756/*
55757 * write_log
55758 * @lc
55759 *
55760 * Returns: 0 on success, -EIO on failure
55761 */
55762static int write_log(struct log_c *lc)
55763{
55764 struct log_header lh;
55765 size_t bitset_size;
55766
55767 lh.magic = MIRROR_MAGIC;
55768 lh.version = MIRROR_DISK_VERSION;
55769 lh.nr_regions = lc->region_count;
55770
55771 header_to_disk(&lh, lc->disk_buffer);
55772
55773 /* Write disk bits from clean_bits */
55774 bitset_size = lc->region_count / 8;
55775 bitset_size += (lc->region_count % 8) ? 1 : 0;
55776
55777 /* 'lc->clean_bits + 1' becasue dm_bitset_t leads with a uint32_t */
55778 memcpy((char *)lc->disk_buffer + 1024, lc->clean_bits + 1, bitset_size);
55779
55780 if (rw_log(lc, 1)) {
55781 lc->log_dev_failed = 1;
55782 return -EIO; /* Failed disk write */
55783 }
55784 return 0;
55785}
55786
55787/* FIXME Rewrite this function taking advantage of the udev changes (where in use) to improve its efficiency! */
55788static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_path __attribute__((unused)))
55789{
55790 int r;
55791 DIR *dp;
55792 struct dirent *dep;
55793 struct stat statbuf;
55794 int major, minor;
55795
55796 if (!strstr(major_minor_str, ":")) {
55797 r = stat(major_minor_str, &statbuf);
55798 if (r)
55799 return -errno;
55800 if (!S_ISBLK(statbuf.st_mode))
55801 return -EINVAL;
55802 sprintf(path_rtn, "%s", major_minor_str);
55803 return 0;
55804 }
55805
55806 r = sscanf(major_minor_str, "%d:%d", &major, &minor);
55807 if (r != 2)
55808 return -EINVAL;
55809
55810 /* FIXME dm_dir() */
55811 LOG_DBG("Checking /dev/mapper for device %d:%d", major, minor);
55812 /* Check /dev/mapper dir */
55813 dp = opendir("/dev/mapper");
55814 if (!dp)
55815 return -ENOENT;
55816
55817 while ((dep = readdir(dp)) != NULL) {
55818 /*
55819 * FIXME: This is racy. By the time the path is used,
55820 * it may point to something else. 'fstat' will be
55821 * required upon opening to ensure we got what we
55822 * wanted.
55823 */
55824
55825 sprintf(path_rtn, "/dev/mapper/%s", dep->d_name);
55826 if (stat(path_rtn, &statbuf) < 0) {
55827 LOG_DBG("Unable to stat %s", path_rtn);
55828 continue;
55829 }
55830 if (S_ISBLK(statbuf.st_mode) &&
55831 (major(statbuf.st_rdev) == major) &&
55832 (minor(statbuf.st_rdev) == minor)) {
55833 LOG_DBG(" %s: YES", dep->d_name);
55834 if (closedir(dp))
55835 LOG_DBG("Unable to closedir /dev/mapper %s",
55836 strerror(errno));
55837 return 0;
55838 } else {
55839 LOG_DBG(" %s: NO", dep->d_name);
55840 }
55841 }
55842
55843 if (closedir(dp))
55844 LOG_DBG("Unable to closedir /dev/mapper %s",
55845 strerror(errno));
55846
55847 /* FIXME Find out why this was here and deal with underlying problem. */
55848 LOG_DBG("Path not found for %d/%d", major, minor);
55849 return -ENOENT;
55850
55851 // LOG_DBG("Creating /dev/mapper/%d-%d", major, minor);
55852 // sprintf(path_rtn, "/dev/mapper/%d-%d", major, minor);
55853 // r = mknod(path_rtn, S_IFBLK | S_IRUSR | S_IWUSR, MKDEV(major, minor));
55854 /*
55855 * If we have to make the path, we unlink it after we open it
55856 */
55857 // *unlink_path = 1;
55858 // return r ? -errno : 0;
55859}
55860
55861static int _clog_ctr(char *uuid, uint64_t luid,
55862 int argc, char **argv, uint64_t device_size)
55863{
55864 int i;
55865 int r = 0;
55866 char *p;
55867 uint64_t region_size;
55868 uint64_t region_count;
55869 struct log_c *lc = NULL;
55870 enum sync log_sync = DEFAULTSYNC;
55871 uint32_t block_on_error = 0;
55872
55873 int disk_log;
55874 char disk_path[128];
55875 int unlink_path = 0;
55876 long page_size;
55877 int pages;
55878
55879 /* If core log request, then argv[0] will be region_size */
55880 if (!strtoll(argv[0], &p, 0) || *p) {
55881 disk_log = 1;
55882
55883 if ((argc < 2) || (argc > 4)) {
55884 LOG_ERROR("Too %s arguments to clustered-disk log type",
55885 (argc < 3) ? "few" : "many");
55886 r = -EINVAL;
55887 goto fail;
55888 }
55889
55890 r = find_disk_path(argv[0], disk_path, &unlink_path);
55891 if (r) {
55892 LOG_ERROR("Unable to find path to device %s", argv[0]);
55893 goto fail;
55894 }
55895 LOG_DBG("Clustered log disk is %s", disk_path);
55896 } else {
55897 disk_log = 0;
55898
55899 if ((argc < 1) || (argc > 3)) {
55900 LOG_ERROR("Too %s arguments to clustered-core log type",
55901 (argc < 2) ? "few" : "many");
55902 r = -EINVAL;
55903 goto fail;
55904 }
55905 }
55906
55907 if (!(region_size = strtoll(argv[disk_log], &p, 0)) || *p) {
55908 LOG_ERROR("Invalid region_size argument to clustered-%s log type",
55909 (disk_log) ? "disk" : "core");
55910 r = -EINVAL;
55911 goto fail;
55912 }
55913
55914 region_count = device_size / region_size;
55915 if (device_size % region_size) {
55916 /*
55917 * I can't remember if device_size must be a multiple
55918 * of region_size, so check it anyway.
55919 */
55920 region_count++;
55921 }
55922
55923 for (i = 0; i < argc; i++) {
55924 if (!strcmp(argv[i], "sync"))
55925 log_sync = FORCESYNC;
55926 else if (!strcmp(argv[i], "nosync"))
55927 log_sync = NOSYNC;
55928 else if (!strcmp(argv[i], "block_on_error"))
55929 block_on_error = 1;
55930 }
55931
55932 lc = dm_zalloc(sizeof(*lc));
55933 if (!lc) {
55934 LOG_ERROR("Unable to allocate cluster log context");
55935 r = -ENOMEM;
55936 goto fail;
55937 }
55938
55939 lc->region_size = region_size;
55940 lc->region_count = region_count;
55941 lc->sync = log_sync;
55942 lc->block_on_error = block_on_error;
55943 lc->sync_search = 0;
55944 lc->recovering_region = (uint64_t)-1;
55945 lc->skip_bit_warning = region_count;
55946 lc->disk_fd = -1;
55947 lc->log_dev_failed = 0;
55948 strncpy(lc->uuid, uuid, DM_UUID_LEN);
55949 lc->luid = luid;
55950
55951 if (get_log(lc->uuid, lc->luid) ||
55952 get_pending_log(lc->uuid, lc->luid)) {
55953 LOG_ERROR("[%s/%" PRIu64 "u] Log already exists, unable to create.",
55954 SHORT_UUID(lc->uuid), lc->luid);
55955 dm_free(lc);
55956 return -EINVAL;
55957 }
55958
55959 dm_list_init(&lc->mark_list);
55960
55961 lc->clean_bits = dm_bitset_create(NULL, region_count);
55962 if (!lc->clean_bits) {
55963 LOG_ERROR("Unable to allocate clean bitset");
55964 r = -ENOMEM;
55965 goto fail;
55966 }
55967
55968 lc->sync_bits = dm_bitset_create(NULL, region_count);
55969 if (!lc->sync_bits) {
55970 LOG_ERROR("Unable to allocate sync bitset");
55971 r = -ENOMEM;
55972 goto fail;
55973 }
55974 if (log_sync == NOSYNC)
55975 dm_bit_set_all(lc->sync_bits);
55976
55977 lc->sync_count = (log_sync == NOSYNC) ? region_count : 0;
55978
55979 if (disk_log) {
55980 if ((page_size = sysconf(_SC_PAGESIZE)) < 0) {
55981 LOG_ERROR("Unable to read pagesize: %s",
55982 strerror(errno));
55983 r = errno;
55984 goto fail;
55985 }
55986 pages = *(lc->clean_bits) / page_size;
55987 pages += *(lc->clean_bits) % page_size ? 1 : 0;
55988 pages += 1; /* for header */
55989
55990 r = open(disk_path, O_RDWR | O_DIRECT);
55991 if (r < 0) {
55992 LOG_ERROR("Unable to open log device, %s: %s",
55993 disk_path, strerror(errno));
55994 r = errno;
55995 goto fail;
55996 }
55997 if (unlink_path)
55998 if (unlink(disk_path) < 0) {
55999 LOG_DBG("Warning: Unable to unlink log device, %s: %s",
56000 disk_path, strerror(errno));
56001 }
56002
56003 lc->disk_fd = r;
56004 lc->disk_size = pages * page_size;
56005
56006 r = posix_memalign(&(lc->disk_buffer), page_size,
56007 lc->disk_size);
56008 if (r) {
56009 LOG_ERROR("Unable to allocate memory for disk_buffer");
56010 goto fail;
56011 }
56012 memset(lc->disk_buffer, 0, lc->disk_size);
56013 LOG_DBG("Disk log ready");
56014 }
56015
56016 dm_list_add(&log_pending_list, &lc->list);
56017
56018 return 0;
56019fail:
56020 if (lc) {
56021 if (lc->disk_fd >= 0 && close(lc->disk_fd))
56022 LOG_ERROR("Close device error, %s: %s",
56023 disk_path, strerror(errno));
56024 free(lc->disk_buffer);
56025 dm_free(lc->sync_bits);
56026 dm_free(lc->clean_bits);
56027 dm_free(lc);
56028 }
56029 return r;
56030}
56031
56032/*
56033 * clog_ctr
56034 * @rq
56035 *
56036 * rq->data should contain constructor string as follows:
56037 * <log_type> [disk] <region_size> [[no]sync] <device_len>
56038 * The kernel is responsible for adding the <dev_len> argument
56039 * to the end; otherwise, we cannot compute the region_count.
56040 *
56041 * FIXME: Currently relies on caller to fill in rq->error
56042 */
56043static int clog_dtr(struct dm_ulog_request *rq);
56044static int clog_ctr(struct dm_ulog_request *rq)
56045{
56046 int argc, i, r = 0;
56047 char *p, **argv = NULL;
56048 char *dev_size_str;
56049 uint64_t device_size;
56050
56051 /* Sanity checks */
56052 if (!rq->data_size) {
56053 LOG_ERROR("Received constructor request with no data");
56054 return -EINVAL;
56055 }
56056
56057 if (strlen(rq->data) > rq->data_size) {
56058 LOG_ERROR("Received constructor request with bad data");
56059 LOG_ERROR("strlen(rq->data)[%d] != rq->data_size[%llu]",
56060 (int)strlen(rq->data),
56061 (unsigned long long)rq->data_size);
56062 LOG_ERROR("rq->data = '%s' [%d]",
56063 rq->data, (int)strlen(rq->data));
56064 return -EINVAL;
56065 }
56066
56067 /* Split up args */
56068 for (argc = 0, p = rq->data; (p = strstr(p, " ")); p++, argc++)
56069 *p = '\0';
56070
56071 if (!argc) {
56072 LOG_ERROR("Received constructor request with bad data %s",
56073 rq->data);
56074 return -EINVAL;
56075 }
56076
56077 argv = malloc(argc * sizeof(char *));
56078 if (!argv)
56079 return -ENOMEM;
56080
56081 p = dev_size_str = rq->data;
56082 p += strlen(p) + 1;
56083 for (i = 0; i < argc; i++, p = p + strlen(p) + 1)
56084 argv[i] = p;
56085
56086 if (strcmp(argv[0], "clustered-disk") &&
56087 strcmp(argv[0], "clustered-core")) {
56088 LOG_ERROR("Unsupported userspace log type, \"%s\"", argv[0]);
56089 free(argv);
56090 return -EINVAL;
56091 }
56092
56093 if (!(device_size = strtoll(dev_size_str, &p, 0)) || *p) {
56094 LOG_ERROR("Invalid device size argument: %s", dev_size_str);
56095 free(argv);
56096 return -EINVAL;
56097 }
56098
56099 r = _clog_ctr(rq->uuid, rq->luid, argc - 1, argv + 1, device_size);
56100
56101 /* We join the CPG when we resume */
56102
56103 /* No returning data */
56104 if ((rq->version > 1) && !strcmp(argv[0], "clustered-disk"))
56105 rq->data_size = sprintf(rq->data, "%s", argv[1]) + 1;
56106 else
56107 rq->data_size = 0;
56108
56109 if (r) {
56110 LOG_ERROR("Failed to create cluster log (%s)", rq->uuid);
56111 for (i = 0; i < argc; i++)
56112 LOG_ERROR("argv[%d] = %s", i, argv[i]);
56113 }
56114 else
56115 LOG_DBG("[%s] Cluster log created",
56116 SHORT_UUID(rq->uuid));
56117
56118 free(argv);
56119 return r;
56120}
56121
56122/*
56123 * clog_dtr
56124 * @rq
56125 *
56126 */
56127static int clog_dtr(struct dm_ulog_request *rq)
56128{
56129 struct log_c *lc = get_log(rq->uuid, rq->luid);
56130
56131 if (lc) {
56132 /*
56133 * The log should not be on the official list. There
56134 * should have been a suspend first.
56135 */
56136 LOG_ERROR("[%s] DTR before SUS: leaving CPG",
56137 SHORT_UUID(rq->uuid));
56138 destroy_cluster_cpg(rq->uuid);
56139 } else if (!(lc = get_pending_log(rq->uuid, rq->luid))) {
56140 LOG_ERROR("clog_dtr called on log that is not official or pending");
56141 return -EINVAL;
56142 }
56143
56144 LOG_DBG("[%s] Cluster log removed", SHORT_UUID(lc->uuid));
56145
56146 dm_list_del(&lc->list);
56147 if (lc->disk_fd != -1 && close(lc->disk_fd))
56148 LOG_ERROR("Failed to close disk log: %s",
56149 strerror(errno));
56150 if (lc->disk_buffer)
56151 free(lc->disk_buffer);
56152 dm_free(lc->clean_bits);
56153 dm_free(lc->sync_bits);
56154 dm_free(lc);
56155
56156 return 0;
56157}
56158
56159/*
56160 * clog_presuspend
56161 * @rq
56162 *
56163 */
56164static int clog_presuspend(struct dm_ulog_request *rq)
56165{
56166 struct log_c *lc = get_log(rq->uuid, rq->luid);
56167
56168 if (!lc)
56169 return -EINVAL;
56170
56171 if (lc->touched)
56172 LOG_DBG("WARNING: log still marked as 'touched' during suspend");
56173
56174 lc->recovery_halted = 1;
56175
56176 return 0;
56177}
56178
56179/*
56180 * clog_postsuspend
56181 * @rq
56182 *
56183 */
56184static int clog_postsuspend(struct dm_ulog_request *rq)
56185{
56186 struct log_c *lc = get_log(rq->uuid, rq->luid);
56187
56188 if (!lc)
56189 return -EINVAL;
56190
56191 LOG_DBG("[%s] clog_postsuspend: leaving CPG", SHORT_UUID(lc->uuid));
56192 destroy_cluster_cpg(rq->uuid);
56193
56194 lc->state = LOG_SUSPENDED;
56195 lc->recovering_region = (uint64_t)-1;
56196 lc->recoverer = (uint32_t)-1;
56197 lc->delay = time(NULL);
56198
56199 return 0;
56200}
56201
56202/*
56203 * cluster_postsuspend
56204 * @rq
56205 *
56206 */
56207int cluster_postsuspend(char *uuid, uint64_t luid)
56208{
56209 struct log_c *lc = get_log(uuid, luid);
56210
56211 if (!lc)
56212 return -EINVAL;
56213
56214 LOG_DBG("[%s] clog_postsuspend: finalizing", SHORT_UUID(lc->uuid));
56215 lc->resume_override = 0;
56216
56217 /* move log to pending list */
56218 dm_list_del(&lc->list);
56219 dm_list_add(&log_pending_list, &lc->list);
56220
56221 return 0;
56222}
56223
56224/*
56225 * clog_resume
56226 * @rq
56227 *
56228 * Does the main work of resuming.
56229 */
56230static int clog_resume(struct dm_ulog_request *rq)
56231{
56232 uint32_t i;
56233 int commit_log = 0;
56234 struct log_c *lc = get_log(rq->uuid, rq->luid);
56235
56236 if (!lc)
56237 return -EINVAL;
56238
56239 lc->in_sync = 0;
56240 switch (lc->resume_override) {
56241 case 1000:
56242 LOG_ERROR("[%s] Additional resume issued before suspend",
56243 SHORT_UUID(rq->uuid));
56244#ifdef DEBUG
56245 kill(getpid(), SIGUSR1);
56246#endif
56247 return 0;
56248 case 0:
56249 lc->resume_override = 1000;
56250 if (lc->disk_fd == -1) {
56251 LOG_DBG("[%s] Master resume.",
56252 SHORT_UUID(lc->uuid));
56253 goto no_disk;
56254 }
56255
56256 LOG_DBG("[%s] Master resume: reading disk log",
56257 SHORT_UUID(lc->uuid));
56258 commit_log = 1;
56259 break;
56260 case 1:
56261 LOG_ERROR("Error:: partial bit loading (just sync_bits)");
56262 return -EINVAL;
56263 case 2:
56264 LOG_ERROR("Error:: partial bit loading (just clean_bits)");
56265 return -EINVAL;
56266 case 3:
56267 LOG_DBG("[%s] Non-master resume: bits pre-loaded",
56268 SHORT_UUID(lc->uuid));
56269 lc->resume_override = 1000;
56270 goto out;
56271 default:
56272 LOG_ERROR("Error:: multiple loading of bits (%d)",
56273 lc->resume_override);
56274 return -EINVAL;
56275 }
56276
56277 if (lc->log_dev_failed) {
56278 LOG_ERROR("Log device has failed, unable to read bits");
56279 rq->error = 0; /* We can handle this so far */
56280 lc->disk_nr_regions = 0;
56281 } else
56282 rq->error = read_log(lc);
56283
56284 switch (rq->error) {
56285 case 0:
56286 if (lc->disk_nr_regions < lc->region_count)
56287 LOG_DBG("[%s] Mirror has grown, updating log bits",
56288 SHORT_UUID(lc->uuid));
56289 else if (lc->disk_nr_regions > lc->region_count)
56290 LOG_DBG("[%s] Mirror has shrunk, updating log bits",
56291 SHORT_UUID(lc->uuid));
56292 break;
56293 case -EINVAL:
56294 LOG_DBG("[%s] (Re)initializing mirror log - resync issued.",
56295 SHORT_UUID(lc->uuid));
56296 lc->disk_nr_regions = 0;
56297 break;
56298 default:
56299 LOG_ERROR("Failed to read disk log");
56300 lc->disk_nr_regions = 0;
56301 break;
56302 }
56303
56304no_disk:
56305 /* If mirror has grown, set bits appropriately */
56306 if (lc->sync == NOSYNC)
56307 for (i = lc->disk_nr_regions; i < lc->region_count; i++)
56308 log_set_bit(lc, lc->clean_bits, i);
56309 else
56310 for (i = lc->disk_nr_regions; i < lc->region_count; i++)
56311 log_clear_bit(lc, lc->clean_bits, i);
56312
56313 /* Clear any old bits if device has shrunk */
56314 for (i = lc->region_count; i % 32; i++)
56315 log_clear_bit(lc, lc->clean_bits, i);
56316
56317 /* copy clean across to sync */
56318 dm_bit_copy(lc->sync_bits, lc->clean_bits);
56319
56320 if (commit_log && (lc->disk_fd >= 0)) {
56321 rq->error = write_log(lc);
56322 if (rq->error)
56323 LOG_ERROR("Failed initial disk log write");
56324 else
56325 LOG_DBG("Disk log initialized");
56326 lc->touched = 0;
56327 }
56328out:
56329 /*
56330 * Clear any old bits if device has shrunk - necessary
56331 * for non-master resume
56332 */
56333 for (i = lc->region_count; i % 32; i++) {
56334 log_clear_bit(lc, lc->clean_bits, i);
56335 log_clear_bit(lc, lc->sync_bits, i);
56336 }
56337
56338 lc->sync_count = count_bits32(lc->sync_bits);
56339
56340 LOG_SPRINT(lc, "[%s] Initial sync_count = %llu",
56341 SHORT_UUID(lc->uuid), (unsigned long long)lc->sync_count);
56342 lc->sync_search = 0;
56343 lc->state = LOG_RESUMED;
56344 lc->recovery_halted = 0;
56345
56346 return rq->error;
56347}
56348
56349/*
56350 * local_resume
56351 * @rq
56352 *
56353 * If the log is pending, we must first join the cpg and
56354 * put the log in the official list.
56355 *
56356 */
56357int local_resume(struct dm_ulog_request *rq)
56358{
56359 int r;
56360 time_t t;
56361 struct log_c *lc = get_log(rq->uuid, rq->luid);
56362
56363 if (!lc) {
56364 /* Is the log in the pending list? */
56365 lc = get_pending_log(rq->uuid, rq->luid);
56366 if (!lc) {
56367 LOG_ERROR("clog_resume called on log that is not official or pending");
56368 return -EINVAL;
56369 }
56370
56371 t = time(NULL);
56372 t -= lc->delay;
56373 /*
56374 * This should be considered a temporary fix. It addresses
56375 * a problem that exists when nodes suspend/resume in rapid
56376 * succession. While the problem is very rare, it has been
56377 * seen to happen in real-world-like testing.
56378 *
56379 * The problem:
56380 * - Node A joins cluster
56381 * - Node B joins cluster
56382 * - Node A prepares checkpoint
56383 * - Node A gets ready to write checkpoint
56384 * - Node B leaves
56385 * - Node B joins
56386 * - Node A finishes write of checkpoint
56387 * - Node B receives checkpoint meant for previous session
56388 * -- Node B can now be non-coherent
56389 *
56390 * This timer will solve the problem for now, but could be
56391 * replaced by a generation number sent with the resume
56392 * command from the kernel. The generation number would
56393 * be included in the name of the checkpoint to prevent
56394 * reading stale data.
56395 */
56396 if ((t < 3) && (t >= 0))
56397 sleep(3 - t);
56398
56399 /* Join the CPG */
56400 r = create_cluster_cpg(rq->uuid, rq->luid);
56401 if (r) {
56402 LOG_ERROR("clog_resume: Failed to create cluster CPG");
56403 return r;
56404 }
56405
56406 /* move log to official list */
56407 dm_list_del(&lc->list);
56408 dm_list_add(&log_list, &lc->list);
56409 }
56410
56411 return 0;
56412}
56413
56414/*
56415 * clog_get_region_size
56416 * @rq
56417 *
56418 * Since this value doesn't change, the kernel
56419 * should not need to talk to server to get this
56420 * The function is here for completness
56421 *
56422 * Returns: 0 on success, -EXXX on failure
56423 */
56424static int clog_get_region_size(struct dm_ulog_request *rq)
56425{
56426 uint64_t *rtn = (uint64_t *)rq->data;
56427 struct log_c *lc = get_log(rq->uuid, rq->luid);
56428
56429 if (!lc && !(lc = get_pending_log(rq->uuid, rq->luid)))
56430 return -EINVAL;
56431
56432 *rtn = lc->region_size;
56433 rq->data_size = sizeof(*rtn);
56434
56435 return 0;
56436}
56437
56438/*
56439 * clog_is_clean
56440 * @rq
56441 *
56442 * Returns: 1 if clean, 0 otherwise
56443 */
56444static int clog_is_clean(struct dm_ulog_request *rq)
56445{
56446 int64_t *rtn = (int64_t *)rq->data;
56447 uint64_t *region = (uint64_t *)rq->data;
56448 struct log_c *lc = get_log(rq->uuid, rq->luid);
56449
56450 if (!lc)
56451 return -EINVAL;
56452
56453 *rtn = log_test_bit(lc->clean_bits, *region);
56454 rq->data_size = sizeof(*rtn);
56455
56456 return 0;
56457}
56458
56459/*
56460 * clog_in_sync
56461 * @rq
56462 *
56463 * We ignore any request for non-block. That
56464 * should be handled elsewhere. (If the request
56465 * has come this far, it has already blocked.)
56466 *
56467 * Returns: 1 if in-sync, 0 otherwise
56468 */
56469static int clog_in_sync(struct dm_ulog_request *rq)
56470{
56471 int64_t *rtn = (int64_t *)rq->data;
56472 uint64_t *region_p = (uint64_t *)rq->data;
56473 uint64_t region = *region_p;
56474 struct log_c *lc = get_log(rq->uuid, rq->luid);
56475
56476 if (!lc)
56477 return -EINVAL;
56478
56479 if (region > lc->region_count)
56480 return -EINVAL;
56481
56482 *rtn = log_test_bit(lc->sync_bits, region);
56483
56484 /*
56485 * If the mirror was successfully recovered, we want to always
56486 * force every machine to write to all devices - otherwise,
56487 * corruption will occur. Here's how:
56488 * Node1 suffers a failure and marks a region out-of-sync
56489 * Node2 attempts a write, gets by is_remote_recovering,
56490 * and queries the sync status of the region - finding
56491 * it out-of-sync.
56492 * Node2 thinks the write should be a nosync write, but it
56493 * hasn't suffered the drive failure that Node1 has yet.
56494 * It then issues a generic_make_request directly to
56495 * the primary image only - which is exactly the device
56496 * that has suffered the failure.
56497 * Node2 suffers a lost write - which completely bypasses the
56498 * mirror layer because it had gone through generic_m_r.
56499 * The file system will likely explode at this point due to
56500 * I/O errors. If it wasn't the primary that failed, it is
56501 * easily possible in this case to issue writes to just one
56502 * of the remaining images - also leaving the mirror inconsistent.
56503 *
56504 * We let in_sync() return 1 in a cluster regardless of what is
56505 * in the bitmap once recovery has successfully completed on a
56506 * mirror. This ensures the mirroring code will continue to
56507 * attempt to write to all mirror images. The worst that can
56508 * happen for reads is that additional read attempts may be
56509 * taken.
56510 *
56511 * Futher investigation may be required to determine if there are
56512 * similar possible outcomes when the mirror is in the process of
56513 * recovering. In that case, lc->in_sync would not have been set
56514 * yet.
56515 */
56516 if (!*rtn && lc->in_sync)
56517 *rtn = 1;
56518
56519 if (*rtn)
56520 LOG_DBG("[%s] Region is in-sync: %llu",
56521 SHORT_UUID(lc->uuid), (unsigned long long)region);
56522 else
56523 LOG_DBG("[%s] Region is not in-sync: %llu",
56524 SHORT_UUID(lc->uuid), (unsigned long long)region);
56525
56526 rq->data_size = sizeof(*rtn);
56527
56528 return 0;
56529}
56530
56531/*
56532 * clog_flush
56533 * @rq
56534 *
56535 */
56536static int clog_flush(struct dm_ulog_request *rq, int server)
56537{
56538 int r = 0;
56539 struct log_c *lc = get_log(rq->uuid, rq->luid);
56540
56541 if (!lc)
56542 return -EINVAL;
56543
56544 if (!lc->touched)
56545 return 0;
56546
56547 /*
56548 * Do the actual flushing of the log only
56549 * if we are the server.
56550 */
56551 if (server && (lc->disk_fd >= 0)) {
56552 r = rq->error = write_log(lc);
56553 if (r)
56554 LOG_ERROR("[%s] Error writing to disk log",
56555 SHORT_UUID(lc->uuid));
56556 else
56557 LOG_DBG("[%s] Disk log written", SHORT_UUID(lc->uuid));
56558 }
56559
56560 lc->touched = 0;
56561
56562 return r;
56563
56564}
56565
56566/*
56567 * mark_region
56568 * @lc
56569 * @region
56570 * @who
56571 *
56572 * Put a mark region request in the tree for tracking.
56573 *
56574 * Returns: 0 on success, -EXXX on error
56575 */
56576static int mark_region(struct log_c *lc, uint64_t region, uint32_t who)
56577{
56578 int found = 0;
56579 struct mark_entry *m;
56580
56581 dm_list_iterate_items(m, &lc->mark_list)
56582 if (m->region == region) {
56583 found = 1;
56584 if (m->nodeid == who)
56585 return 0;
56586 }
56587
56588 if (!found)
56589 log_clear_bit(lc, lc->clean_bits, region);
56590
56591 /*
56592 * Save allocation until here - if there is a failure,
56593 * at least we have cleared the bit.
56594 */
56595 m = malloc(sizeof(*m));
56596 if (!m) {
56597 LOG_ERROR("Unable to allocate space for mark_entry: %llu/%u",
56598 (unsigned long long)region, who);
56599 return -ENOMEM;
56600 }
56601
56602 m->nodeid = who;
56603 m->region = region;
56604 dm_list_add(&lc->mark_list, &m->list);
56605
56606 return 0;
56607}
56608
56609/*
56610 * clog_mark_region
56611 * @rq
56612 *
56613 * rq may contain more than one mark request. We
56614 * can determine the number from the 'data_size' field.
56615 *
56616 * Returns: 0 on success, -EXXX on failure
56617 */
56618static int clog_mark_region(struct dm_ulog_request *rq, uint32_t originator)
56619{
56620 int r;
56621 int count;
56622 uint64_t *region;
56623 struct log_c *lc = get_log(rq->uuid, rq->luid);
56624
56625 if (!lc)
56626 return -EINVAL;
56627
56628 if (rq->data_size % sizeof(uint64_t)) {
56629 LOG_ERROR("Bad data size given for mark_region request");
56630 return -EINVAL;
56631 }
56632
56633 count = rq->data_size / sizeof(uint64_t);
56634 region = (uint64_t *)&rq->data;
56635
56636 for (; count > 0; count--, region++) {
56637 r = mark_region(lc, *region, originator);
56638 if (r)
56639 return r;
56640 }
56641
56642 rq->data_size = 0;
56643
56644 return 0;
56645}
56646
56647static int clear_region(struct log_c *lc, uint64_t region, uint32_t who)
56648{
56649 int other_matches = 0;
56650 struct mark_entry *m, *n;
56651
56652 dm_list_iterate_items_safe(m, n, &lc->mark_list)
56653 if (m->region == region) {
56654 if (m->nodeid == who) {
56655 dm_list_del(&m->list);
56656 free(m);
56657 } else
56658 other_matches = 1;
56659 }
56660
56661 /*
56662 * Clear region if:
56663 * 1) It is in-sync
56664 * 2) There are no other machines that have it marked
56665 */
56666 if (!other_matches && log_test_bit(lc->sync_bits, region))
56667 log_set_bit(lc, lc->clean_bits, region);
56668
56669 return 0;
56670}
56671
56672/*
56673 * clog_clear_region
56674 * @rq
56675 *
56676 * rq may contain more than one clear request. We
56677 * can determine the number from the 'data_size' field.
56678 *
56679 * Returns: 0 on success, -EXXX on failure
56680 */
56681static int clog_clear_region(struct dm_ulog_request *rq, uint32_t originator)
56682{
56683 int r;
56684 int count;
56685 uint64_t *region;
56686 struct log_c *lc = get_log(rq->uuid, rq->luid);
56687
56688 if (!lc)
56689 return -EINVAL;
56690
56691 if (rq->data_size % sizeof(uint64_t)) {
56692 LOG_ERROR("Bad data size given for clear_region request");
56693 return -EINVAL;
56694 }
56695
56696 count = rq->data_size / sizeof(uint64_t);
56697 region = (uint64_t *)&rq->data;
56698
56699 for (; count > 0; count--, region++) {
56700 r = clear_region(lc, *region, originator);
56701 if (r)
56702 return r;
56703 }
56704
56705 rq->data_size = 0;
56706
56707 return 0;
56708}
56709
56710/*
56711 * clog_get_resync_work
56712 * @rq
56713 *
56714 */
56715static int clog_get_resync_work(struct dm_ulog_request *rq, uint32_t originator)
56716{
56717 struct {
56718 int64_t i;
56719 uint64_t r;
56720 } *pkg = (void *)rq->data;
56721 struct log_c *lc = get_log(rq->uuid, rq->luid);
56722
56723 if (!lc)
56724 return -EINVAL;
56725
56726 rq->data_size = sizeof(*pkg);
56727 pkg->i = 0;
56728
56729 if (lc->sync_search >= lc->region_count) {
56730 /*
56731 * FIXME: handle intermittent errors during recovery
56732 * by resetting sync_search... but not to many times.
56733 */
56734 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56735 "Recovery finished",
56736 rq->seq, SHORT_UUID(lc->uuid), originator);
56737 return 0;
56738 }
56739
56740 if (lc->recovering_region != (uint64_t)-1) {
56741 if (lc->recoverer == originator) {
56742 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56743 "Re-requesting work (%llu)",
56744 rq->seq, SHORT_UUID(lc->uuid), originator,
56745 (unsigned long long)lc->recovering_region);
56746 pkg->r = lc->recovering_region;
56747 pkg->i = 1;
56748 LOG_COND(log_resend_requests, "***** RE-REQUEST *****");
56749 } else {
56750 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56751 "Someone already recovering (%llu)",
56752 rq->seq, SHORT_UUID(lc->uuid), originator,
56753 (unsigned long long)lc->recovering_region);
56754 }
56755
56756 return 0;
56757 }
56758
56759 while (lc->recovery_request_list) {
56760 struct recovery_request *del;
56761
56762 del = lc->recovery_request_list;
56763 lc->recovery_request_list = del->next;
56764
56765 pkg->r = del->region;
56766 free(del);
56767
56768 if (!log_test_bit(lc->sync_bits, pkg->r)) {
56769 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56770 "Assigning priority resync work (%llu)",
56771 rq->seq, SHORT_UUID(lc->uuid), originator,
56772 (unsigned long long)pkg->r);
56773 pkg->i = 1;
56774 lc->recovering_region = pkg->r;
56775 lc->recoverer = originator;
56776 return 0;
56777 }
56778 }
56779
56780 pkg->r = find_next_zero_bit(lc->sync_bits, lc->sync_search);
56781
56782 if (pkg->r >= lc->region_count) {
56783 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56784 "Resync work complete.",
56785 rq->seq, SHORT_UUID(lc->uuid), originator);
56786 lc->sync_search = lc->region_count + 1;
56787 return 0;
56788 }
56789
56790 lc->sync_search = pkg->r + 1;
56791
56792 LOG_SPRINT(lc, "GET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56793 "Assigning resync work (%llu)",
56794 rq->seq, SHORT_UUID(lc->uuid), originator,
56795 (unsigned long long)pkg->r);
56796 pkg->i = 1;
56797 lc->recovering_region = pkg->r;
56798 lc->recoverer = originator;
56799
56800 return 0;
56801}
56802
56803/*
56804 * clog_set_region_sync
56805 * @rq
56806 */
56807static int clog_set_region_sync(struct dm_ulog_request *rq, uint32_t originator)
56808{
56809 struct {
56810 uint64_t region;
56811 int64_t in_sync;
56812 } *pkg = (void *)rq->data;
56813 struct log_c *lc = get_log(rq->uuid, rq->luid);
56814
56815 if (!lc)
56816 return -EINVAL;
56817
56818 lc->recovering_region = (uint64_t)-1;
56819
56820 if (pkg->in_sync) {
56821 if (log_test_bit(lc->sync_bits, pkg->region)) {
56822 LOG_SPRINT(lc, "SET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56823 "Region already set (%llu)",
56824 rq->seq, SHORT_UUID(lc->uuid), originator,
56825 (unsigned long long)pkg->region);
56826 } else {
56827 log_set_bit(lc, lc->sync_bits, pkg->region);
56828 lc->sync_count++;
56829
56830 /* The rest of this section is all for debugging */
56831 LOG_SPRINT(lc, "SET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56832 "Setting region (%llu)",
56833 rq->seq, SHORT_UUID(lc->uuid), originator,
56834 (unsigned long long)pkg->region);
56835 if (pkg->region == lc->skip_bit_warning)
56836 lc->skip_bit_warning = lc->region_count;
56837
56838 if (pkg->region > (lc->skip_bit_warning + 5)) {
56839 LOG_SPRINT(lc, "*** Region #%llu skipped during recovery ***",
56840 (unsigned long long)lc->skip_bit_warning);
56841 lc->skip_bit_warning = lc->region_count;
56842#ifdef DEBUG
56843 kill(getpid(), SIGUSR1);
56844#endif
56845 }
56846
56847 if (!log_test_bit(lc->sync_bits,
56848 (pkg->region) ? pkg->region - 1 : 0)) {
56849 LOG_SPRINT(lc, "*** Previous bit not set ***");
56850 lc->skip_bit_warning = (pkg->region) ?
56851 pkg->region - 1 : 0;
56852 }
56853 }
56854 } else if (log_test_bit(lc->sync_bits, pkg->region)) {
56855 lc->sync_count--;
56856 log_clear_bit(lc, lc->sync_bits, pkg->region);
56857 LOG_SPRINT(lc, "SET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56858 "Unsetting region (%llu)",
56859 rq->seq, SHORT_UUID(lc->uuid), originator,
56860 (unsigned long long)pkg->region);
56861 }
56862
56863 if (lc->sync_count != count_bits32(lc->sync_bits)) {
56864 unsigned long long reset = count_bits32(lc->sync_bits);
56865
56866 LOG_SPRINT(lc, "SET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56867 "sync_count(%llu) != bitmap count(%llu)",
56868 rq->seq, SHORT_UUID(lc->uuid), originator,
56869 (unsigned long long)lc->sync_count, reset);
56870#ifdef DEBUG
56871 kill(getpid(), SIGUSR1);
56872#endif
56873 lc->sync_count = reset;
56874 }
56875
56876 if (lc->sync_count > lc->region_count)
56877 LOG_SPRINT(lc, "SET - SEQ#=%u, UUID=%s, nodeid = %u:: "
56878 "(lc->sync_count > lc->region_count) - this is bad",
56879 rq->seq, SHORT_UUID(lc->uuid), originator);
56880
56881 if (lc->sync_count == lc->region_count)
56882 lc->in_sync = 1;
56883
56884 rq->data_size = 0;
56885 return 0;
56886}
56887
56888/*
56889 * clog_get_sync_count
56890 * @rq
56891 */
56892static int clog_get_sync_count(struct dm_ulog_request *rq, uint32_t originator)
56893{
56894 uint64_t *sync_count = (uint64_t *)rq->data;
56895 struct log_c *lc = get_log(rq->uuid, rq->luid);
56896
56897 /*
56898 * FIXME: Mirror requires us to be able to ask for
56899 * the sync count while pending... but I don't like
56900 * it because other machines may not be suspended and
56901 * the stored value may not be accurate.
56902 */
56903 if (!lc)
56904 lc = get_pending_log(rq->uuid, rq->luid);
56905
56906 if (!lc)
56907 return -EINVAL;
56908
56909 *sync_count = lc->sync_count;
56910
56911 rq->data_size = sizeof(*sync_count);
56912
56913 if (lc->sync_count != count_bits32(lc->sync_bits)) {
56914 unsigned long long reset = count_bits32(lc->sync_bits);
56915
56916 LOG_SPRINT(lc, "get_sync_count - SEQ#=%u, UUID=%s, nodeid = %u:: "
56917 "sync_count(%llu) != bitmap count(%llu)",
56918 rq->seq, SHORT_UUID(lc->uuid), originator,
56919 (unsigned long long)lc->sync_count, reset);
56920#ifdef DEBUG
56921 kill(getpid(), SIGUSR1);
56922#endif
56923 lc->sync_count = reset;
56924 }
56925
56926 return 0;
56927}
56928
56929static int core_status_info(struct log_c *lc __attribute__((unused)), struct dm_ulog_request *rq)
56930{
56931 int r;
56932 char *data = (char *)rq->data;
56933
56934 r = sprintf(data, "1 clustered-core");
56935 if (r < 0)
56936 return r;
56937
56938 rq->data_size = r;
56939
56940 return 0;
56941}
56942
56943static int disk_status_info(struct log_c *lc, struct dm_ulog_request *rq)
56944{
56945 int r;
56946 char *data = (char *)rq->data;
56947 struct stat statbuf;
56948
56949 if (fstat(lc->disk_fd, &statbuf)) {
56950 rq->error = -errno;
56951 return -errno;
56952 }
56953
56954 r = sprintf(data, "3 clustered-disk %d:%d %c",
56955 major(statbuf.st_rdev), minor(statbuf.st_rdev),
56956 (lc->log_dev_failed) ? 'D' : 'A');
56957 if (r < 0)
56958 return r;
56959
56960 rq->data_size = r;
56961
56962 return 0;
56963}
56964
56965/*
56966 * clog_status_info
56967 * @rq
56968 *
56969 */
56970static int clog_status_info(struct dm_ulog_request *rq)
56971{
56972 int r;
56973 struct log_c *lc = get_log(rq->uuid, rq->luid);
56974
56975 if (!lc)
56976 lc = get_pending_log(rq->uuid, rq->luid);
56977
56978 if (!lc)
56979 return -EINVAL;
56980
56981 if (lc->disk_fd == -1)
56982 r = core_status_info(lc, rq);
56983 else
56984 r = disk_status_info(lc, rq);
56985
56986 return r;
56987}
56988
56989static int core_status_table(struct log_c *lc, struct dm_ulog_request *rq)
56990{
56991 int r;
56992 char *data = (char *)rq->data;
56993
56994 r = sprintf(data, "clustered-core %u %s%s ",
56995 lc->region_size,
56996 (lc->sync == DEFAULTSYNC) ? "" :
56997 (lc->sync == NOSYNC) ? "nosync " : "sync ",
56998 (lc->block_on_error) ? "block_on_error" : "");
56999 if (r < 0)
57000 return r;
57001
57002 rq->data_size = r;
57003 return 0;
57004}
57005
57006static int disk_status_table(struct log_c *lc, struct dm_ulog_request *rq)
57007{
57008 int r;
57009 char *data = (char *)rq->data;
57010 struct stat statbuf;
57011
57012 if (fstat(lc->disk_fd, &statbuf)) {
57013 rq->error = -errno;
57014 return -errno;
57015 }
57016
57017 r = sprintf(data, "clustered-disk %d:%d %u %s%s ",
57018 major(statbuf.st_rdev), minor(statbuf.st_rdev),
57019 lc->region_size,
57020 (lc->sync == DEFAULTSYNC) ? "" :
57021 (lc->sync == NOSYNC) ? "nosync " : "sync ",
57022 (lc->block_on_error) ? "block_on_error" : "");
57023 if (r < 0)
57024 return r;
57025
57026 rq->data_size = r;
57027 return 0;
57028}
57029
57030/*
57031 * clog_status_table
57032 * @rq
57033 *
57034 */
57035static int clog_status_table(struct dm_ulog_request *rq)
57036{
57037 int r;
57038 struct log_c *lc = get_log(rq->uuid, rq->luid);
57039
57040 if (!lc)
57041 lc = get_pending_log(rq->uuid, rq->luid);
57042
57043 if (!lc)
57044 return -EINVAL;
57045
57046 if (lc->disk_fd == -1)
57047 r = core_status_table(lc, rq);
57048 else
57049 r = disk_status_table(lc, rq);
57050
57051 return r;
57052}
57053
57054/*
57055 * clog_is_remote_recovering
57056 * @rq
57057 *
57058 */
57059static int clog_is_remote_recovering(struct dm_ulog_request *rq)
57060{
57061 uint64_t *region_p = (uint64_t *)rq->data;
57062 uint64_t region = *region_p;
57063 struct {
57064 int64_t is_recovering;
57065 uint64_t in_sync_hint;
57066 } *pkg = (void *)rq->data;
57067 struct log_c *lc = get_log(rq->uuid, rq->luid);
57068
57069 if (!lc)
57070 return -EINVAL;
57071
57072 if (region > lc->region_count)
57073 return -EINVAL;
57074
57075 if (lc->recovery_halted) {
57076 LOG_DBG("[%s] Recovery halted... [not remote recovering]: %llu",
57077 SHORT_UUID(lc->uuid), (unsigned long long)region);
57078 pkg->is_recovering = 0;
57079 pkg->in_sync_hint = lc->region_count; /* none are recovering */
57080 } else {
57081 pkg->is_recovering = !log_test_bit(lc->sync_bits, region);
57082
57083 /*
57084 * Remember, 'lc->sync_search' is 1 plus the region
57085 * currently being recovered. So, we must take off 1
57086 * to account for that; but only if 'sync_search > 1'.
57087 */
57088 pkg->in_sync_hint = lc->sync_search ? (lc->sync_search - 1) : 0;
57089 LOG_DBG("[%s] Region is %s: %llu",
57090 SHORT_UUID(lc->uuid),
57091 (region == lc->recovering_region) ?
57092 "currently remote recovering" :
57093 (pkg->is_recovering) ? "pending remote recovery" :
57094 "not remote recovering", (unsigned long long)region);
57095 }
57096
57097 if (pkg->is_recovering &&
57098 (region != lc->recovering_region)) {
57099 struct recovery_request *rr;
57100
57101 /* Already in the list? */
57102 for (rr = lc->recovery_request_list; rr; rr = rr->next)
57103 if (rr->region == region)
57104 goto out;
57105
57106 /* Failure to allocated simply means we can't prioritize it */
57107 rr = malloc(sizeof(*rr));
57108 if (!rr)
57109 goto out;
57110
57111 LOG_DBG("[%s] Adding region to priority list: %llu",
57112 SHORT_UUID(lc->uuid), (unsigned long long)region);
57113 rr->region = region;
57114 rr->next = lc->recovery_request_list;
57115 lc->recovery_request_list = rr;
57116 }
57117
57118out:
57119
57120 rq->data_size = sizeof(*pkg);
57121
57122 return 0;
57123}
57124
57125
57126/*
57127 * do_request
57128 * @rq: the request
57129 * @server: is this request performed by the server
57130 *
57131 * An inability to perform this function will return an error
57132 * from this function. However, an inability to successfully
57133 * perform the request will fill in the 'rq->error' field.
57134 *
57135 * 'rq' (or more correctly, rq->u_rq.data) should be of sufficient
57136 * size to hold any returning data. Currently, local.c uses 2kiB
57137 * to hold 'rq' - leaving ~1.5kiB for return data... more than
57138 * enough for all the implemented functions here.
57139 *
57140 * Returns: 0 on success, -EXXX on error
57141 */
57142int do_request(struct clog_request *rq, int server)
57143{
57144 int r;
57145
57146 if (!rq)
57147 return 0;
57148
57149 if (rq->u_rq.error)
57150 LOG_DBG("Programmer error: rq struct has error set");
57151
57152 switch (rq->u_rq.request_type) {
57153 case DM_ULOG_CTR:
57154 r = clog_ctr(&rq->u_rq);
57155 break;
57156 case DM_ULOG_DTR:
57157 r = clog_dtr(&rq->u_rq);
57158 break;
57159 case DM_ULOG_PRESUSPEND:
57160 r = clog_presuspend(&rq->u_rq);
57161 break;
57162 case DM_ULOG_POSTSUSPEND:
57163 r = clog_postsuspend(&rq->u_rq);
57164 break;
57165 case DM_ULOG_RESUME:
57166 r = clog_resume(&rq->u_rq);
57167 break;
57168 case DM_ULOG_GET_REGION_SIZE:
57169 r = clog_get_region_size(&rq->u_rq);
57170 break;
57171 case DM_ULOG_IS_CLEAN:
57172 r = clog_is_clean(&rq->u_rq);
57173 break;
57174 case DM_ULOG_IN_SYNC:
57175 r = clog_in_sync(&rq->u_rq);
57176 break;
57177 case DM_ULOG_FLUSH:
57178 r = clog_flush(&rq->u_rq, server);
57179 break;
57180 case DM_ULOG_MARK_REGION:
57181 r = clog_mark_region(&rq->u_rq, rq->originator);
57182 break;
57183 case DM_ULOG_CLEAR_REGION:
57184 r = clog_clear_region(&rq->u_rq, rq->originator);
57185 break;
57186 case DM_ULOG_GET_RESYNC_WORK:
57187 r = clog_get_resync_work(&rq->u_rq, rq->originator);
57188 break;
57189 case DM_ULOG_SET_REGION_SYNC:
57190 r = clog_set_region_sync(&rq->u_rq, rq->originator);
57191 break;
57192 case DM_ULOG_GET_SYNC_COUNT:
57193 r = clog_get_sync_count(&rq->u_rq, rq->originator);
57194 break;
57195 case DM_ULOG_STATUS_INFO:
57196 r = clog_status_info(&rq->u_rq);
57197 break;
57198 case DM_ULOG_STATUS_TABLE:
57199 r = clog_status_table(&rq->u_rq);
57200 break;
57201 case DM_ULOG_IS_REMOTE_RECOVERING:
57202 r = clog_is_remote_recovering(&rq->u_rq);
57203 break;
57204 default:
57205 LOG_ERROR("Unknown request");
57206 r = rq->u_rq.error = -EINVAL;
57207 break;
57208 }
57209
57210 if (r && !rq->u_rq.error)
57211 rq->u_rq.error = r;
57212 else if (r != rq->u_rq.error)
57213 LOG_DBG("Warning: error from function != rq->u_rq.error");
57214
57215 if (rq->u_rq.error && rq->u_rq.data_size) {
57216 /* Make sure I'm handling errors correctly above */
57217 LOG_DBG("Programmer error: rq->u_rq.error && rq->u_rq.data_size");
57218 rq->u_rq.data_size = 0;
57219 }
57220
57221 return 0;
57222}
57223
57224static void print_bits(dm_bitset_t bs, int print)
57225{
57226 int i, size;
57227 char outbuf[128] = { 0 };
57228 unsigned char *buf = (unsigned char *)(bs + 1);
57229
57230 size = (*bs % 8) ? 1 : 0;
57231 size += (*bs / 8);
57232
57233 for (i = 0; i < size; i++) {
57234 if (!(i % 16)) {
57235 if (outbuf[0] != '\0') {
57236 if (print)
57237 LOG_PRINT("%s", outbuf);
57238 else
57239 LOG_DBG("%s", outbuf);
57240 }
57241 memset(outbuf, 0, sizeof(outbuf));
57242 sprintf(outbuf, "[%3d - %3d]", i, i+15);
57243 }
57244 sprintf(outbuf + strlen(outbuf), " %.2X", (unsigned char)buf[i]);
57245 }
57246 if (outbuf[0] != '\0') {
57247 if (print)
57248 LOG_PRINT("%s", outbuf);
57249 else
57250 LOG_DBG("%s", outbuf);
57251 }
57252}
57253
57254/* int store_bits(const char *uuid, const char *which, char **buf)*/
57255int push_state(const char *uuid, uint64_t luid,
57256 const char *which, char **buf, uint32_t debug_who)
57257{
57258 int bitset_size;
57259 struct log_c *lc;
57260
57261 if (*buf)
57262 LOG_ERROR("store_bits: *buf != NULL");
57263
57264 lc = get_log(uuid, luid);
57265 if (!lc) {
57266 LOG_ERROR("store_bits: No log found for %s", uuid);
57267 return -EINVAL;
57268 }
57269
57270 if (!strcmp(which, "recovering_region")) {
57271 *buf = malloc(64); /* easily handles the 2 written numbers */
57272 if (!*buf)
57273 return -ENOMEM;
57274 sprintf(*buf, "%llu %u", (unsigned long long)lc->recovering_region,
57275 lc->recoverer);
57276
57277 LOG_SPRINT(lc, "CKPT SEND - SEQ#=X, UUID=%s, nodeid = %u:: "
57278 "recovering_region=%llu, recoverer=%u, sync_count=%llu",
57279 SHORT_UUID(lc->uuid), debug_who,
57280 (unsigned long long)lc->recovering_region,
57281 lc->recoverer,
57282 (unsigned long long)count_bits32(lc->sync_bits));
57283 return 64;
57284 }
57285
57286 /* Size in 'int's */
57287 bitset_size = (*(lc->clean_bits) / DM_BITS_PER_INT) + 1;
57288
57289 /* Size in bytes */
57290 bitset_size *= 4;
57291
57292 *buf = malloc(bitset_size);
57293
57294 if (!*buf) {
57295 LOG_ERROR("store_bits: Unable to allocate memory");
57296 return -ENOMEM;
57297 }
57298
57299 if (!strncmp(which, "sync_bits", 9)) {
57300 memcpy(*buf, lc->sync_bits + 1, bitset_size);
57301
57302 LOG_DBG("[%s] storing sync_bits (sync_count = %llu):",
57303 SHORT_UUID(uuid), (unsigned long long)
57304 count_bits32(lc->sync_bits));
57305
57306 print_bits(lc->sync_bits, 0);
57307 } else if (!strncmp(which, "clean_bits", 9)) {
57308 memcpy(*buf, lc->clean_bits + 1, bitset_size);
57309
57310 LOG_DBG("[%s] storing clean_bits:", SHORT_UUID(lc->uuid));
57311
57312 print_bits(lc->clean_bits, 0);
57313 }
57314
57315 return bitset_size;
57316}
57317
57318/*int load_bits(const char *uuid, const char *which, char *buf, int size)*/
57319int pull_state(const char *uuid, uint64_t luid,
57320 const char *which, char *buf, int size)
57321{
57322 int bitset_size;
57323 struct log_c *lc;
57324
57325 if (!buf) {
57326 LOG_ERROR("pull_state: buf == NULL");
57327 return -EINVAL;
57328 }
57329
57330 lc = get_log(uuid, luid);
57331 if (!lc) {
57332 LOG_ERROR("pull_state: No log found for %s", uuid);
57333 return -EINVAL;
57334 }
57335
57336 if (!strncmp(which, "recovering_region", 17)) {
57337 if (sscanf(buf, "%llu %u", (unsigned long long *)&lc->recovering_region,
57338 &lc->recoverer) != 2) {
57339 LOG_ERROR("cannot parse recovering region from: %s", buf);
57340 return -EINVAL;
57341 }
57342 LOG_SPRINT(lc, "CKPT INIT - SEQ#=X, UUID=%s, nodeid = X:: "
57343 "recovering_region=%llu, recoverer=%u",
57344 SHORT_UUID(lc->uuid),
57345 (unsigned long long)lc->recovering_region, lc->recoverer);
57346 return 0;
57347 }
57348
57349 /* Size in 'int's */
57350 bitset_size = (*(lc->clean_bits) /DM_BITS_PER_INT) + 1;
57351
57352 /* Size in bytes */
57353 bitset_size *= 4;
57354
57355 if (bitset_size != size) {
57356 LOG_ERROR("pull_state(%s): bad bitset_size (%d vs %d)",
57357 which, size, bitset_size);
57358 return -EINVAL;
57359 }
57360
57361 if (!strncmp(which, "sync_bits", 9)) {
57362 lc->resume_override += 1;
57363 memcpy(lc->sync_bits + 1, buf, bitset_size);
57364
57365 LOG_DBG("[%s] loading sync_bits (sync_count = %llu):",
57366 SHORT_UUID(lc->uuid),(unsigned long long)
57367 count_bits32(lc->sync_bits));
57368
57369 print_bits(lc->sync_bits, 0);
57370 } else if (!strncmp(which, "clean_bits", 9)) {
57371 lc->resume_override += 2;
57372 memcpy(lc->clean_bits + 1, buf, bitset_size);
57373
57374 LOG_DBG("[%s] loading clean_bits:", SHORT_UUID(lc->uuid));
57375
57376 print_bits(lc->clean_bits, 0);
57377 }
57378
57379 return 0;
57380}
57381
57382int log_get_state(struct dm_ulog_request *rq)
57383{
57384 struct log_c *lc;
57385
57386 lc = get_log(rq->uuid, rq->luid);
57387 if (!lc)
57388 /* FIXME Callers are ignoring this */
57389 return -EINVAL;
57390
57391 return (int)lc->state;
57392}
57393
57394/*
57395 * log_status
57396 *
57397 * Returns: 1 if logs are still present, 0 otherwise
57398 */
57399int log_status(void)
57400{
57401 if (!dm_list_empty(&log_list) || !dm_list_empty(&log_pending_list))
57402 return 1;
57403
57404 return 0;
57405}
57406
57407void log_debug(void)
57408{
57409 struct log_c *lc;
57410 uint64_t r;
57411 int i;
57412
57413 LOG_ERROR("");
57414 LOG_ERROR("LOG COMPONENT DEBUGGING::");
57415 LOG_ERROR("Official log list:");
57416 LOG_ERROR("Pending log list:");
57417 dm_list_iterate_items(lc, &log_pending_list) {
57418 LOG_ERROR("%s", lc->uuid);
57419 LOG_ERROR("sync_bits:");
57420 print_bits(lc->sync_bits, 1);
57421 LOG_ERROR("clean_bits:");
57422 print_bits(lc->clean_bits, 1);
57423 }
57424
57425 dm_list_iterate_items(lc, &log_list) {
57426 LOG_ERROR("%s", lc->uuid);
57427 LOG_ERROR(" recoverer : %" PRIu32, lc->recoverer);
57428 LOG_ERROR(" recovering_region: %" PRIu64, lc->recovering_region);
57429 LOG_ERROR(" recovery_halted : %s", (lc->recovery_halted) ?
57430 "YES" : "NO");
57431 LOG_ERROR("sync_bits:");
57432 print_bits(lc->sync_bits, 1);
57433 LOG_ERROR("clean_bits:");
57434 print_bits(lc->clean_bits, 1);
57435
57436 LOG_ERROR("Validating %s::", SHORT_UUID(lc->uuid));
57437 r = find_next_zero_bit(lc->sync_bits, 0);
57438 LOG_ERROR(" lc->region_count = %" PRIu32, lc->region_count);
57439 LOG_ERROR(" lc->sync_count = %" PRIu64, lc->sync_count);
57440 LOG_ERROR(" next zero bit = %" PRIu64, r);
57441 if ((r > lc->region_count) ||
57442 ((r == lc->region_count) && (lc->sync_count > lc->region_count))) {
57443 LOG_ERROR("ADJUSTING SYNC_COUNT");
57444 lc->sync_count = lc->region_count;
57445 }
57446
57447 LOG_ERROR("Resync request history:");
57448 for (i = 0; i < RESYNC_HISTORY; i++) {
57449 lc->idx++;
57450 lc->idx = lc->idx % RESYNC_HISTORY;
57451 if (lc->resync_history[lc->idx][0] == '\0')
57452 continue;
57453 LOG_ERROR("%d:%d) %s", i, lc->idx,
57454 lc->resync_history[lc->idx]);
57455 }
57456 }
57457}
57458\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020326\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-protocol.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003246\013062740170\0024174\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
57459 * Copyright (C) 2015 Red Hat, Inc.
57460 *
57461 * This file is part of LVM2.
57462 *
57463 * This copyrighted material is made available to anyone wishing to use,
57464 * modify, copy, or redistribute it subject to the terms and conditions
57465 * of the GNU Lesser General Public License v.2.1.
57466 *
57467 * You should have received a copy of the GNU Lesser General Public License
57468 * along with this program; if not, write to the Free Software Foundation,
57469 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
57470 */
57471
57472#ifndef _LVM_LVMPOLLD_PROTOCOL_H
57473#define _LVM_LVMPOLLD_PROTOCOL_H
57474
57475#include "polling_ops.h"
57476
57477#define LVMPOLLD_PROTOCOL "lvmpolld"
57478#define LVMPOLLD_PROTOCOL_VERSION 1
57479
57480#define LVMPD_REQ_CONVERT CONVERT_POLL
57481#define LVMPD_REQ_DUMP "dump"
57482#define LVMPD_REQ_MERGE MERGE_POLL
57483#define LVMPD_REQ_MERGE_THIN MERGE_THIN_POLL
57484#define LVMPD_REQ_PROGRESS "progress_info"
57485#define LVMPD_REQ_PVMOVE PVMOVE_POLL
57486
57487#define LVMPD_PARM_ABORT "abort"
57488#define LVMPD_PARM_HANDLE_MISSING_PVS "handle_missing_pvs"
57489#define LVMPD_PARM_INTERVAL "interval"
57490#define LVMPD_PARM_LVID "lvid"
57491#define LVMPD_PARM_LVNAME "lvname"
57492#define LVMPD_PARM_SYSDIR "sysdir"
57493#define LVMPD_PARM_VALUE "value" /* either retcode or signal value */
57494#define LVMPD_PARM_VGNAME "vgname"
57495
57496#define LVMPD_RESP_FAILED "failed"
57497#define LVMPD_RESP_FINISHED "finished"
57498#define LVMPD_RESP_IN_PROGRESS "in_progress"
57499#define LVMPD_RESP_EINVAL "invalid"
57500#define LVMPD_RESP_NOT_FOUND "not_found"
57501#define LVMPD_RESP_OK "OK"
57502
57503#define LVMPD_REAS_RETCODE "retcode" /* lvm cmd ret code */
57504#define LVMPD_REAS_SIGNAL "signal" /* lvm cmd terminating singal */
57505
57506#define LVMPD_RET_DUP_FAILED 100
57507#define LVMPD_RET_EXC_FAILED 101
57508
57509#endif /* _LVM_LVMPOLLD_PROTOCOL_H */
57510\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-cmd-utils.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001543\013062740170\0024232\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
57511 * Copyright (C) 2015 Red Hat, Inc.
57512 *
57513 * This file is part of LVM2.
57514 *
57515 * This copyrighted material is made available to anyone wishing to use,
57516 * modify, copy, or redistribute it subject to the terms and conditions
57517 * of the GNU Lesser General Public License v.2.1.
57518 *
57519 * You should have received a copy of the GNU Lesser General Public License
57520 * along with this program; if not, write to the Free Software Foundation,
57521 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
57522 */
57523
57524#ifndef _LVM_LVMPOLLD_CMD_UTILS_H
57525#define _LVM_LVMPOLLD_CMD_UTILS_H
57526
57527#include "lvmpolld-data-utils.h"
57528
57529const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, unsigned abort, unsigned handle_missing_pvs);
57530const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv);
57531
57532const char *polling_op(enum poll_type);
57533
57534#endif /* _LVM_LVMPOLLD_CMD_UTILS_H */
57535\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-core.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000064512\013062740170\0023261\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
57536 * Copyright (C) 2014-2015 Red Hat, Inc.
57537 *
57538 * This file is part of LVM2.
57539 *
57540 * This copyrighted material is made available to anyone wishing to use,
57541 * modify, copy, or redistribute it subject to the terms and conditions
57542 * of the GNU Lesser General Public License v.2.1.
57543 *
57544 * You should have received a copy of the GNU Lesser General Public License
57545 * along with this program; if not, write to the Free Software Foundation,
57546 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
57547 */
57548
57549#include "lvmpolld-common.h"
57550
57551#include "lvm-version.h"
57552#include "daemon-server.h"
57553#include "daemon-log.h"
57554
57555#include <getopt.h>
57556#include <poll.h>
57557#include <wait.h>
57558
57559#define LVMPOLLD_SOCKET DEFAULT_RUN_DIR "/lvmpolld.socket"
57560
57561#define PD_LOG_PREFIX "LVMPOLLD"
57562#define LVM2_LOG_PREFIX "\tLVPOLL"
57563
57564/* predefined reason for response = "failed" case */
57565#define REASON_REQ_NOT_IMPLEMENTED "request not implemented"
57566#define REASON_MISSING_LVID "request requires lvid set"
57567#define REASON_MISSING_LVNAME "request requires lvname set"
57568#define REASON_MISSING_VGNAME "request requires vgname set"
57569#define REASON_POLLING_FAILED "polling of lvm command failed"
57570#define REASON_ILLEGAL_ABORT_REQUEST "abort only supported with PVMOVE polling operation"
57571#define REASON_DIFFERENT_OPERATION_IN_PROGRESS "Different operation on LV already in progress"
57572#define REASON_INVALID_INTERVAL "request requires interval set"
57573#define REASON_ENOMEM "not enough memory"
57574
57575struct lvmpolld_state {
57576 daemon_idle *idle;
57577 log_state *log;
57578 const char *log_config;
57579 const char *lvm_binary;
57580
57581 struct lvmpolld_store *id_to_pdlv_abort;
57582 struct lvmpolld_store *id_to_pdlv_poll;
57583};
57584
57585static pthread_key_t key;
57586
57587static const char *_strerror_r(int errnum, struct lvmpolld_thread_data *data)
57588{
57589#ifdef _GNU_SOURCE
57590 return strerror_r(errnum, data->buf, sizeof(data->buf)); /* never returns NULL */
57591#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
57592 return strerror_r(errnum, data->buf, sizeof(data->buf)) ? "" : data->buf;
57593#else
57594# warning "Can't decide proper strerror_r implementation. lvmpolld will not issue specific system error messages"
57595 return "";
57596#endif
57597}
57598
57599static void _usage(const char *prog, FILE *file)
57600{
57601 fprintf(file, "Usage:\n"
57602 "%s [-V] [-h] [-f] [-l {all|wire|debug}] [-s path] [-B path] [-p path] [-t secs]\n"
57603 "%s --dump [-s path]\n"
57604 " -V|--version Show version info\n"
57605 " -h|--help Show this help information\n"
57606 " -f|--foreground Don't fork, run in the foreground\n"
57607 " --dump Dump full lvmpolld state\n"
57608 " -l|--log Logging message level (-l {all|wire|debug})\n"
57609 " -p|--pidfile Set path to the pidfile\n"
57610 " -s|--socket Set path to the communication socket\n"
57611 " -B|--binary Path to lvm2 binary\n"
57612 " -t|--timeout Time to wait in seconds before shutdown on idle (missing or 0 = inifinite)\n\n", prog, prog);
57613}
57614
57615static int _init(struct daemon_state *s)
57616{
57617 struct lvmpolld_state *ls = s->private;
57618 ls->log = s->log;
57619
57620 /*
57621 * log warnings to stderr by default. Otherwise we would miss any lvpoll
57622 * error messages in default configuration
57623 */
57624 daemon_log_enable(ls->log, DAEMON_LOG_OUTLET_STDERR, DAEMON_LOG_WARN, 1);
57625
57626 if (!daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->log_config, 1))
57627 return 0;
57628
57629 if (pthread_key_create(&key, lvmpolld_thread_data_destroy)) {
57630 FATAL(ls, "%s: %s", PD_LOG_PREFIX, "Failed to create pthread key");
57631 return 0;
57632 }
57633
57634 ls->id_to_pdlv_poll = pdst_init("polling");
57635 ls->id_to_pdlv_abort = pdst_init("abort");
57636
57637 if (!ls->id_to_pdlv_poll || !ls->id_to_pdlv_abort) {
57638 FATAL(ls, "%s: %s", PD_LOG_PREFIX, "Failed to allocate internal data structures");
57639 return 0;
57640 }
57641
57642 ls->lvm_binary = ls->lvm_binary ?: LVM_PATH;
57643
57644 if (access(ls->lvm_binary, X_OK)) {
57645 FATAL(ls, "%s: %s %s", PD_LOG_PREFIX, "Execute access rights denied on", ls->lvm_binary);
57646 return 0;
57647 }
57648
57649 if (ls->idle)
57650 ls->idle->is_idle = 1;
57651
57652 return 1;
57653}
57654
57655static void _lvmpolld_stores_lock(struct lvmpolld_state *ls)
57656{
57657 pdst_lock(ls->id_to_pdlv_poll);
57658 pdst_lock(ls->id_to_pdlv_abort);
57659}
57660
57661static void _lvmpolld_stores_unlock(struct lvmpolld_state *ls)
57662{
57663 pdst_unlock(ls->id_to_pdlv_abort);
57664 pdst_unlock(ls->id_to_pdlv_poll);
57665}
57666
57667static void _lvmpolld_global_lock(struct lvmpolld_state *ls)
57668{
57669 _lvmpolld_stores_lock(ls);
57670
57671 pdst_locked_lock_all_pdlvs(ls->id_to_pdlv_poll);
57672 pdst_locked_lock_all_pdlvs(ls->id_to_pdlv_abort);
57673}
57674
57675static void _lvmpolld_global_unlock(struct lvmpolld_state *ls)
57676{
57677 pdst_locked_unlock_all_pdlvs(ls->id_to_pdlv_abort);
57678 pdst_locked_unlock_all_pdlvs(ls->id_to_pdlv_poll);
57679
57680 _lvmpolld_stores_unlock(ls);
57681}
57682
57683static int _fini(struct daemon_state *s)
57684{
57685 int done;
57686 const struct timespec t = { .tv_nsec = 250000000 }; /* .25 sec */
57687 struct lvmpolld_state *ls = s->private;
57688
57689 DEBUGLOG(s, "fini");
57690
57691 DEBUGLOG(s, "sending cancel requests");
57692
57693 _lvmpolld_global_lock(ls);
57694 pdst_locked_send_cancel(ls->id_to_pdlv_poll);
57695 pdst_locked_send_cancel(ls->id_to_pdlv_abort);
57696 _lvmpolld_global_unlock(ls);
57697
57698 DEBUGLOG(s, "waiting for background threads to finish");
57699
57700 while(1) {
57701 _lvmpolld_stores_lock(ls);
57702 done = !pdst_locked_get_active_count(ls->id_to_pdlv_poll) &&
57703 !pdst_locked_get_active_count(ls->id_to_pdlv_abort);
57704 _lvmpolld_stores_unlock(ls);
57705 if (done)
57706 break;
57707 nanosleep(&t, NULL);
57708 }
57709
57710 DEBUGLOG(s, "destroying internal data structures");
57711
57712 _lvmpolld_stores_lock(ls);
57713 pdst_locked_destroy_all_pdlvs(ls->id_to_pdlv_poll);
57714 pdst_locked_destroy_all_pdlvs(ls->id_to_pdlv_abort);
57715 _lvmpolld_stores_unlock(ls);
57716
57717 pdst_destroy(ls->id_to_pdlv_poll);
57718 pdst_destroy(ls->id_to_pdlv_abort);
57719
57720 pthread_key_delete(key);
57721
57722 return 1;
57723}
57724
57725static response reply(const char *res, const char *reason)
57726{
57727 return daemon_reply_simple(res, "reason = %s", reason, NULL);
57728}
57729
57730static int read_single_line(struct lvmpolld_thread_data *data, int err)
57731{
57732 ssize_t r = getline(&data->line, &data->line_size, err ? data->ferr : data->fout);
57733
57734 if (r > 0 && *(data->line + r - 1) == '\n')
57735 *(data->line + r - 1) = '\0';
57736
57737 return (r > 0);
57738}
57739
57740static void update_idle_state(struct lvmpolld_state *ls)
57741{
57742 if (!ls->idle)
57743 return;
57744
57745 _lvmpolld_stores_lock(ls);
57746
57747 ls->idle->is_idle = !pdst_locked_get_active_count(ls->id_to_pdlv_poll) &&
57748 !pdst_locked_get_active_count(ls->id_to_pdlv_abort);
57749
57750 _lvmpolld_stores_unlock(ls);
57751
57752 DEBUGLOG(ls, "%s: %s %s%s", PD_LOG_PREFIX, "daemon is", ls->idle->is_idle ? "" : "not ", "idle");
57753}
57754
57755/* make this configurable */
57756#define MAX_TIMEOUT 2
57757
57758static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data *data)
57759{
57760 int ch_stat, r, err = 1, fds_count = 2, timeout = 0;
57761 pid_t pid;
57762 struct lvmpolld_cmd_stat cmd_state = { .retcode = -1, .signal = 0 };
57763 struct pollfd fds[] = { { .fd = data->outpipe[0], .events = POLLIN },
57764 { .fd = data->errpipe[0], .events = POLLIN } };
57765
57766 if (!(data->fout = fdopen(data->outpipe[0], "r")) || !(data->ferr = fdopen(data->errpipe[0], "r"))) {
57767 ERROR(pdlv->ls, "%s: %s: (%d) %s", PD_LOG_PREFIX, "failed to open file stream",
57768 errno, _strerror_r(errno, data));
57769 goto out;
57770 }
57771
57772 while (1) {
57773 do {
57774 r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
57775 } while (r < 0 && errno == EINTR);
57776
57777 DEBUGLOG(pdlv->ls, "%s: %s %d", PD_LOG_PREFIX, "poll() returned", r);
57778 if (r < 0) {
57779 ERROR(pdlv->ls, "%s: %s (PID %d) failed: (%d) %s",
57780 PD_LOG_PREFIX, "poll() for LVM2 cmd", pdlv->cmd_pid,
57781 errno, _strerror_r(errno, data));
57782 goto out;
57783 } else if (!r) {
57784 timeout++;
57785
57786 WARN(pdlv->ls, "%s: %s (PID %d) %s", PD_LOG_PREFIX,
57787 "polling for output of the lvm cmd", pdlv->cmd_pid,
57788 "has timed out");
57789
57790 if (timeout > MAX_TIMEOUT) {
57791 ERROR(pdlv->ls, "%s: %s (PID %d) (no output for %d seconds)",
57792 PD_LOG_PREFIX,
57793 "LVM2 cmd is unresponsive too long",
57794 pdlv->cmd_pid,
57795 timeout * pdlv_get_timeout(pdlv));
57796 goto out;
57797 }
57798
57799 continue; /* while(1) */
57800 }
57801
57802 timeout = 0;
57803
57804 /* handle the command's STDOUT */
57805 if (fds[0].revents & POLLIN) {
57806 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "caught input data in STDOUT");
57807
57808 assert(read_single_line(data, 0)); /* may block indef. anyway */
57809 INFO(pdlv->ls, "%s: PID %d: %s: '%s'", LVM2_LOG_PREFIX,
57810 pdlv->cmd_pid, "STDOUT", data->line);
57811 } else if (fds[0].revents) {
57812 if (fds[0].revents & POLLHUP)
57813 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "caught POLLHUP");
57814 else
57815 WARN(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "poll for command's STDOUT failed");
57816
57817 fds[0].fd = -1;
57818 fds_count--;
57819 }
57820
57821 /* handle the command's STDERR */
57822 if (fds[1].revents & POLLIN) {
57823 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX,
57824 "caught input data in STDERR");
57825
57826 assert(read_single_line(data, 1)); /* may block indef. anyway */
57827 WARN(pdlv->ls, "%s: PID %d: %s: '%s'", LVM2_LOG_PREFIX,
57828 pdlv->cmd_pid, "STDERR", data->line);
57829 } else if (fds[1].revents) {
57830 if (fds[1].revents & POLLHUP)
57831 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "caught err POLLHUP");
57832 else
57833 WARN(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "poll for command's STDOUT failed");
57834
57835 fds[1].fd = -1;
57836 fds_count--;
57837 }
57838
57839 do {
57840 /*
57841 * fds_count == 0 means polling reached EOF
57842 * or received error on both descriptors.
57843 * In such case, just wait for command to finish
57844 */
57845 pid = waitpid(pdlv->cmd_pid, &ch_stat, fds_count ? WNOHANG : 0);
57846 } while (pid < 0 && errno == EINTR);
57847
57848 if (pid) {
57849 if (pid < 0) {
57850 ERROR(pdlv->ls, "%s: %s (PID %d) failed: (%d) %s",
57851 PD_LOG_PREFIX, "waitpid() for lvm2 cmd",
57852 pdlv->cmd_pid, errno,
57853 _strerror_r(errno, data));
57854 goto out;
57855 }
57856 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "child exited");
57857 break;
57858 }
57859 } /* while(1) */
57860
57861 DEBUGLOG(pdlv->ls, "%s: %s", PD_LOG_PREFIX, "about to collect remaining lines");
57862 if (fds[0].fd >= 0)
57863 while (read_single_line(data, 0)) {
57864 assert(r > 0);
57865 INFO(pdlv->ls, "%s: PID %d: %s: %s", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDOUT", data->line);
57866 }
57867 if (fds[1].fd >= 0)
57868 while (read_single_line(data, 1)) {
57869 assert(r > 0);
57870 WARN(pdlv->ls, "%s: PID %d: %s: %s", LVM2_LOG_PREFIX, pdlv->cmd_pid, "STDERR", data->line);
57871 }
57872
57873 if (WIFEXITED(ch_stat)) {
57874 cmd_state.retcode = WEXITSTATUS(ch_stat);
57875 if (cmd_state.retcode)
57876 ERROR(pdlv->ls, "%s: %s (PID %d) %s (retcode: %d)", PD_LOG_PREFIX,
57877 "lvm2 cmd", pdlv->cmd_pid, "failed", cmd_state.retcode);
57878 else
57879 INFO(pdlv->ls, "%s: %s (PID %d) %s", PD_LOG_PREFIX,
57880 "lvm2 cmd", pdlv->cmd_pid, "finished successfully");
57881 } else if (WIFSIGNALED(ch_stat)) {
57882 ERROR(pdlv->ls, "%s: %s (PID %d) %s (%d)", PD_LOG_PREFIX,
57883 "lvm2 cmd", pdlv->cmd_pid, "got terminated by signal",
57884 WTERMSIG(ch_stat));
57885 cmd_state.signal = WTERMSIG(ch_stat);
57886 }
57887
57888 err = 0;
57889out:
57890 if (!err)
57891 pdlv_set_cmd_state(pdlv, &cmd_state);
57892
57893 return err;
57894}
57895
57896static void debug_print(struct lvmpolld_state *ls, const char * const* ptr)
57897{
57898 const char * const* tmp = ptr;
57899
57900 if (!tmp)
57901 return;
57902
57903 while (*tmp) {
57904 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, *tmp);
57905 tmp++;
57906 }
57907}
57908
57909static void *fork_and_poll(void *args)
57910{
57911 int outfd, errfd, state;
57912 struct lvmpolld_thread_data *data;
57913 pid_t r;
57914
57915 int error = 1;
57916 struct lvmpolld_lv *pdlv = (struct lvmpolld_lv *) args;
57917 struct lvmpolld_state *ls = pdlv->ls;
57918
57919 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
57920 data = lvmpolld_thread_data_constructor(pdlv);
57921 pthread_setspecific(key, data);
57922 pthread_setcancelstate(state, &state);
57923
57924 if (!data) {
57925 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Failed to initialize per-thread data");
57926 goto err;
57927 }
57928
57929 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd line arguments:");
57930 debug_print(ls, pdlv->cmdargv);
57931 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---");
57932
57933 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd environment variables:");
57934 debug_print(ls, pdlv->cmdenvp);
57935 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---");
57936
57937 outfd = data->outpipe[1];
57938 errfd = data->errpipe[1];
57939
57940 r = fork();
57941 if (!r) {
57942 /* child */
57943 /* !!! Do not touch any posix thread primitives !!! */
57944
57945 if ((dup2(outfd, STDOUT_FILENO ) != STDOUT_FILENO) ||
57946 (dup2(errfd, STDERR_FILENO ) != STDERR_FILENO))
57947 _exit(LVMPD_RET_DUP_FAILED);
57948
57949 execve(*(pdlv->cmdargv), (char *const *)pdlv->cmdargv, (char *const *)pdlv->cmdenvp);
57950
57951 _exit(LVMPD_RET_EXC_FAILED);
57952 } else {
57953 /* parent */
57954 if (r == -1) {
57955 ERROR(ls, "%s: %s: (%d) %s", PD_LOG_PREFIX, "fork failed",
57956 errno, _strerror_r(errno, data));
57957 goto err;
57958 }
57959
57960 INFO(ls, "%s: LVM2 cmd \"%s\" (PID: %d)", PD_LOG_PREFIX, *(pdlv->cmdargv), r);
57961
57962 pdlv->cmd_pid = r;
57963
57964 /* failure to close write end of any pipe will result in broken polling */
57965 if (close(data->outpipe[1])) {
57966 ERROR(ls, "%s: %s: (%d) %s", PD_LOG_PREFIX, "failed to close write end of pipe",
57967 errno, _strerror_r(errno, data));
57968 goto err;
57969 }
57970 data->outpipe[1] = -1;
57971
57972 if (close(data->errpipe[1])) {
57973 ERROR(ls, "%s: %s: (%d) %s", PD_LOG_PREFIX, "failed to close write end of err pipe",
57974 errno, _strerror_r(errno, data));
57975 goto err;
57976 }
57977 data->errpipe[1] = -1;
57978
57979 error = poll_for_output(pdlv, data);
57980 DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "polling for lvpoll output has finished");
57981 }
57982
57983err:
57984 r = 0;
57985
57986 pdst_lock(pdlv->pdst);
57987
57988 if (error) {
57989 /* last reader is responsible for pdlv cleanup */
57990 r = pdlv->cmd_pid;
57991 pdlv_set_error(pdlv, 1);
57992 }
57993
57994 pdlv_set_polling_finished(pdlv, 1);
57995 if (data)
57996 data->pdlv = NULL;
57997
57998 pdst_locked_dec(pdlv->pdst);
57999
58000 pdst_unlock(pdlv->pdst);
58001
58002 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
58003 lvmpolld_thread_data_destroy(data);
58004 pthread_setspecific(key, NULL);
58005 pthread_setcancelstate(state, &state);
58006
58007 update_idle_state(ls);
58008
58009 /*
58010 * This is unfortunate case where we
58011 * know nothing about state of lvm cmd and
58012 * (eventually) ongoing progress.
58013 *
58014 * harvest zombies
58015 */
58016 if (r)
58017 while(waitpid(r, NULL, 0) < 0 && errno == EINTR);
58018
58019 return NULL;
58020}
58021
58022static response progress_info(client_handle h, struct lvmpolld_state *ls, request req)
58023{
58024 char *id;
58025 struct lvmpolld_lv *pdlv;
58026 struct lvmpolld_store *pdst;
58027 struct lvmpolld_lv_state st;
58028 response r;
58029 const char *lvid = daemon_request_str(req, LVMPD_PARM_LVID, NULL);
58030 const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
58031 unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
58032
58033 if (!lvid)
58034 return reply(LVMPD_RESP_FAILED, REASON_MISSING_LVID);
58035
58036 id = construct_id(sysdir, lvid);
58037 if (!id) {
58038 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "progress_info request failed to construct ID.");
58039 return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
58040 }
58041
58042 DEBUGLOG(ls, "%s: %s: %s", PD_LOG_PREFIX, "ID", id);
58043
58044 pdst = abort_polling ? ls->id_to_pdlv_abort : ls->id_to_pdlv_poll;
58045
58046 pdst_lock(pdst);
58047
58048 pdlv = pdst_locked_lookup(pdst, id);
58049 if (pdlv) {
58050 /*
58051 * with store lock held, I'm the only reader accessing the pdlv
58052 */
58053 st = pdlv_get_status(pdlv);
58054
58055 if (st.error || st.polling_finished) {
58056 INFO(ls, "%s: %s %s", PD_LOG_PREFIX,
58057 "Polling finished. Removing related data structure for LV",
58058 lvid);
58059 pdst_locked_remove(pdst, id);
58060 pdlv_destroy(pdlv);
58061 }
58062 }
58063 /* pdlv must not be dereferenced from now on */
58064
58065 pdst_unlock(pdst);
58066
58067 dm_free(id);
58068
58069 if (pdlv) {
58070 if (st.error)
58071 return reply(LVMPD_RESP_FAILED, REASON_POLLING_FAILED);
58072
58073 if (st.polling_finished)
58074 r = daemon_reply_simple(LVMPD_RESP_FINISHED,
58075 "reason = %s", st.cmd_state.signal ? LVMPD_REAS_SIGNAL : LVMPD_REAS_RETCODE,
58076 LVMPD_PARM_VALUE " = " FMTd64, (int64_t)(st.cmd_state.signal ?: st.cmd_state.retcode),
58077 NULL);
58078 else
58079 r = daemon_reply_simple(LVMPD_RESP_IN_PROGRESS, NULL);
58080 }
58081 else
58082 r = daemon_reply_simple(LVMPD_RESP_NOT_FOUND, NULL);
58083
58084 return r;
58085}
58086
58087static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls,
58088 struct lvmpolld_store *pdst,
58089 const char *interval, const char *id,
58090 const char *vgname, const char *lvname,
58091 const char *sysdir, enum poll_type type,
58092 unsigned abort_polling, unsigned uinterval)
58093{
58094 const char **cmdargv, **cmdenvp;
58095 struct lvmpolld_lv *pdlv;
58096 unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0);
58097
58098 pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type,
58099 interval, uinterval, pdst);
58100
58101 if (!pdlv) {
58102 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure.");
58103 return NULL;
58104 }
58105
58106 cmdargv = cmdargv_ctr(pdlv, pdlv->ls->lvm_binary, abort_polling, handle_missing_pvs);
58107 if (!cmdargv) {
58108 pdlv_destroy(pdlv);
58109 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct cmd arguments for lvpoll command");
58110 return NULL;
58111 }
58112
58113 pdlv->cmdargv = cmdargv;
58114
58115 cmdenvp = cmdenvp_ctr(pdlv);
58116 if (!cmdenvp) {
58117 pdlv_destroy(pdlv);
58118 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to construct cmd environment for lvpoll command");
58119 return NULL;
58120 }
58121
58122 pdlv->cmdenvp = cmdenvp;
58123
58124 return pdlv;
58125}
58126
58127static int spawn_detached_thread(struct lvmpolld_lv *pdlv)
58128{
58129 int r;
58130 pthread_attr_t attr;
58131
58132 if (pthread_attr_init(&attr) != 0)
58133 return 0;
58134
58135 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
58136 return 0;
58137
58138 r = pthread_create(&pdlv->tid, &attr, fork_and_poll, (void *)pdlv);
58139
58140 if (pthread_attr_destroy(&attr) != 0)
58141 return 0;
58142
58143 return !r;
58144}
58145
58146static response poll_init(client_handle h, struct lvmpolld_state *ls, request req, enum poll_type type)
58147{
58148 char *id;
58149 struct lvmpolld_lv *pdlv;
58150 struct lvmpolld_store *pdst;
58151 unsigned uinterval;
58152
58153 const char *interval = daemon_request_str(req, LVMPD_PARM_INTERVAL, NULL);
58154 const char *lvid = daemon_request_str(req, LVMPD_PARM_LVID, NULL);
58155 const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL);
58156 const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL);
58157 const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
58158 unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
58159
58160 assert(type < POLL_TYPE_MAX);
58161
58162 if (abort_polling && type != PVMOVE)
58163 return reply(LVMPD_RESP_EINVAL, REASON_ILLEGAL_ABORT_REQUEST);
58164
58165 if (!interval || strpbrk(interval, "-") || sscanf(interval, "%u", &uinterval) != 1)
58166 return reply(LVMPD_RESP_EINVAL, REASON_INVALID_INTERVAL);
58167
58168 if (!lvname)
58169 return reply(LVMPD_RESP_FAILED, REASON_MISSING_LVNAME);
58170
58171 if (!lvid)
58172 return reply(LVMPD_RESP_FAILED, REASON_MISSING_LVID);
58173
58174 if (!vgname)
58175 return reply(LVMPD_RESP_FAILED, REASON_MISSING_VGNAME);
58176
58177 id = construct_id(sysdir, lvid);
58178 if (!id) {
58179 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "poll_init request failed to construct ID.");
58180 return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
58181 }
58182
58183 DEBUGLOG(ls, "%s: %s=%s", PD_LOG_PREFIX, "ID", id);
58184
58185 pdst = abort_polling ? ls->id_to_pdlv_abort : ls->id_to_pdlv_poll;
58186
58187 pdst_lock(pdst);
58188
58189 pdlv = pdst_locked_lookup(pdst, id);
58190 if (pdlv && pdlv_get_polling_finished(pdlv)) {
58191 WARN(ls, "%s: %s %s", PD_LOG_PREFIX, "Force removal of uncollected info for LV",
58192 lvid);
58193 /*
58194 * lvmpolld has to remove uncollected results in this case.
58195 * otherwise it would have to refuse request for new polling
58196 * lv with same id.
58197 */
58198 pdst_locked_remove(pdst, id);
58199 pdlv_destroy(pdlv);
58200 pdlv = NULL;
58201 }
58202
58203 if (pdlv) {
58204 if (!pdlv_is_type(pdlv, type)) {
58205 pdst_unlock(pdst);
58206 ERROR(ls, "%s: %s '%s': expected: %s, requested: %s",
58207 PD_LOG_PREFIX, "poll operation type mismatch on LV identified by",
58208 id,
58209 polling_op(pdlv_get_type(pdlv)), polling_op(type));
58210 dm_free(id);
58211 return reply(LVMPD_RESP_EINVAL,
58212 REASON_DIFFERENT_OPERATION_IN_PROGRESS);
58213 }
58214 pdlv->init_rq_count++; /* safe. protected by store lock */
58215 } else {
58216 pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname,
58217 lvname, sysdir, type, abort_polling, 2 * uinterval);
58218 if (!pdlv) {
58219 pdst_unlock(pdst);
58220 dm_free(id);
58221 return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
58222 }
58223 if (!pdst_locked_insert(pdst, id, pdlv)) {
58224 pdlv_destroy(pdlv);
58225 pdst_unlock(pdst);
58226 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "couldn't store internal LV data structure");
58227 dm_free(id);
58228 return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
58229 }
58230 if (!spawn_detached_thread(pdlv)) {
58231 ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to spawn detached monitoring thread");
58232 pdst_locked_remove(pdst, id);
58233 pdlv_destroy(pdlv);
58234 pdst_unlock(pdst);
58235 dm_free(id);
58236 return reply(LVMPD_RESP_FAILED, REASON_ENOMEM);
58237 }
58238
58239 pdst_locked_inc(pdst);
58240 if (ls->idle)
58241 ls->idle->is_idle = 0;
58242 }
58243
58244 pdst_unlock(pdst);
58245
58246 dm_free(id);
58247
58248 return daemon_reply_simple(LVMPD_RESP_OK, NULL);
58249}
58250
58251static response dump_state(client_handle h, struct lvmpolld_state *ls, request r)
58252{
58253 response res = { 0 };
58254 struct buffer *b = &res.buffer;
58255
58256 buffer_init(b);
58257
58258 _lvmpolld_global_lock(ls);
58259
58260 buffer_append(b, "# Registered polling operations\n\n");
58261 buffer_append(b, "poll {\n");
58262 pdst_locked_dump(ls->id_to_pdlv_poll, b);
58263 buffer_append(b, "}\n\n");
58264
58265 buffer_append(b, "# Registered abort operations\n\n");
58266 buffer_append(b, "abort {\n");
58267 pdst_locked_dump(ls->id_to_pdlv_abort, b);
58268 buffer_append(b, "}");
58269
58270 _lvmpolld_global_unlock(ls);
58271
58272 return res;
58273}
58274
58275static response _handler(struct daemon_state s, client_handle h, request r)
58276{
58277 struct lvmpolld_state *ls = s.private;
58278 const char *rq = daemon_request_str(r, "request", "NONE");
58279
58280 if (!strcmp(rq, LVMPD_REQ_PVMOVE))
58281 return poll_init(h, ls, r, PVMOVE);
58282 else if (!strcmp(rq, LVMPD_REQ_CONVERT))
58283 return poll_init(h, ls, r, CONVERT);
58284 else if (!strcmp(rq, LVMPD_REQ_MERGE))
58285 return poll_init(h, ls, r, MERGE);
58286 else if (!strcmp(rq, LVMPD_REQ_MERGE_THIN))
58287 return poll_init(h, ls, r, MERGE_THIN);
58288 else if (!strcmp(rq, LVMPD_REQ_PROGRESS))
58289 return progress_info(h, ls, r);
58290 else if (!strcmp(rq, LVMPD_REQ_DUMP))
58291 return dump_state(h, ls, r);
58292 else
58293 return reply(LVMPD_RESP_EINVAL, REASON_REQ_NOT_IMPLEMENTED);
58294}
58295
58296static int process_timeout_arg(const char *str, unsigned *max_timeouts)
58297{
58298 char *endptr;
58299 unsigned long l;
58300
58301 errno = 0;
58302 l = strtoul(str, &endptr, 10);
58303 if (errno || *endptr || l >= UINT_MAX)
58304 return 0;
58305
58306 *max_timeouts = (unsigned) l;
58307
58308 return 1;
58309}
58310
58311/* Client functionality */
58312typedef int (*action_fn_t) (void *args);
58313
58314struct log_line_baton {
58315 const char *prefix;
58316};
58317
58318daemon_handle _lvmpolld = { .error = 0 };
58319
58320static daemon_handle _lvmpolld_open(const char *socket)
58321{
58322 daemon_info lvmpolld_info = {
58323 .path = "lvmpolld",
58324 .socket = socket ?: DEFAULT_RUN_DIR "/lvmpolld.socket",
58325 .protocol = LVMPOLLD_PROTOCOL,
58326 .protocol_version = LVMPOLLD_PROTOCOL_VERSION
58327 };
58328
58329 return daemon_open(lvmpolld_info);
58330}
58331
58332static void _log_line(const char *line, void *baton) {
58333 struct log_line_baton *b = baton;
58334 fprintf(stdout, "%s%s\n", b->prefix, line);
58335}
58336
58337static int printout_raw_response(const char *prefix, const char *msg)
58338{
58339 struct log_line_baton b = { .prefix = prefix };
58340 char *buf;
58341 char *pos;
58342
58343 buf = dm_strdup(msg);
58344 pos = buf;
58345
58346 if (!buf)
58347 return 0;
58348
58349 while (pos) {
58350 char *next = strchr(pos, '\n');
58351 if (next)
58352 *next = 0;
58353 _log_line(pos, &b);
58354 pos = next ? next + 1 : 0;
58355 }
58356 dm_free(buf);
58357
58358 return 1;
58359}
58360
58361/* place all action implementations below */
58362
58363static int action_dump(void *args __attribute__((unused)))
58364{
58365 daemon_request req;
58366 daemon_reply repl;
58367 int r = 0;
58368
58369 req = daemon_request_make(LVMPD_REQ_DUMP);
58370 if (!req.cft) {
58371 fprintf(stderr, "Failed to create lvmpolld " LVMPD_REQ_DUMP " request.\n");
58372 goto out_req;
58373 }
58374
58375 repl = daemon_send(_lvmpolld, req);
58376 if (repl.error) {
58377 fprintf(stderr, "Failed to send a request or receive response.\n");
58378 goto out_rep;
58379 }
58380
58381 /*
58382 * This is dumb copy & paste from libdaemon log routines.
58383 */
58384 if (!printout_raw_response(" ", repl.buffer.mem)) {
58385 fprintf(stderr, "Failed to print out the response.\n");
58386 goto out_rep;
58387 }
58388
58389 r = 1;
58390
58391out_rep:
58392 daemon_reply_destroy(repl);
58393out_req:
58394 daemon_request_destroy(req);
58395
58396 return r;
58397}
58398
58399enum action_index {
58400 ACTION_DUMP = 0,
58401 ACTION_MAX /* keep at the end */
58402};
58403
58404static const action_fn_t actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
58405
58406static int _make_action(enum action_index idx, void *args)
58407{
58408 return idx < ACTION_MAX ? actions[idx](args) : 0;
58409}
58410
58411static int _lvmpolld_client(const char *socket, unsigned action)
58412{
58413 int r;
58414
58415 _lvmpolld = _lvmpolld_open(socket);
58416
58417 if (_lvmpolld.error || _lvmpolld.socket_fd < 0) {
58418 fprintf(stderr, "Failed to establish connection with lvmpolld.\n");
58419 return 0;
58420 }
58421
58422 r = _make_action(action, NULL);
58423
58424 daemon_close(_lvmpolld);
58425
58426 return r ? EXIT_SUCCESS : EXIT_FAILURE;
58427}
58428
58429static int action_idx = ACTION_MAX;
58430static struct option long_options[] = {
58431 /* Have actions always at the beginning of the array. */
58432 {"dump", no_argument, &action_idx, ACTION_DUMP }, /* or an option_index ? */
58433
58434 /* other options */
58435 {"binary", required_argument, 0, 'B' },
58436 {"foreground", no_argument, 0, 'f' },
58437 {"help", no_argument, 0, 'h' },
58438 {"log", required_argument, 0, 'l' },
58439 {"pidfile", required_argument, 0, 'p' },
58440 {"socket", required_argument, 0, 's' },
58441 {"timeout", required_argument, 0, 't' },
58442 {"version", no_argument, 0, 'V' },
58443 {0, 0, 0, 0 }
58444};
58445
58446int main(int argc, char *argv[])
58447{
58448 int opt;
58449 int option_index = 0;
58450 int client = 0, server = 0;
58451 unsigned action = ACTION_MAX;
58452 struct timeval timeout;
58453 daemon_idle di = { .ptimeout = &timeout };
58454 struct lvmpolld_state ls = { .log_config = "" };
58455 daemon_state s = {
58456 .daemon_fini = _fini,
58457 .daemon_init = _init,
58458 .handler = _handler,
58459 .name = "lvmpolld",
58460 .pidfile = getenv("LVM_LVMPOLLD_PIDFILE") ?: LVMPOLLD_PIDFILE,
58461 .private = &ls,
58462 .protocol = LVMPOLLD_PROTOCOL,
58463 .protocol_version = LVMPOLLD_PROTOCOL_VERSION,
58464 .socket_path = getenv("LVM_LVMPOLLD_SOCKET") ?: LVMPOLLD_SOCKET,
58465 };
58466
58467 while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", long_options, &option_index)) != -1) {
58468 switch (opt) {
58469 case 0 :
58470 if (action < ACTION_MAX) {
58471 fprintf(stderr, "Can't perform more actions. Action already requested: %s\n",
58472 long_options[action].name);
58473 _usage(argv[0], stderr);
58474 exit(EXIT_FAILURE);
58475 }
58476 action = action_idx;
58477 client = 1;
58478 break;
58479 case '?':
58480 _usage(argv[0], stderr);
58481 exit(EXIT_FAILURE);
58482 case 'B': /* --binary */
58483 ls.lvm_binary = optarg;
58484 server = 1;
58485 break;
58486 case 'V': /* --version */
58487 printf("lvmpolld version: " LVM_VERSION "\n");
58488 exit(EXIT_SUCCESS);
58489 case 'f': /* --foreground */
58490 s.foreground = 1;
58491 server = 1;
58492 break;
58493 case 'h': /* --help */
58494 _usage(argv[0], stdout);
58495 exit(EXIT_SUCCESS);
58496 case 'l': /* --log */
58497 ls.log_config = optarg;
58498 server = 1;
58499 break;
58500 case 'p': /* --pidfile */
58501 s.pidfile = optarg;
58502 server = 1;
58503 break;
58504 case 's': /* --socket */
58505 s.socket_path = optarg;
58506 break;
58507 case 't': /* --timeout in seconds */
58508 if (!process_timeout_arg(optarg, &di.max_timeouts)) {
58509 fprintf(stderr, "Invalid value of timeout parameter.\n");
58510 exit(EXIT_FAILURE);
58511 }
58512 /* 0 equals to wait indefinitely */
58513 if (di.max_timeouts)
58514 s.idle = ls.idle = &di;
58515 server = 1;
58516 break;
58517 }
58518 }
58519
58520 if (client && server) {
58521 fprintf(stderr, "Invalid combination of client and server parameters.\n\n");
58522 _usage(argv[0], stdout);
58523 exit(EXIT_FAILURE);
58524 }
58525
58526 if (client)
58527 return _lvmpolld_client(s.socket_path, action);
58528
58529 /* Server */
58530 daemon_start(s);
58531
58532 return EXIT_SUCCESS;
58533}
58534\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-common.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001510\013062740170\0023613\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
58535 * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
58536 *
58537 * This file is part of LVM2.
58538 *
58539 * This copyrighted material is made available to anyone wishing to use,
58540 * modify, copy, or redistribute it subject to the terms and conditions
58541 * of the GNU Lesser General Public License v.2.1.
58542 *
58543 * You should have received a copy of the GNU Lesser General Public License
58544 * along with this program; if not, write to the Free Software Foundation,
58545 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
58546 */
58547
58548/*
58549 * This file must be included first by every lvmpolld source file.
58550 */
58551#ifndef _LVM_LVMPOLLD_COMMON_H
58552#define _LVM_LVMPOLLD_COMMON_H
58553
58554#define _REENTRANT
58555
58556#include "tool.h"
58557
58558#include "lvmpolld-cmd-utils.h"
58559#include "lvmpolld-protocol.h"
58560
58561#include <assert.h>
58562#include <errno.h>
58563
58564#endif /* _LVM_LVMPOLLD_COMMON_H */
58565\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-data-utils.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000023657\013062740170\0024405\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
58566 * Copyright (C) 2014-2015 Red Hat, Inc.
58567 *
58568 * This file is part of LVM2.
58569 *
58570 * This copyrighted material is made available to anyone wishing to use,
58571 * modify, copy, or redistribute it subject to the terms and conditions
58572 * of the GNU Lesser General Public License v.2.1.
58573 *
58574 * You should have received a copy of the GNU Lesser General Public License
58575 * along with this program; if not, write to the Free Software Foundation,
58576 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
58577 */
58578
58579#include "lvmpolld-common.h"
58580
58581#include "config-util.h"
58582
58583#include <fcntl.h>
58584#include <signal.h>
58585
58586static const char LVM_SYSTEM_DIR[] = "LVM_SYSTEM_DIR=";
58587
58588static char *_construct_full_lvname(const char *vgname, const char *lvname)
58589{
58590 char *name;
58591 size_t l;
58592
58593 l = strlen(vgname) + strlen(lvname) + 2; /* vg/lv and \0 */
58594 name = (char *) dm_malloc(l * sizeof(char));
58595 if (!name)
58596 return NULL;
58597
58598 if (dm_snprintf(name, l, "%s/%s", vgname, lvname) < 0) {
58599 dm_free(name);
58600 name = NULL;
58601 }
58602
58603 return name;
58604}
58605
58606static char *_construct_lvm_system_dir_env(const char *sysdir)
58607{
58608 /*
58609 * Store either "LVM_SYSTEM_DIR=/path/to..."
58610 * - or -
58611 * just single char to store NULL byte
58612 */
58613 size_t l = sysdir ? strlen(sysdir) + 16 : 1;
58614 char *env = (char *) dm_malloc(l * sizeof(char));
58615
58616 if (!env)
58617 return NULL;
58618
58619 *env = '\0';
58620
58621 if (sysdir && dm_snprintf(env, l, "%s%s", LVM_SYSTEM_DIR, sysdir) < 0) {
58622 dm_free(env);
58623 env = NULL;
58624 }
58625
58626 return env;
58627}
58628
58629static const char *_get_lvid(const char *lvmpolld_id, const char *sysdir)
58630{
58631 return lvmpolld_id ? (lvmpolld_id + (sysdir ? strlen(sysdir) : 0)) : NULL;
58632}
58633
58634char *construct_id(const char *sysdir, const char *uuid)
58635{
58636 char *id;
58637 int r;
58638 size_t l;
58639
58640 l = strlen(uuid) + (sysdir ? strlen(sysdir) : 0) + 1;
58641 id = (char *) dm_malloc(l * sizeof(char));
58642 if (!id)
58643 return NULL;
58644
58645 r = sysdir ? dm_snprintf(id, l, "%s%s", sysdir, uuid) :
58646 dm_snprintf(id, l, "%s", uuid);
58647
58648 if (r < 0) {
58649 dm_free(id);
58650 id = NULL;
58651 }
58652
58653 return id;
58654}
58655
58656struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
58657 const char *vgname, const char *lvname,
58658 const char *sysdir, enum poll_type type,
58659 const char *sinterval, unsigned pdtimeout,
58660 struct lvmpolld_store *pdst)
58661{
58662 char *lvmpolld_id = dm_strdup(id), /* copy */
58663 *full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
58664 *lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
58665
58666 struct lvmpolld_lv tmp = {
58667 .ls = ls,
58668 .type = type,
58669 .lvmpolld_id = lvmpolld_id,
58670 .lvid = _get_lvid(lvmpolld_id, sysdir),
58671 .lvname = full_lvname,
58672 .lvm_system_dir_env = lvm_system_dir_env,
58673 .sinterval = dm_strdup(sinterval), /* copy */
58674 .pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
58675 .cmd_state = { .retcode = -1, .signal = 0 },
58676 .pdst = pdst,
58677 .init_rq_count = 1
58678 }, *pdlv = (struct lvmpolld_lv *) dm_malloc(sizeof(struct lvmpolld_lv));
58679
58680 if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
58681 goto err;
58682
58683 memcpy(pdlv, &tmp, sizeof(*pdlv));
58684
58685 if (pthread_mutex_init(&pdlv->lock, NULL))
58686 goto err;
58687
58688 return pdlv;
58689
58690err:
58691 dm_free((void *)full_lvname);
58692 dm_free((void *)lvmpolld_id);
58693 dm_free((void *)lvm_system_dir_env);
58694 dm_free((void *)tmp.sinterval);
58695 dm_free((void *)pdlv);
58696
58697 return NULL;
58698}
58699
58700void pdlv_destroy(struct lvmpolld_lv *pdlv)
58701{
58702 dm_free((void *)pdlv->lvmpolld_id);
58703 dm_free((void *)pdlv->lvname);
58704 dm_free((void *)pdlv->sinterval);
58705 dm_free((void *)pdlv->lvm_system_dir_env);
58706 dm_free((void *)pdlv->cmdargv);
58707 dm_free((void *)pdlv->cmdenvp);
58708
58709 pthread_mutex_destroy(&pdlv->lock);
58710
58711 dm_free((void *)pdlv);
58712}
58713
58714unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
58715{
58716 unsigned ret;
58717
58718 pdlv_lock(pdlv);
58719 ret = pdlv->polling_finished;
58720 pdlv_unlock(pdlv);
58721
58722 return ret;
58723}
58724
58725struct lvmpolld_lv_state pdlv_get_status(struct lvmpolld_lv *pdlv)
58726{
58727 struct lvmpolld_lv_state r;
58728
58729 pdlv_lock(pdlv);
58730 r.error = pdlv_locked_error(pdlv);
58731 r.polling_finished = pdlv_locked_polling_finished(pdlv);
58732 r.cmd_state = pdlv_locked_cmd_state(pdlv);
58733 pdlv_unlock(pdlv);
58734
58735 return r;
58736}
58737
58738void pdlv_set_cmd_state(struct lvmpolld_lv *pdlv, const struct lvmpolld_cmd_stat *cmd_state)
58739{
58740 pdlv_lock(pdlv);
58741 pdlv->cmd_state = *cmd_state;
58742 pdlv_unlock(pdlv);
58743}
58744
58745void pdlv_set_error(struct lvmpolld_lv *pdlv, unsigned error)
58746{
58747 pdlv_lock(pdlv);
58748 pdlv->error = error;
58749 pdlv_unlock(pdlv);
58750}
58751
58752void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished)
58753{
58754 pdlv_lock(pdlv);
58755 pdlv->polling_finished = finished;
58756 pdlv_unlock(pdlv);
58757}
58758
58759struct lvmpolld_store *pdst_init(const char *name)
58760{
58761 struct lvmpolld_store *pdst = (struct lvmpolld_store *) dm_malloc(sizeof(struct lvmpolld_store));
58762 if (!pdst)
58763 return NULL;
58764
58765 pdst->store = dm_hash_create(32);
58766 if (!pdst->store)
58767 goto err_hash;
58768 if (pthread_mutex_init(&pdst->lock, NULL))
58769 goto err_mutex;
58770
58771 pdst->name = name;
58772 pdst->active_polling_count = 0;
58773
58774 return pdst;
58775
58776err_mutex:
58777 dm_hash_destroy(pdst->store);
58778err_hash:
58779 dm_free(pdst);
58780 return NULL;
58781}
58782
58783void pdst_destroy(struct lvmpolld_store *pdst)
58784{
58785 if (!pdst)
58786 return;
58787
58788 dm_hash_destroy(pdst->store);
58789 pthread_mutex_destroy(&pdst->lock);
58790 dm_free(pdst);
58791}
58792
58793void pdst_locked_lock_all_pdlvs(const struct lvmpolld_store *pdst)
58794{
58795 struct dm_hash_node *n;
58796
58797 dm_hash_iterate(n, pdst->store)
58798 pdlv_lock(dm_hash_get_data(pdst->store, n));
58799}
58800
58801void pdst_locked_unlock_all_pdlvs(const struct lvmpolld_store *pdst)
58802{
58803 struct dm_hash_node *n;
58804
58805 dm_hash_iterate(n, pdst->store)
58806 pdlv_unlock(dm_hash_get_data(pdst->store, n));
58807}
58808
58809static void _pdlv_locked_dump(struct buffer *buff, const struct lvmpolld_lv *pdlv)
58810{
58811 char tmp[1024];
58812 const struct lvmpolld_cmd_stat *cmd_state = &pdlv->cmd_state;
58813
58814 /* pdlv-section { */
58815 if (dm_snprintf(tmp, sizeof(tmp), "\t%s {\n", pdlv->lvmpolld_id) > 0)
58816 buffer_append(buff, tmp);
58817
58818 if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvid=\"%s\"\n", pdlv->lvid) > 0)
58819 buffer_append(buff, tmp);
58820 if (dm_snprintf(tmp, sizeof(tmp), "\t\ttype=\"%s\"\n", polling_op(pdlv->type)) > 0)
58821 buffer_append(buff, tmp);
58822 if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvname=\"%s\"\n", pdlv->lvname) > 0)
58823 buffer_append(buff, tmp);
58824 if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvmpolld_internal_timeout=%d\n", pdlv->pdtimeout) > 0)
58825 buffer_append(buff, tmp);
58826 if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvm_command_interval=\"%s\"\n", pdlv->sinterval ?: "<undefined>") > 0)
58827 buffer_append(buff, tmp);
58828 if (dm_snprintf(tmp, sizeof(tmp), "\t\t%s\"%s\"\n", LVM_SYSTEM_DIR,
58829 (*pdlv->lvm_system_dir_env ? (pdlv->lvm_system_dir_env + (sizeof(LVM_SYSTEM_DIR) - 1)) : "<undefined>")) > 0)
58830 buffer_append(buff, tmp);
58831 if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvm_command_pid=%d\n", pdlv->cmd_pid) > 0)
58832 buffer_append(buff, tmp);
58833 if (dm_snprintf(tmp, sizeof(tmp), "\t\tpolling_finished=%d\n", pdlv->polling_finished) > 0)
58834 buffer_append(buff, tmp);
58835 if (dm_snprintf(tmp, sizeof(tmp), "\t\terror_occured=%d\n", pdlv->error) > 0)
58836 buffer_append(buff, tmp);
58837 if (dm_snprintf(tmp, sizeof(tmp), "\t\tinit_requests_count=%d\n", pdlv->init_rq_count) > 0)
58838 buffer_append(buff, tmp);
58839
58840 /* lvm_commmand-section { */
58841 buffer_append(buff, "\t\tlvm_command {\n");
58842 if (cmd_state->retcode == -1 && !cmd_state->signal)
58843 buffer_append(buff, "\t\t\tstate=\"" LVMPD_RESP_IN_PROGRESS "\"\n");
58844 else {
58845 buffer_append(buff, "\t\t\tstate=\"" LVMPD_RESP_FINISHED "\"\n");
58846 if (dm_snprintf(tmp, sizeof(tmp), "\t\t\treason=\"%s\"\n\t\t\tvalue=%d\n",
58847 (cmd_state->signal ? LVMPD_REAS_SIGNAL : LVMPD_REAS_RETCODE),
58848 (cmd_state->signal ?: cmd_state->retcode)) > 0)
58849 buffer_append(buff, tmp);
58850 }
58851 buffer_append(buff, "\t\t}\n");
58852 /* } lvm_commmand-section */
58853
58854 buffer_append(buff, "\t}\n");
58855 /* } pdlv-section */
58856}
58857
58858void pdst_locked_dump(const struct lvmpolld_store *pdst, struct buffer *buff)
58859{
58860 struct dm_hash_node *n;
58861
58862 dm_hash_iterate(n, pdst->store)
58863 _pdlv_locked_dump(buff, dm_hash_get_data(pdst->store, n));
58864}
58865
58866void pdst_locked_send_cancel(const struct lvmpolld_store *pdst)
58867{
58868 struct lvmpolld_lv *pdlv;
58869 struct dm_hash_node *n;
58870
58871 dm_hash_iterate(n, pdst->store) {
58872 pdlv = dm_hash_get_data(pdst->store, n);
58873 if (!pdlv_locked_polling_finished(pdlv))
58874 pthread_cancel(pdlv->tid);
58875 }
58876}
58877
58878void pdst_locked_destroy_all_pdlvs(const struct lvmpolld_store *pdst)
58879{
58880 struct dm_hash_node *n;
58881
58882 dm_hash_iterate(n, pdst->store)
58883 pdlv_destroy(dm_hash_get_data(pdst->store, n));
58884}
58885
58886struct lvmpolld_thread_data *lvmpolld_thread_data_constructor(struct lvmpolld_lv *pdlv)
58887{
58888 struct lvmpolld_thread_data *data = (struct lvmpolld_thread_data *) dm_malloc(sizeof(struct lvmpolld_thread_data));
58889 if (!data)
58890 return NULL;
58891
58892 data->pdlv = NULL;
58893 data->line = NULL;
58894 data->line_size = 0;
58895 data->fout = data->ferr = NULL;
58896 data->outpipe[0] = data->outpipe[1] = data->errpipe[0] = data->errpipe[1] = -1;
58897
58898 if (pipe(data->outpipe) || pipe(data->errpipe)) {
58899 lvmpolld_thread_data_destroy(data);
58900 return NULL;
58901 }
58902
58903 if (fcntl(data->outpipe[0], F_SETFD, FD_CLOEXEC) ||
58904 fcntl(data->outpipe[1], F_SETFD, FD_CLOEXEC) ||
58905 fcntl(data->errpipe[0], F_SETFD, FD_CLOEXEC) ||
58906 fcntl(data->errpipe[1], F_SETFD, FD_CLOEXEC)) {
58907 lvmpolld_thread_data_destroy(data);
58908 return NULL;
58909 }
58910
58911 data->pdlv = pdlv;
58912
58913 return data;
58914}
58915
58916void lvmpolld_thread_data_destroy(void *thread_private)
58917{
58918 struct lvmpolld_thread_data *data = (struct lvmpolld_thread_data *) thread_private;
58919 if (!data)
58920 return;
58921
58922 if (data->pdlv) {
58923 pdst_lock(data->pdlv->pdst);
58924 /*
58925 * FIXME: skip this step if lvmpolld is activated
58926 * by systemd.
58927 */
58928 if (!pdlv_get_polling_finished(data->pdlv))
58929 kill(data->pdlv->cmd_pid, SIGTERM);
58930 pdlv_set_polling_finished(data->pdlv, 1);
58931 pdst_locked_dec(data->pdlv->pdst);
58932 pdst_unlock(data->pdlv->pdst);
58933 }
58934
58935 /* may get reallocated in getline(). dm_free must not be used */
58936 free(data->line);
58937
58938 if (data->fout && !fclose(data->fout))
58939 data->outpipe[0] = -1;
58940
58941 if (data->ferr && !fclose(data->ferr))
58942 data->errpipe[0] = -1;
58943
58944 if (data->outpipe[0] >= 0)
58945 (void) close(data->outpipe[0]);
58946
58947 if (data->outpipe[1] >= 0)
58948 (void) close(data->outpipe[1]);
58949
58950 if (data->errpipe[0] >= 0)
58951 (void) close(data->errpipe[0]);
58952
58953 if (data->errpipe[1] >= 0)
58954 (void) close(data->errpipe[1]);
58955
58956 dm_free(data);
58957}
58958\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-cmd-utils.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000007072\013062740170\0024230\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
58959 * Copyright (C) 2015 Red Hat, Inc.
58960 *
58961 * This file is part of LVM2.
58962 *
58963 * This copyrighted material is made available to anyone wishing to use,
58964 * modify, copy, or redistribute it subject to the terms and conditions
58965 * of the GNU Lesser General Public License v.2.1.
58966 *
58967 * You should have received a copy of the GNU Lesser General Public License
58968 * along with this program; if not, write to the Free Software Foundation,
58969 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
58970 */
58971
58972#include "lvmpolld-common.h"
58973
58974/* extract this info from autoconf/automake files */
58975#define LVPOLL_CMD "lvpoll"
58976
58977#define MIN_ARGV_SIZE 8
58978
58979static const char *const const polling_ops[] = { [PVMOVE] = LVMPD_REQ_PVMOVE,
58980 [CONVERT] = LVMPD_REQ_CONVERT,
58981 [MERGE] = LVMPD_REQ_MERGE,
58982 [MERGE_THIN] = LVMPD_REQ_MERGE_THIN };
58983
58984const char *polling_op(enum poll_type type)
58985{
58986 return type < POLL_TYPE_MAX ? polling_ops[type] : "<undefined>";
58987}
58988
58989static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
58990{
58991 const char **newargv;
58992
58993 if (*ind && !(*ind % MIN_ARGV_SIZE)) {
58994 newargv = dm_realloc(*cmdargv, (*ind / MIN_ARGV_SIZE + 1) * MIN_ARGV_SIZE * sizeof(char *));
58995 if (!newargv)
58996 return 0;
58997 *cmdargv = newargv;
58998 }
58999
59000 *(*cmdargv + (*ind)++) = str;
59001
59002 return 1;
59003}
59004
59005const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary, unsigned abort_polling, unsigned handle_missing_pvs)
59006{
59007 unsigned i = 0;
59008 const char **cmd_argv = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));
59009
59010 if (!cmd_argv)
59011 return NULL;
59012
59013 /* path to lvm2 binary */
59014 if (!add_to_cmd_arr(&cmd_argv, lvm_binary, &i))
59015 goto err;
59016
59017 /* cmd to execute */
59018 if (!add_to_cmd_arr(&cmd_argv, LVPOLL_CMD, &i))
59019 goto err;
59020
59021 /* transfer internal polling interval */
59022 if (pdlv->sinterval &&
59023 (!add_to_cmd_arr(&cmd_argv, "--interval", &i) ||
59024 !add_to_cmd_arr(&cmd_argv, pdlv->sinterval, &i)))
59025 goto err;
59026
59027 /* pass abort param */
59028 if (abort_polling &&
59029 !add_to_cmd_arr(&cmd_argv, "--abort", &i))
59030 goto err;
59031
59032 /* pass handle-missing-pvs. used by mirror polling operation */
59033 if (handle_missing_pvs &&
59034 !add_to_cmd_arr(&cmd_argv, "--handlemissingpvs", &i))
59035 goto err;
59036
59037 /* one of: "convert", "pvmove", "merge", "merge_thin" */
59038 if (!add_to_cmd_arr(&cmd_argv, "--polloperation", &i) ||
59039 !add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i))
59040 goto err;
59041
59042 /* vg/lv name */
59043 if (!add_to_cmd_arr(&cmd_argv, pdlv->lvname, &i))
59044 goto err;
59045
59046 /* disable metadata backup */
59047 if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
59048 goto err;
59049
59050 /* terminating NULL */
59051 if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
59052 goto err;
59053
59054 return cmd_argv;
59055err:
59056 dm_free(cmd_argv);
59057 return NULL;
59058}
59059
59060/* FIXME: in fact exclude should be va list */
59061static int copy_env(const char ***cmd_envp, unsigned *i, const char *exclude)
59062{
59063 const char * const* tmp = (const char * const*) environ;
59064
59065 if (!tmp)
59066 return 0;
59067
59068 while (*tmp) {
59069 if (strncmp(*tmp, exclude, strlen(exclude)) && !add_to_cmd_arr(cmd_envp, *tmp, i))
59070 return 0;
59071 tmp++;
59072 }
59073
59074 return 1;
59075}
59076
59077const char **cmdenvp_ctr(const struct lvmpolld_lv *pdlv)
59078{
59079 unsigned i = 0;
59080 const char **cmd_envp = dm_malloc(MIN_ARGV_SIZE * sizeof(char *));
59081
59082 if (!cmd_envp)
59083 return NULL;
59084
59085 /* copy whole environment from lvmpolld, exclude LVM_SYSTEM_DIR if set */
59086 if (!copy_env(&cmd_envp, &i, "LVM_SYSTEM_DIR="))
59087 goto err;
59088
59089 /* Add per client LVM_SYSTEM_DIR variable if set */
59090 if (*pdlv->lvm_system_dir_env && !add_to_cmd_arr(&cmd_envp, pdlv->lvm_system_dir_env, &i))
59091 goto err;
59092
59093 /* terminating NULL */
59094 if (!add_to_cmd_arr(&cmd_envp, NULL, &i))
59095 goto err;
59096
59097 return cmd_envp;
59098err:
59099 dm_free(cmd_envp);
59100 return NULL;
59101}
59102\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/polling_ops.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001442\013062740170\0023025\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
59103 * Copyright (C) 2014-2015 Red Hat, Inc. All rights reserved.
59104 *
59105 * This file is part of LVM2.
59106 *
59107 * This copyrighted material is made available to anyone wishing to use,
59108 * modify, copy, or redistribute it subject to the terms and conditions
59109 * of the GNU Lesser General Public License v.2.1.
59110 *
59111 * You should have received a copy of the GNU Lesser General Public License
59112 * along with this program; if not, write to the Free Software Foundation,
59113 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
59114 */
59115
59116#ifndef _LVM_TOOL_POLLING_OPS_H
59117#define _LVM_TOOL_POLLING_OPS_H
59118
59119/* this file is also part of lvmpolld protocol */
59120
59121#define PVMOVE_POLL "pvmove"
59122#define CONVERT_POLL "convert"
59123#define MERGE_POLL "merge"
59124#define MERGE_THIN_POLL "merge_thin"
59125
59126#endif /* _LVM_TOOL_POLLING_OPS_H */
59127\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/lvmpolld-data-utils.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013035\013062740170\0024377\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
59128 * Copyright (C) 2014-2015 Red Hat, Inc.
59129 *
59130 * This file is part of LVM2.
59131 *
59132 * This copyrighted material is made available to anyone wishing to use,
59133 * modify, copy, or redistribute it subject to the terms and conditions
59134 * of the GNU Lesser General Public License v.2.1.
59135 *
59136 * You should have received a copy of the GNU Lesser General Public License
59137 * along with this program; if not, write to the Free Software Foundation,
59138 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
59139 */
59140
59141#ifndef _LVM_LVMPOLLD_DATA_UTILS_H
59142#define _LVM_LVMPOLLD_DATA_UTILS_H
59143
59144#include <pthread.h>
59145
59146struct buffer;
59147struct lvmpolld_state;
59148
59149enum poll_type {
59150 PVMOVE = 0,
59151 CONVERT,
59152 MERGE,
59153 MERGE_THIN,
59154 POLL_TYPE_MAX
59155};
59156
59157struct lvmpolld_cmd_stat {
59158 int retcode;
59159 int signal;
59160};
59161
59162struct lvmpolld_store {
59163 pthread_mutex_t lock;
59164 void *store;
59165 const char *name;
59166 unsigned active_polling_count;
59167};
59168
59169struct lvmpolld_lv {
59170 /*
59171 * accessing following vars doesn't
59172 * require struct lvmpolld_lv lock
59173 */
59174 struct lvmpolld_state *const ls;
59175 const enum poll_type type;
59176 const char *const lvid;
59177 const char *const lvmpolld_id;
59178 const char *const lvname; /* full vg/lv name */
59179 const unsigned pdtimeout; /* in seconds */
59180 const char *const sinterval;
59181 const char *const lvm_system_dir_env;
59182 struct lvmpolld_store *const pdst;
59183 const char *const *cmdargv;
59184 const char *const *cmdenvp;
59185
59186 /* only used by write */
59187 pid_t cmd_pid;
59188 pthread_t tid;
59189
59190 pthread_mutex_t lock;
59191
59192 /* block of shared variables protected by lock */
59193 struct lvmpolld_cmd_stat cmd_state;
59194 unsigned init_rq_count; /* for debuging purposes only */
59195 unsigned polling_finished:1; /* no more updates */
59196 unsigned error:1; /* unrecoverable error occured in lvmpolld */
59197};
59198
59199typedef void (*lvmpolld_parse_output_fn_t) (struct lvmpolld_lv *pdlv, const char *line);
59200
59201/* TODO: replace with configuration option */
59202#define MIN_POLLING_TIMEOUT 60
59203
59204struct lvmpolld_lv_state {
59205 unsigned error:1;
59206 unsigned polling_finished:1;
59207 struct lvmpolld_cmd_stat cmd_state;
59208};
59209
59210struct lvmpolld_thread_data {
59211 char *line;
59212 size_t line_size;
59213 int outpipe[2];
59214 int errpipe[2];
59215 FILE *fout;
59216 FILE *ferr;
59217 char buf[1024];
59218 struct lvmpolld_lv *pdlv;
59219};
59220
59221char *construct_id(const char *sysdir, const char *lvid);
59222
59223/* LVMPOLLD_LV_T section */
59224
59225/* only call with appropriate struct lvmpolld_store lock held */
59226struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
59227 const char *vgname, const char *lvname,
59228 const char *sysdir, enum poll_type type,
59229 const char *sinterval, unsigned pdtimeout,
59230 struct lvmpolld_store *pdst);
59231
59232/* only call with appropriate struct lvmpolld_store lock held */
59233void pdlv_destroy(struct lvmpolld_lv *pdlv);
59234
59235static inline void pdlv_lock(struct lvmpolld_lv *pdlv)
59236{
59237 pthread_mutex_lock(&pdlv->lock);
59238}
59239
59240static inline void pdlv_unlock(struct lvmpolld_lv *pdlv)
59241{
59242 pthread_mutex_unlock(&pdlv->lock);
59243}
59244
59245/*
59246 * no struct lvmpolld_lv lock required section
59247 */
59248static inline int pdlv_is_type(const struct lvmpolld_lv *pdlv, enum poll_type type)
59249{
59250 return pdlv->type == type;
59251}
59252
59253static inline unsigned pdlv_get_timeout(const struct lvmpolld_lv *pdlv)
59254{
59255 return pdlv->pdtimeout;
59256}
59257
59258static inline enum poll_type pdlv_get_type(const struct lvmpolld_lv *pdlv)
59259{
59260 return pdlv->type;
59261}
59262
59263unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv);
59264struct lvmpolld_lv_state pdlv_get_status(struct lvmpolld_lv *pdlv);
59265void pdlv_set_cmd_state(struct lvmpolld_lv *pdlv, const struct lvmpolld_cmd_stat *cmd_state);
59266void pdlv_set_error(struct lvmpolld_lv *pdlv, unsigned error);
59267void pdlv_set_polling_finished(struct lvmpolld_lv *pdlv, unsigned finished);
59268
59269/*
59270 * struct lvmpolld_lv lock required section
59271 */
59272static inline struct lvmpolld_cmd_stat pdlv_locked_cmd_state(const struct lvmpolld_lv *pdlv)
59273{
59274 return pdlv->cmd_state;
59275}
59276
59277static inline int pdlv_locked_polling_finished(const struct lvmpolld_lv *pdlv)
59278{
59279 return pdlv->polling_finished;
59280}
59281
59282static inline unsigned pdlv_locked_error(const struct lvmpolld_lv *pdlv)
59283{
59284 return pdlv->error;
59285}
59286
59287/* struct lvmpolld_store manipulation routines */
59288
59289struct lvmpolld_store *pdst_init(const char *name);
59290void pdst_destroy(struct lvmpolld_store *pdst);
59291
59292void pdst_locked_dump(const struct lvmpolld_store *pdst, struct buffer *buff);
59293void pdst_locked_lock_all_pdlvs(const struct lvmpolld_store *pdst);
59294void pdst_locked_unlock_all_pdlvs(const struct lvmpolld_store *pdst);
59295void pdst_locked_destroy_all_pdlvs(const struct lvmpolld_store *pdst);
59296void pdst_locked_send_cancel(const struct lvmpolld_store *pdst);
59297
59298static inline void pdst_lock(struct lvmpolld_store *pdst)
59299{
59300 pthread_mutex_lock(&pdst->lock);
59301}
59302
59303static inline void pdst_unlock(struct lvmpolld_store *pdst)
59304{
59305 pthread_mutex_unlock(&pdst->lock);
59306}
59307
59308static inline void pdst_locked_inc(struct lvmpolld_store *pdst)
59309{
59310 pdst->active_polling_count++;
59311}
59312
59313static inline void pdst_locked_dec(struct lvmpolld_store *pdst)
59314{
59315 pdst->active_polling_count--;
59316}
59317
59318static inline unsigned pdst_locked_get_active_count(const struct lvmpolld_store *pdst)
59319{
59320 return pdst->active_polling_count;
59321}
59322
59323static inline int pdst_locked_insert(struct lvmpolld_store *pdst, const char *key, struct lvmpolld_lv *pdlv)
59324{
59325 return dm_hash_insert(pdst->store, key, pdlv);
59326}
59327
59328static inline struct lvmpolld_lv *pdst_locked_lookup(struct lvmpolld_store *pdst, const char *key)
59329{
59330 return dm_hash_lookup(pdst->store, key);
59331}
59332
59333static inline void pdst_locked_remove(struct lvmpolld_store *pdst, const char *key)
59334{
59335 dm_hash_remove(pdst->store, key);
59336}
59337
59338struct lvmpolld_thread_data *lvmpolld_thread_data_constructor(struct lvmpolld_lv *pdlv);
59339void lvmpolld_thread_data_destroy(void *thread_private);
59340
59341#endif /* _LVM_LVMPOLLD_DATA_UTILS_H */
59342\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmpolld/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002554\013062740170\0022401\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
59343# Copyright (C) 2014-2015 Red Hat, Inc.
59344#
59345# This file is part of LVM2.
59346#
59347# This copyrighted material is made available to anyone wishing to use,
59348# modify, copy, or redistribute it subject to the terms and conditions
59349# of the GNU Lesser General Public License v.2.1.
59350#
59351# You should have received a copy of the GNU Lesser General Public License
59352# along with this program; if not, write to the Free Software Foundation,
59353# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
59354
59355srcdir = @srcdir@
59356top_srcdir = @top_srcdir@
59357top_builddir = @top_builddir@
59358
59359SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c
59360
59361TARGETS = lvmpolld
59362
59363.PHONY: install_lvmpolld
59364
59365CFLOW_LIST = $(SOURCES)
59366CFLOW_LIST_TARGET = $(LIB_NAME).cflow
59367CFLOW_TARGET = lvmpolld
59368
59369include $(top_builddir)/make.tmpl
59370
59371INCLUDES += -I$(top_srcdir)/libdaemon/server
59372LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
59373
59374LIBS += $(PTHREAD_LIBS)
59375
59376LDFLAGS += -L$(top_builddir)/libdaemon/server $(DAEMON_LDFLAGS)
59377CLDFLAGS += -L$(top_builddir)/libdaemon/server
59378CFLAGS += $(DAEMON_CFLAGS)
59379
59380lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
59381 $(top_builddir)/libdaemon/server/libdaemonserver.a
59382 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
59383
59384install_lvmpolld: lvmpolld
59385 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
59386
59387install_lvm2: install_lvmpolld
59388
59389install: install_lvm2
59390\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020303\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/libdevmapper-event.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000056413\013062740170\0024251\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
59391 * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
59392 *
59393 * This file is part of the device-mapper userspace tools.
59394 *
59395 * This copyrighted material is made available to anyone wishing to use,
59396 * modify, copy, or redistribute it subject to the terms and conditions
59397 * of the GNU Lesser General Public License v.2.1.
59398 *
59399 * You should have received a copy of the GNU Lesser General Public License
59400 * along with this program; if not, write to the Free Software Foundation,
59401 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
59402 */
59403
59404#include "dm-logging.h"
59405#include "dmlib.h"
59406#include "libdevmapper-event.h"
59407#include "dmeventd.h"
59408
59409#include <fcntl.h>
59410#include <sys/file.h>
59411#include <sys/types.h>
59412#include <sys/stat.h>
59413#include <sys/wait.h>
59414#include <arpa/inet.h> /* for htonl, ntohl */
59415#include <pthread.h>
59416#include <syslog.h>
59417
59418static int _debug_level = 0;
59419static int _use_syslog = 0;
59420static int _sequence_nr = 0;
59421
59422struct dm_event_handler {
59423 char *dso;
59424
59425 char *dmeventd_path;
59426
59427 char *dev_name;
59428
59429 char *uuid;
59430 int major;
59431 int minor;
59432 uint32_t timeout;
59433
59434 enum dm_event_mask mask;
59435};
59436
59437static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
59438{
59439 dm_free(dmevh->dev_name);
59440 dm_free(dmevh->uuid);
59441 dmevh->dev_name = dmevh->uuid = NULL;
59442 dmevh->major = dmevh->minor = 0;
59443}
59444
59445struct dm_event_handler *dm_event_handler_create(void)
59446{
59447 struct dm_event_handler *dmevh;
59448
59449 if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
59450 log_error("Failed to allocate event handler.");
59451 return NULL;
59452 }
59453
59454 return dmevh;
59455}
59456
59457void dm_event_handler_destroy(struct dm_event_handler *dmevh)
59458{
59459 _dm_event_handler_clear_dev_info(dmevh);
59460 dm_free(dmevh->dso);
59461 dm_free(dmevh->dmeventd_path);
59462 dm_free(dmevh);
59463}
59464
59465int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
59466{
59467 if (!dmeventd_path) /* noop */
59468 return 0;
59469
59470 dm_free(dmevh->dmeventd_path);
59471
59472 if (!(dmevh->dmeventd_path = dm_strdup(dmeventd_path)))
59473 return -ENOMEM;
59474
59475 return 0;
59476}
59477
59478int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
59479{
59480 if (!path) /* noop */
59481 return 0;
59482
59483 dm_free(dmevh->dso);
59484
59485 if (!(dmevh->dso = dm_strdup(path)))
59486 return -ENOMEM;
59487
59488 return 0;
59489}
59490
59491int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
59492{
59493 if (!dev_name)
59494 return 0;
59495
59496 _dm_event_handler_clear_dev_info(dmevh);
59497
59498 if (!(dmevh->dev_name = dm_strdup(dev_name)))
59499 return -ENOMEM;
59500
59501 return 0;
59502}
59503
59504int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
59505{
59506 if (!uuid)
59507 return 0;
59508
59509 _dm_event_handler_clear_dev_info(dmevh);
59510
59511 if (!(dmevh->uuid = dm_strdup(uuid)))
59512 return -ENOMEM;
59513
59514 return 0;
59515}
59516
59517void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
59518{
59519 int minor = dmevh->minor;
59520
59521 _dm_event_handler_clear_dev_info(dmevh);
59522
59523 dmevh->major = major;
59524 dmevh->minor = minor;
59525}
59526
59527void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
59528{
59529 int major = dmevh->major;
59530
59531 _dm_event_handler_clear_dev_info(dmevh);
59532
59533 dmevh->major = major;
59534 dmevh->minor = minor;
59535}
59536
59537void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
59538 enum dm_event_mask evmask)
59539{
59540 dmevh->mask = evmask;
59541}
59542
59543void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
59544{
59545 dmevh->timeout = timeout;
59546}
59547
59548const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
59549{
59550 return dmevh->dso;
59551}
59552
59553const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
59554{
59555 return dmevh->dev_name;
59556}
59557
59558const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
59559{
59560 return dmevh->uuid;
59561}
59562
59563int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
59564{
59565 return dmevh->major;
59566}
59567
59568int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
59569{
59570 return dmevh->minor;
59571}
59572
59573int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
59574{
59575 return dmevh->timeout;
59576}
59577
59578enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
59579{
59580 return dmevh->mask;
59581}
59582
59583static int _check_message_id(struct dm_event_daemon_message *msg)
59584{
59585 int pid, seq_nr;
59586
59587 if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
59588 (pid != getpid()) || (seq_nr != _sequence_nr)) {
59589 log_error("Ignoring out-of-sequence reply from dmeventd. "
59590 "Expected %d:%d but received %s.", getpid(),
59591 _sequence_nr, msg->data);
59592 return 0;
59593 }
59594
59595 return 1;
59596}
59597
59598/*
59599 * daemon_read
59600 * @fifos
59601 * @msg
59602 *
59603 * Read message from daemon.
59604 *
59605 * Returns: 0 on failure, 1 on success
59606 */
59607static int _daemon_read(struct dm_event_fifos *fifos,
59608 struct dm_event_daemon_message *msg)
59609{
59610 unsigned bytes = 0;
59611 int ret, i;
59612 fd_set fds;
59613 size_t size = 2 * sizeof(uint32_t); /* status + size */
59614 uint32_t *header = alloca(size);
59615 char *buf = (char *)header;
59616
59617 while (bytes < size) {
59618 for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
59619 /* Watch daemon read FIFO for input. */
59620 struct timeval tval = { .tv_sec = 1 };
59621 FD_ZERO(&fds);
59622 FD_SET(fifos->server, &fds);
59623 ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
59624 if (ret < 0 && errno != EINTR) {
59625 log_error("Unable to read from event server.");
59626 return 0;
59627 }
59628 if ((ret == 0) && (i > 4) && !bytes) {
59629 log_error("No input from event server.");
59630 return 0;
59631 }
59632 }
59633 if (ret < 1) {
59634 log_error("Unable to read from event server.");
59635 return 0;
59636 }
59637
59638 ret = read(fifos->server, buf + bytes, size);
59639 if (ret < 0) {
59640 if ((errno == EINTR) || (errno == EAGAIN))
59641 continue;
59642 else {
59643 log_error("Unable to read from event server.");
59644 return 0;
59645 }
59646 }
59647
59648 bytes += ret;
59649 if (header && (bytes == 2 * sizeof(uint32_t))) {
59650 msg->cmd = ntohl(header[0]);
59651 msg->size = ntohl(header[1]);
59652 buf = msg->data = dm_malloc(msg->size);
59653 size = msg->size;
59654 bytes = 0;
59655 header = 0;
59656 }
59657 }
59658
59659 if (bytes != size) {
59660 dm_free(msg->data);
59661 msg->data = NULL;
59662 }
59663 return bytes == size;
59664}
59665
59666/* Write message to daemon. */
59667static int _daemon_write(struct dm_event_fifos *fifos,
59668 struct dm_event_daemon_message *msg)
59669{
59670 int ret;
59671 fd_set fds;
59672 size_t bytes = 0;
59673 size_t size = 2 * sizeof(uint32_t) + msg->size;
59674 uint32_t *header = alloca(size);
59675 char *buf = (char *)header;
59676 char drainbuf[128];
59677
59678 header[0] = htonl(msg->cmd);
59679 header[1] = htonl(msg->size);
59680 memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
59681
59682 /* drain the answer fifo */
59683 while (1) {
59684 struct timeval tval = { .tv_usec = 100 };
59685 FD_ZERO(&fds);
59686 FD_SET(fifos->server, &fds);
59687 ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
59688 if (ret < 0) {
59689 if (errno == EINTR)
59690 continue;
59691 log_error("Unable to talk to event daemon.");
59692 return 0;
59693 }
59694 if (ret == 0)
59695 break;
59696 ret = read(fifos->server, drainbuf, sizeof(drainbuf));
59697 if (ret < 0) {
59698 if ((errno == EINTR) || (errno == EAGAIN))
59699 continue;
59700 log_error("Unable to talk to event daemon.");
59701 return 0;
59702 }
59703 }
59704
59705 while (bytes < size) {
59706 do {
59707 /* Watch daemon write FIFO to be ready for output. */
59708 FD_ZERO(&fds);
59709 FD_SET(fifos->client, &fds);
59710 ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
59711 if ((ret < 0) && (errno != EINTR)) {
59712 log_error("Unable to talk to event daemon.");
59713 return 0;
59714 }
59715 } while (ret < 1);
59716
59717 ret = write(fifos->client, buf + bytes, size - bytes);
59718 if (ret < 0) {
59719 if ((errno == EINTR) || (errno == EAGAIN))
59720 continue;
59721 else {
59722 log_error("Unable to talk to event daemon.");
59723 return 0;
59724 }
59725 }
59726
59727 bytes += ret;
59728 }
59729
59730 return bytes == size;
59731}
59732
59733int dm_event_daemon_talk(struct dm_event_fifos *fifos,
59734 struct dm_event_daemon_message *msg, int cmd,
59735 const char *dso_name, const char *dev_name,
59736 enum dm_event_mask evmask, uint32_t timeout)
59737{
59738 int msg_size;
59739 memset(msg, 0, sizeof(*msg));
59740
59741 /*
59742 * Set command and pack the arguments
59743 * into ASCII message string.
59744 */
59745 if ((msg_size =
59746 ((cmd == DM_EVENT_CMD_HELLO) ?
59747 dm_asprintf(&(msg->data), "%d:%d HELLO", getpid(), _sequence_nr) :
59748 dm_asprintf(&(msg->data), "%d:%d %s %s %u %" PRIu32,
59749 getpid(), _sequence_nr,
59750 dso_name ? : "-", dev_name ? : "-", evmask, timeout)))
59751 < 0) {
59752 log_error("_daemon_talk: message allocation failed.");
59753 return -ENOMEM;
59754 }
59755 msg->cmd = cmd;
59756 msg->size = msg_size;
59757
59758 /*
59759 * Write command and message to and
59760 * read status return code from daemon.
59761 */
59762 if (!_daemon_write(fifos, msg)) {
59763 stack;
59764 dm_free(msg->data);
59765 msg->data = NULL;
59766 return -EIO;
59767 }
59768
59769 do {
59770 dm_free(msg->data);
59771 msg->data = NULL;
59772
59773 if (!_daemon_read(fifos, msg)) {
59774 stack;
59775 return -EIO;
59776 }
59777 } while (!_check_message_id(msg));
59778
59779 _sequence_nr++;
59780
59781 return (int32_t) msg->cmd;
59782}
59783
59784/*
59785 * start_daemon
59786 *
59787 * This function forks off a process (dmeventd) that will handle
59788 * the events. I am currently test opening one of the fifos to
59789 * ensure that the daemon is running and listening... I thought
59790 * this would be less expensive than fork/exec'ing every time.
59791 * Perhaps there is an even quicker/better way (no, checking the
59792 * lock file is _not_ a better way).
59793 *
59794 * Returns: 1 on success, 0 otherwise
59795 */
59796static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
59797{
59798 int pid, ret = 0;
59799 int status;
59800 struct stat statbuf;
59801 char default_dmeventd_path[] = DMEVENTD_PATH;
59802 char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
59803
59804 /*
59805 * FIXME Explicitly verify the code's requirement that client_path is secure:
59806 * - All parent directories owned by root without group/other write access unless sticky.
59807 */
59808
59809 /* If client fifo path exists, only use it if it is root-owned fifo mode 0600 */
59810 if ((lstat(fifos->client_path, &statbuf) < 0)) {
59811 if (errno == ENOENT)
59812 /* Jump ahead if fifo does not already exist. */
59813 goto start_server;
59814 else {
59815 log_sys_error("stat", fifos->client_path);
59816 return 0;
59817 }
59818 } else if (!S_ISFIFO(statbuf.st_mode)) {
59819 log_error("%s must be a fifo.", fifos->client_path);
59820 return 0;
59821 } else if (statbuf.st_uid) {
59822 log_error("%s must be owned by uid 0.", fifos->client_path);
59823 return 0;
59824 } else if (statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO)) {
59825 log_error("%s must have mode 0600.", fifos->client_path);
59826 return 0;
59827 }
59828
59829 /* Anyone listening? If not, errno will be ENXIO */
59830 fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
59831 if (fifos->client >= 0) {
59832 /* Should never happen if all the above checks passed. */
59833 if ((fstat(fifos->client, &statbuf) < 0) ||
59834 !S_ISFIFO(statbuf.st_mode) || statbuf.st_uid ||
59835 (statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
59836 log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
59837 if (close(fifos->client))
59838 log_sys_debug("close", fifos->client_path);
59839 return 0;
59840 }
59841
59842 /* server is running and listening */
59843 if (close(fifos->client))
59844 log_sys_debug("close", fifos->client_path);
59845 return 1;
59846 } else if (errno != ENXIO && errno != ENOENT) {
59847 /* problem */
59848 log_sys_error("open", fifos->client_path);
59849 return 0;
59850 }
59851
59852start_server:
59853 /* server is not running */
59854
59855 if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
59856 log_sys_error("stat", args[0]);
59857 return 0;
59858 }
59859
59860 pid = fork();
59861
59862 if (pid < 0)
59863 log_sys_error("fork", "");
59864
59865 else if (!pid) {
59866 execvp(args[0], args);
59867 log_error("Unable to exec dmeventd: %s.", strerror(errno));
59868 _exit(EXIT_FAILURE);
59869 } else {
59870 if (waitpid(pid, &status, 0) < 0)
59871 log_error("Unable to start dmeventd: %s.",
59872 strerror(errno));
59873 else if (WEXITSTATUS(status))
59874 log_error("Unable to start dmeventd.");
59875 else
59876 ret = 1;
59877 }
59878
59879 return ret;
59880}
59881
59882int dm_event_daemon_init_fifos(struct dm_event_fifos *fifos)
59883{
59884 /* FIXME? Is fifo the most suitable method? Why not share
59885 comms/daemon code with something else e.g. multipath? */
59886
59887 /* Open the fifo used to read from the daemon. */
59888 if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
59889 log_sys_error("open", fifos->server_path);
59890 return 0;
59891 }
59892
59893 /* Lock out anyone else trying to do communication with the daemon. */
59894 if (flock(fifos->server, LOCK_EX) < 0) {
59895 log_sys_error("flock", fifos->server_path);
59896 goto bad;
59897 }
59898
59899/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
59900 if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
59901 log_sys_error("open", fifos->client_path);
59902 goto bad;
59903 }
59904
59905 return 1;
59906bad:
59907 if (close(fifos->server))
59908 log_sys_debug("close", fifos->server_path);
59909 fifos->server = -1;
59910
59911 return 0;
59912}
59913
59914/* Initialize client. */
59915static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
59916{
59917 if (!_start_daemon(dmeventd_path, fifos))
59918 return_0;
59919
59920 return dm_event_daemon_init_fifos(fifos);
59921}
59922
59923void dm_event_daemon_fini_fifos(struct dm_event_fifos *fifos)
59924{
59925 if (fifos->client >= 0 && close(fifos->client))
59926 log_sys_debug("close", fifos->client_path);
59927
59928 if (fifos->server >= 0) {
59929 if (flock(fifos->server, LOCK_UN))
59930 log_sys_debug("flock unlock", fifos->server_path);
59931
59932 if (close(fifos->server))
59933 log_sys_debug("close", fifos->server_path);
59934 }
59935}
59936
59937/* Get uuid of a device */
59938static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
59939{
59940 struct dm_task *dmt;
59941 struct dm_info info;
59942
59943 if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
59944 log_error("_get_device_info: dm_task creation for info failed.");
59945 return NULL;
59946 }
59947
59948 if (dmevh->uuid) {
59949 if (!dm_task_set_uuid(dmt, dmevh->uuid))
59950 goto_bad;
59951 } else if (dmevh->dev_name) {
59952 if (!dm_task_set_name(dmt, dmevh->dev_name))
59953 goto_bad;
59954 } else if (dmevh->major && dmevh->minor) {
59955 if (!dm_task_set_major(dmt, dmevh->major) ||
59956 !dm_task_set_minor(dmt, dmevh->minor))
59957 goto_bad;
59958 }
59959
59960 /* FIXME Add name or uuid or devno to messages */
59961 if (!dm_task_run(dmt)) {
59962 log_error("_get_device_info: dm_task_run() failed.");
59963 goto bad;
59964 }
59965
59966 if (!dm_task_get_info(dmt, &info)) {
59967 log_error("_get_device_info: failed to get info for device.");
59968 goto bad;
59969 }
59970
59971 if (!info.exists) {
59972 log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found.",
59973 dmevh->uuid ? : "",
59974 (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
59975 (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
59976 (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0,
59977 (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "",
59978 (!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0,
59979 (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "",
59980 (!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : "");
59981 goto bad;
59982 }
59983
59984 return dmt;
59985
59986 bad:
59987 dm_task_destroy(dmt);
59988 return NULL;
59989}
59990
59991/* Handle the event (de)registration call and return negative error codes. */
59992static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg,
59993 const char *dso_name, const char *dev_name,
59994 enum dm_event_mask evmask, uint32_t timeout)
59995{
59996 int ret;
59997 struct dm_event_fifos fifos = {
59998 .server = -1,
59999 .client = -1,
60000 /* FIXME Make these either configurable or depend directly on dmeventd_path */
60001 .client_path = DM_EVENT_FIFO_CLIENT,
60002 .server_path = DM_EVENT_FIFO_SERVER
60003 };
60004
60005 if (!_init_client(dmeventd_path, &fifos)) {
60006 ret = -ESRCH;
60007 goto_out;
60008 }
60009
60010 ret = dm_event_daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
60011
60012 dm_free(msg->data);
60013 msg->data = 0;
60014
60015 if (!ret)
60016 ret = dm_event_daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
60017out:
60018 /* what is the opposite of init? */
60019 dm_event_daemon_fini_fifos(&fifos);
60020
60021 return ret;
60022}
60023
60024/* External library interface. */
60025int dm_event_register_handler(const struct dm_event_handler *dmevh)
60026{
60027 int ret = 1, err;
60028 const char *uuid;
60029 struct dm_task *dmt;
60030 struct dm_event_daemon_message msg = { 0 };
60031
60032 if (!(dmt = _get_device_info(dmevh)))
60033 return_0;
60034
60035 uuid = dm_task_get_uuid(dmt);
60036
60037 if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") &&
60038 !strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
60039 !strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
60040 !strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
60041 log_warn("WARNING: %s: dmeventd plugins are deprecated.", dmevh->dso);
60042
60043
60044 if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
60045 dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
60046 log_error("%s: event registration failed: %s.",
60047 dm_task_get_name(dmt),
60048 msg.data ? msg.data : strerror(-err));
60049 ret = 0;
60050 }
60051
60052 dm_free(msg.data);
60053
60054 dm_task_destroy(dmt);
60055
60056 return ret;
60057}
60058
60059int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
60060{
60061 int ret = 1, err;
60062 const char *uuid;
60063 struct dm_task *dmt;
60064 struct dm_event_daemon_message msg = { 0 };
60065
60066 if (!(dmt = _get_device_info(dmevh)))
60067 return_0;
60068
60069 uuid = dm_task_get_uuid(dmt);
60070
60071 if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
60072 dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
60073 log_error("%s: event deregistration failed: %s.",
60074 dm_task_get_name(dmt),
60075 msg.data ? msg.data : strerror(-err));
60076 ret = 0;
60077 }
60078
60079 dm_free(msg.data);
60080
60081 dm_task_destroy(dmt);
60082
60083 return ret;
60084}
60085
60086/* Fetch a string off src and duplicate it into *dest. */
60087/* FIXME: move to separate module to share with the daemon. */
60088static char *_fetch_string(char **src, const int delimiter)
60089{
60090 char *p, *ret;
60091
60092 if ((p = strchr(*src, delimiter)))
60093 *p = 0;
60094
60095 if ((ret = dm_strdup(*src)))
60096 *src += strlen(ret) + 1;
60097
60098 if (p)
60099 *p = delimiter;
60100
60101 return ret;
60102}
60103
60104/* Parse a device message from the daemon. */
60105static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
60106 char **uuid, enum dm_event_mask *evmask)
60107{
60108 char *id;
60109 char *p = msg->data;
60110
60111 if ((id = _fetch_string(&p, ' ')) &&
60112 (*dso_name = _fetch_string(&p, ' ')) &&
60113 (*uuid = _fetch_string(&p, ' '))) {
60114 *evmask = atoi(p);
60115 dm_free(id);
60116 return 0;
60117 }
60118
60119 dm_free(id);
60120 return -ENOMEM;
60121}
60122
60123/*
60124 * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
60125 */
60126int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
60127{
60128 int ret = 0;
60129 const char *uuid = NULL;
60130 char *reply_dso = NULL, *reply_uuid = NULL;
60131 enum dm_event_mask reply_mask = 0;
60132 struct dm_task *dmt = NULL;
60133 struct dm_event_daemon_message msg = { 0 };
60134 struct dm_info info;
60135
60136 if (!(dmt = _get_device_info(dmevh))) {
60137 log_debug("Device does not exists (uuid=%s, name=%s, %d:%d).",
60138 dmevh->uuid, dmevh->dev_name,
60139 dmevh->major, dmevh->minor);
60140 ret = -ENODEV;
60141 goto fail;
60142 }
60143
60144 uuid = dm_task_get_uuid(dmt);
60145
60146 /* FIXME Distinguish errors connecting to daemon */
60147 if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
60148 DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
60149 &msg, dmevh->dso, uuid, dmevh->mask, 0)) {
60150 log_debug("%s: device not registered.", dm_task_get_name(dmt));
60151 ret = -ENOENT;
60152 goto fail;
60153 }
60154
60155 /* FIXME this will probably horribly break if we get
60156 ill-formatted reply */
60157 ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
60158
60159 dm_task_destroy(dmt);
60160 dmt = NULL;
60161
60162 dm_free(msg.data);
60163 msg.data = NULL;
60164
60165 _dm_event_handler_clear_dev_info(dmevh);
60166 if (!reply_uuid) {
60167 ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
60168 goto fail;
60169 }
60170
60171 if (!(dmevh->uuid = dm_strdup(reply_uuid))) {
60172 ret = -ENOMEM;
60173 goto fail;
60174 }
60175
60176 if (!(dmt = _get_device_info(dmevh))) {
60177 ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
60178 goto fail;
60179 }
60180
60181 dm_event_handler_set_dso(dmevh, reply_dso);
60182 dm_event_handler_set_event_mask(dmevh, reply_mask);
60183
60184 dm_free(reply_dso);
60185 reply_dso = NULL;
60186
60187 dm_free(reply_uuid);
60188 reply_uuid = NULL;
60189
60190 if (!(dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)))) {
60191 ret = -ENOMEM;
60192 goto fail;
60193 }
60194
60195 if (!dm_task_get_info(dmt, &info)) {
60196 ret = -1;
60197 goto fail;
60198 }
60199
60200 dmevh->major = info.major;
60201 dmevh->minor = info.minor;
60202
60203 dm_task_destroy(dmt);
60204
60205 return ret;
60206
60207 fail:
60208 dm_free(msg.data);
60209 dm_free(reply_dso);
60210 dm_free(reply_uuid);
60211 _dm_event_handler_clear_dev_info(dmevh);
60212 if (dmt)
60213 dm_task_destroy(dmt);
60214 return ret;
60215}
60216
60217/*
60218 * You can (and have to) call this at the stage of the protocol where
60219 * daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)
60220 *
60221 * would be normally sent. This call will parse the version reply from
60222 * dmeventd, in addition to above call. It is not safe to call this at any
60223 * other place in the protocol.
60224 *
60225 * This is an internal function, not exposed in the public API.
60226 */
60227
60228int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
60229 char *p;
60230 struct dm_event_daemon_message msg = { 0 };
60231
60232 if (dm_event_daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
60233 return 0;
60234 p = msg.data;
60235 *version = 0;
60236
60237 if (!p || !(p = strchr(p, ' '))) /* Message ID */
60238 return 0;
60239 if (!(p = strchr(p + 1, ' '))) /* HELLO */
60240 return 0;
60241 if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
60242 *version = atoi(p);
60243
60244 return 1;
60245}
60246
60247void dm_event_log_set(int debug_log_level, int use_syslog)
60248{
60249 _debug_level = debug_log_level;
60250 _use_syslog = use_syslog;
60251}
60252
60253void dm_event_log(const char *subsys, int level, const char *file,
60254 int line, int dm_errno_or_class,
60255 const char *format, va_list ap)
60256{
60257 static int _abort_on_internal_errors = -1;
60258 static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
60259 static time_t start = 0;
60260 const char *indent = "";
60261 FILE *stream = log_stderr(level) ? stderr : stdout;
60262 int prio;
60263 time_t now;
60264 int log_with_debug = 0;
60265
60266 if (subsys[0] == '#') {
60267 /* Subsystems starting with '#' are logged
60268 * only when debugging is enabled. */
60269 log_with_debug++;
60270 subsys++;
60271 }
60272
60273 switch (log_level(level)) {
60274 case _LOG_DEBUG:
60275 /* Never shown without -ddd */
60276 if (_debug_level < 3)
60277 return;
60278 prio = LOG_DEBUG;
60279 indent = " ";
60280 break;
60281 case _LOG_INFO:
60282 if (log_with_debug && _debug_level < 2)
60283 return;
60284 prio = LOG_INFO;
60285 indent = " ";
60286 break;
60287 case _LOG_NOTICE:
60288 if (log_with_debug && _debug_level < 1)
60289 return;
60290 prio = LOG_NOTICE;
60291 indent = " ";
60292 break;
60293 case _LOG_WARN:
60294 prio = LOG_WARNING;
60295 break;
60296 case _LOG_ERR:
60297 prio = LOG_ERR;
60298 stream = stderr;
60299 break;
60300 default:
60301 prio = LOG_CRIT;
60302 }
60303
60304 /* Serialize to keep lines readable */
60305 pthread_mutex_lock(&_log_mutex);
60306
60307 if (_use_syslog) {
60308 vsyslog(prio, format, ap);
60309 } else {
60310 now = time(NULL);
60311 if (!start)
60312 start = now;
60313 now -= start;
60314 if (_debug_level)
60315 fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
60316 (int)now / 60, (int)now % 60,
60317 // TODO: Maybe use shorter ID
60318 // ((int)(pthread_self()) >> 6) & 0xffff,
60319 (int)pthread_self(), subsys,
60320 (_debug_level > 3) ? "" : indent);
60321 if (_debug_level > 3)
60322 fprintf(stream, "%28s:%4d %s", file, line, indent);
60323 vfprintf(stream, _(format), ap);
60324 fputc('\n', stream);
60325 fflush(stream);
60326 }
60327
60328 pthread_mutex_unlock(&_log_mutex);
60329
60330 if (_abort_on_internal_errors < 0)
60331 /* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
60332 _abort_on_internal_errors =
60333 strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
60334
60335 if (_abort_on_internal_errors &&
60336 !strncmp(format, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
60337 abort();
60338}
60339
60340#if 0 /* left out for now */
60341
60342static char *_skip_string(char *src, const int delimiter)
60343{
60344 src = srtchr(src, delimiter);
60345 if (src && *(src + 1))
60346 return src + 1;
60347 return NULL;
60348}
60349
60350int dm_event_set_timeout(const char *device_path, uint32_t timeout)
60351{
60352 struct dm_event_daemon_message msg = { 0 };
60353
60354 if (!device_exists(device_path))
60355 return -ENODEV;
60356
60357 return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
60358 NULL, device_path, 0, timeout);
60359}
60360
60361int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
60362{
60363 int ret;
60364 struct dm_event_daemon_message msg = { 0 };
60365
60366 if (!device_exists(device_path))
60367 return -ENODEV;
60368
60369 if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
60370 0, 0))) {
60371 char *p = _skip_string(msg.data, ' ');
60372 if (!p) {
60373 log_error("Malformed reply from dmeventd '%s'.",
60374 msg.data);
60375 dm_free(msg.data);
60376 return -EIO;
60377 }
60378 *timeout = atoi(p);
60379 }
60380 dm_free(msg.data);
60381
60382 return ret;
60383}
60384#endif
60385\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006331\013062740170\0022353\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
60386# Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
60387#
60388# This file is part of the device-mapper userspace tools.
60389#
60390# This copyrighted material is made available to anyone wishing to use,
60391# modify, copy, or redistribute it subject to the terms and conditions
60392# of the GNU Lesser General Public License v.2.1.
60393#
60394# You should have received a copy of the GNU Lesser General Public License
60395# along with this program; if not, write to the Free Software Foundation,
60396# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60397
60398srcdir = @srcdir@
60399top_srcdir = @top_srcdir@
60400top_builddir = @top_builddir@
60401
60402SOURCES = libdevmapper-event.c
60403SOURCES2 = dmeventd.c
60404
60405TARGETS = dmeventd
60406
60407.PHONY: install_lib_dynamic install_lib_static install_include \
60408 install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
60409 install_lib install_dmeventd
60410
60411INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
60412INSTALL_LIB_TARGETS = install_lib_dynamic
60413
60414LIB_NAME = libdevmapper-event
60415ifeq ("@STATIC_LINK@", "yes")
60416 LIB_STATIC = $(LIB_NAME).a
60417 TARGETS += $(LIB_STATIC) dmeventd.static
60418 INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
60419 INSTALL_LIB_TARGETS += install_lib_static
60420endif
60421
60422LIB_VERSION = $(LIB_VERSION_DM)
60423LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
60424
60425CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
60426
60427ifneq ($(MAKECMDGOALS),device-mapper)
60428 SUBDIRS+=plugins
60429endif
60430
60431CFLOW_LIST = $(SOURCES)
60432CFLOW_LIST_TARGET = $(LIB_NAME).cflow
60433CFLOW_TARGET = dmeventd
60434
60435EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
60436EXPORTED_FN_PREFIX = dm_event
60437
60438include $(top_builddir)/make.tmpl
60439
60440all: device-mapper
60441device-mapper: $(TARGETS)
60442
60443LIBS += -ldevmapper
60444LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
60445
60446CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
60447
60448dmeventd: $(LIB_SHARED) dmeventd.o
60449 $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
60450 $(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
60451
60452dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
60453 $(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
60454 dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
60455
60456ifeq ("@PKGCONFIG@", "yes")
60457 INSTALL_LIB_TARGETS += install_pkgconfig
60458endif
60459
60460ifneq ("$(CFLOW_CMD)", "")
60461CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
60462-include $(top_builddir)/libdm/libdevmapper.cflow
60463-include $(top_builddir)/lib/liblvm-internal.cflow
60464-include $(top_builddir)/lib/liblvm2cmd.cflow
60465-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
60466-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
60467endif
60468
60469install_include: $(srcdir)/libdevmapper-event.h
60470 $(INSTALL_DATA) -D $< $(includedir)/$(<F)
60471
60472install_pkgconfig: libdevmapper-event.pc
60473 $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
60474
60475install_lib_dynamic: install_lib_shared
60476
60477install_lib_static: $(LIB_STATIC)
60478 $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
60479
60480install_lib: $(INSTALL_LIB_TARGETS)
60481
60482install_dmeventd_dynamic: dmeventd
60483 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
60484
60485install_dmeventd_static: dmeventd.static
60486 $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
60487
60488install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
60489
60490install: install_include install_lib install_dmeventd
60491
60492install_device-mapper: install_include install_lib install_dmeventd
60493
60494DISTCLEAN_TARGETS += libdevmapper-event.pc
60495\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0021764\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/snapshot/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0023623\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000016636\013062740170\0027530\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
60496 * Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved.
60497 *
60498 * This file is part of LVM2.
60499 *
60500 * This copyrighted material is made available to anyone wishing to use,
60501 * modify, copy, or redistribute it subject to the terms and conditions
60502 * of the GNU Lesser General Public License v.2.1.
60503 *
60504 * You should have received a copy of the GNU Lesser General Public License
60505 * along with this program; if not, write to the Free Software Foundation,
60506 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60507 */
60508
60509#include "lib.h"
60510#include "dmeventd_lvm.h"
60511#include "libdevmapper-event.h"
60512
60513#include <sys/sysmacros.h>
60514#include <sys/wait.h>
60515#include <stdarg.h>
60516#include <pthread.h>
60517
60518/* First warning when snapshot is 80% full. */
60519#define WARNING_THRESH (DM_PERCENT_1 * 80)
60520/* Run a check every 5%. */
60521#define CHECK_STEP (DM_PERCENT_1 * 5)
60522/* Do not bother checking snapshots less than 50% full. */
60523#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
60524
60525#define UMOUNT_COMMAND "/bin/umount"
60526
60527struct dso_state {
60528 struct dm_pool *mem;
60529 dm_percent_t percent_check;
60530 uint64_t known_size;
60531 char cmd_lvextend[512];
60532};
60533
60534DM_EVENT_LOG_FN("snap")
60535
60536static int _run(const char *cmd, ...)
60537{
60538 va_list ap;
60539 int argc = 1; /* for argv[0], i.e. cmd */
60540 int i = 0;
60541 const char **argv;
60542 pid_t pid = fork();
60543 int status;
60544
60545 if (pid == 0) { /* child */
60546 va_start(ap, cmd);
60547 while (va_arg(ap, const char *))
60548 ++ argc;
60549 va_end(ap);
60550
60551 /* + 1 for the terminating NULL */
60552 argv = alloca(sizeof(const char *) * (argc + 1));
60553
60554 argv[0] = cmd;
60555 va_start(ap, cmd);
60556 while ((argv[++i] = va_arg(ap, const char *)));
60557 va_end(ap);
60558
60559 execvp(cmd, (char **)argv);
60560 log_sys_error("exec", cmd);
60561 exit(127);
60562 }
60563
60564 if (pid > 0) { /* parent */
60565 if (waitpid(pid, &status, 0) != pid)
60566 return 0; /* waitpid failed */
60567 if (!WIFEXITED(status) || WEXITSTATUS(status))
60568 return 0; /* the child failed */
60569 }
60570
60571 if (pid < 0)
60572 return 0; /* fork failed */
60573
60574 return 1; /* all good */
60575}
60576
60577static int _extend(const char *cmd)
60578{
60579 log_debug("Extending snapshot via %s.", cmd);
60580 return dmeventd_lvm2_run_with_lock(cmd);
60581}
60582
60583#ifdef SNAPSHOT_REMOVE
60584/* Remove invalid snapshot from dm-table */
60585/* Experimental for now and not used by default */
60586static int _remove(const char *uuid)
60587{
60588 int r = 1;
60589 uint32_t cookie = 0;
60590 struct dm_task *dmt;
60591
60592 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
60593 return 0;
60594
60595 if (!dm_task_set_uuid(dmt, uuid)) {
60596 r = 0;
60597 goto_out;
60598 }
60599
60600 dm_task_retry_remove(dmt);
60601
60602 if (!dm_task_set_cookie(dmt, &cookie, 0)) {
60603 r = 0;
60604 goto_out;
60605 }
60606
60607 if (!dm_task_run(dmt)) {
60608 r = 0;
60609 goto_out;
60610 }
60611out:
60612 dm_task_destroy(dmt);
60613
60614 return r;
60615}
60616#endif /* SNAPSHOT_REMOVE */
60617
60618static void _umount(const char *device, int major, int minor)
60619{
60620 FILE *mounts;
60621 char buffer[4096];
60622 char *words[3];
60623 struct stat st;
60624 const char procmounts[] = "/proc/mounts";
60625
60626 if (!(mounts = fopen(procmounts, "r"))) {
60627 log_sys_error("fopen", procmounts);
60628 log_error("Not umounting %s.", device);
60629 return;
60630 }
60631
60632 while (!feof(mounts)) {
60633 /* read a line of /proc/mounts */
60634 if (!fgets(buffer, sizeof(buffer), mounts))
60635 break; /* eof, likely */
60636
60637 /* words[0] is the mount point and words[1] is the device path */
60638 if (dm_split_words(buffer, 3, 0, words) < 2)
60639 continue;
60640
60641 /* find the major/minor of the device */
60642 if (stat(words[0], &st))
60643 continue; /* can't stat, skip this one */
60644
60645 if (S_ISBLK(st.st_mode) &&
60646 (int) major(st.st_rdev) == major &&
60647 (int) minor(st.st_rdev) == minor) {
60648 log_error("Unmounting invalid snapshot %s from %s.", device, words[1]);
60649 if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
60650 log_error("Failed to umount snapshot %s from %s: %s.",
60651 device, words[1], strerror(errno));
60652 }
60653 }
60654
60655 if (fclose(mounts))
60656 log_sys_error("close", procmounts);
60657}
60658
60659void process_event(struct dm_task *dmt,
60660 enum dm_event_mask event __attribute__((unused)),
60661 void **user)
60662{
60663 struct dso_state *state = *user;
60664 void *next = NULL;
60665 uint64_t start, length;
60666 char *target_type = NULL;
60667 char *params;
60668 struct dm_status_snapshot *status = NULL;
60669 const char *device = dm_task_get_name(dmt);
60670 int percent;
60671 struct dm_info info;
60672
60673 /* No longer monitoring, waiting for remove */
60674 if (!state->percent_check)
60675 return;
60676
60677 dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
60678 if (!target_type || strcmp(target_type, "snapshot")) {
60679 log_error("Target %s is not snapshot.", target_type);
60680 return;
60681 }
60682
60683 if (!dm_get_status_snapshot(state->mem, params, &status)) {
60684 log_error("Cannot parse snapshot %s state: %s.", device, params);
60685 return;
60686 }
60687
60688 /*
60689 * If the snapshot has been invalidated or we failed to parse
60690 * the status string. Report the full status string to syslog.
60691 */
60692 if (status->invalid || status->overflow || !status->total_sectors) {
60693 log_warn("WARNING: Snapshot %s changed state to: %s and should be removed.",
60694 device, params);
60695 state->percent_check = 0;
60696 if (dm_task_get_info(dmt, &info))
60697 _umount(device, info.major, info.minor);
60698#ifdef SNAPSHOT_REMOVE
60699 /* Maybe configurable ? */
60700 _remove(dm_task_get_uuid(dmt));
60701#endif
60702 pthread_kill(pthread_self(), SIGALRM);
60703 goto out;
60704 }
60705
60706 if (length <= (status->used_sectors - status->metadata_sectors)) {
60707 /* TODO eventually recognize earlier when room is enough */
60708 log_info("Dropping monitoring of fully provisioned snapshot %s.",
60709 device);
60710 pthread_kill(pthread_self(), SIGALRM);
60711 goto out;
60712 }
60713
60714 /* Snapshot size had changed. Clear the threshold. */
60715 if (state->known_size != status->total_sectors) {
60716 state->percent_check = CHECK_MINIMUM;
60717 state->known_size = status->total_sectors;
60718 }
60719
60720 percent = dm_make_percent(status->used_sectors, status->total_sectors);
60721 if (percent >= state->percent_check) {
60722 /* Usage has raised more than CHECK_STEP since the last
60723 time. Run actions. */
60724 state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
60725
60726 if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
60727 log_warn("WARNING: Snapshot %s is now %.2f%% full.",
60728 device, dm_percent_to_float(percent));
60729
60730 /* Try to extend the snapshot, in accord with user-set policies */
60731 if (!_extend(state->cmd_lvextend))
60732 log_error("Failed to extend snapshot %s.", device);
60733 }
60734out:
60735 dm_pool_free(state->mem, status);
60736}
60737
60738int register_device(const char *device,
60739 const char *uuid __attribute__((unused)),
60740 int major __attribute__((unused)),
60741 int minor __attribute__((unused)),
60742 void **user)
60743{
60744 struct dso_state *state;
60745
60746 if (!dmeventd_lvm2_init_with_pool("snapshot_state", state))
60747 goto_bad;
60748
60749 if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend,
60750 sizeof(state->cmd_lvextend),
60751 "lvextend --use-policies", device)) {
60752 dmeventd_lvm2_exit_with_pool(state);
60753 goto_bad;
60754 }
60755
60756 state->percent_check = CHECK_MINIMUM;
60757 *user = state;
60758
60759 log_info("Monitoring snapshot %s.", device);
60760
60761 return 1;
60762bad:
60763 log_error("Failed to monitor snapshot %s.", device);
60764
60765 return 0;
60766}
60767
60768int unregister_device(const char *device,
60769 const char *uuid __attribute__((unused)),
60770 int major __attribute__((unused)),
60771 int minor __attribute__((unused)),
60772 void **user)
60773{
60774 struct dso_state *state = *user;
60775
60776 dmeventd_lvm2_exit_with_pool(state);
60777 log_info("No longer monitoring snapshot %s.", device);
60778
60779 return 1;
60780}
60781\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/snapshot/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001772\013062740170\0025677\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
60782# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
60783# Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
60784#
60785# This file is part of the LVM2.
60786#
60787# This copyrighted material is made available to anyone wishing to use,
60788# modify, copy, or redistribute it subject to the terms and conditions
60789# of the GNU General Public License v.2.
60790#
60791# You should have received a copy of the GNU General Public License
60792# along with this program; if not, write to the Free Software Foundation,
60793# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60794
60795srcdir = @srcdir@
60796top_srcdir = @top_srcdir@
60797top_builddir = @top_builddir@
60798
60799INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
60800CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
60801
60802SOURCES = dmeventd_snapshot.c
60803
60804LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
60805LIB_VERSION = $(LIB_VERSION_LVM)
60806
60807include $(top_builddir)/make.tmpl
60808
60809LIBS += -ldevmapper-event-lvm2 -ldevmapper
60810
60811install_lvm2: install_dm_plugin
60812
60813install: install_lvm2
60814\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/snapshot/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000060\013062740170\0027222\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0process_event
60815register_device
60816unregister_device
60817\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/lvm2/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0022644\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003604\013062740170\0025504\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
60818 * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
60819 *
60820 * This file is part of LVM2.
60821 *
60822 * This copyrighted material is made available to anyone wishing to use,
60823 * modify, copy, or redistribute it subject to the terms and conditions
60824 * of the GNU Lesser General Public License v.2.1.
60825 *
60826 * You should have received a copy of the GNU Lesser General Public License
60827 * along with this program; if not, write to the Free Software Foundation,
60828 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60829 */
60830
60831/*
60832 * Wrappers around liblvm2cmd functions for dmeventd plug-ins.
60833 *
60834 * liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
60835 * threads to co-operate in sharing a single instance.
60836 *
60837 * FIXME Either support this properly as a generic liblvm2cmd wrapper or make
60838 * liblvm2cmd thread-safe so this can go away.
60839 */
60840
60841#ifndef _DMEVENTD_LVMWRAP_H
60842#define _DMEVENTD_LVMWRAP_H
60843
60844struct dm_pool;
60845
60846int dmeventd_lvm2_init(void);
60847void dmeventd_lvm2_exit(void);
60848int dmeventd_lvm2_run(const char *cmdline);
60849
60850void dmeventd_lvm2_lock(void);
60851void dmeventd_lvm2_unlock(void);
60852
60853struct dm_pool *dmeventd_lvm2_pool(void);
60854
60855int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
60856 const char *cmd, const char *device);
60857
60858#define dmeventd_lvm2_run_with_lock(cmdline) \
60859 ({\
60860 int rc;\
60861 dmeventd_lvm2_lock();\
60862 rc = dmeventd_lvm2_run(cmdline);\
60863 dmeventd_lvm2_unlock();\
60864 rc;\
60865 })
60866
60867#define dmeventd_lvm2_init_with_pool(name, st) \
60868 ({\
60869 struct dm_pool *mem;\
60870 st = NULL;\
60871 if (dmeventd_lvm2_init()) {\
60872 if ((mem = dm_pool_create(name, 2048)) &&\
60873 (st = dm_pool_zalloc(mem, sizeof(*st))))\
60874 st->mem = mem;\
60875 else {\
60876 if (mem)\
60877 dm_pool_destroy(mem);\
60878 dmeventd_lvm2_exit();\
60879 }\
60880 }\
60881 st;\
60882 })
60883
60884#define dmeventd_lvm2_exit_with_pool(pool) \
60885 do {\
60886 dm_pool_destroy(pool->mem);\
60887 dmeventd_lvm2_exit();\
60888 } while(0)
60889
60890#endif /* _DMEVENTD_LVMWRAP_H */
60891\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/lvm2/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001531\013062740170\0024711\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
60892# Copyright (C) 2010-2014 Red Hat, Inc. All rights reserved.
60893#
60894# This file is part of LVM2.
60895#
60896# This copyrighted material is made available to anyone wishing to use,
60897# modify, copy, or redistribute it subject to the terms and conditions
60898# of the GNU General Public License v.2.
60899#
60900# You should have received a copy of the GNU General Public License
60901# along with this program; if not, write to the Free Software Foundation,
60902# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60903
60904srcdir = @srcdir@
60905top_srcdir = @top_srcdir@
60906top_builddir = @top_builddir@
60907
60908CLDFLAGS += -L$(top_builddir)/tools
60909
60910SOURCES = dmeventd_lvm.c
60911
60912LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX)
60913LIB_VERSION = $(LIB_VERSION_LVM)
60914
60915include $(top_builddir)/make.tmpl
60916
60917LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS)
60918
60919install_lvm2: install_lib_shared
60920
60921install: install_lvm2
60922\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/lvm2/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000211\013062740170\0026241\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dmeventd_lvm2_init
60923dmeventd_lvm2_exit
60924dmeventd_lvm2_lock
60925dmeventd_lvm2_unlock
60926dmeventd_lvm2_pool
60927dmeventd_lvm2_run
60928dmeventd_lvm2_command
60929\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006475\013062740170\0025510\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
60930 * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
60931 *
60932 * This file is part of LVM2.
60933 *
60934 * This copyrighted material is made available to anyone wishing to use,
60935 * modify, copy, or redistribute it subject to the terms and conditions
60936 * of the GNU Lesser General Public License v.2.1.
60937 *
60938 * You should have received a copy of the GNU Lesser General Public License
60939 * along with this program; if not, write to the Free Software Foundation,
60940 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60941 */
60942
60943#include "lib.h"
60944#include "dmeventd_lvm.h"
60945#include "libdevmapper-event.h"
60946#include "lvm2cmd.h"
60947
60948#include <pthread.h>
60949
60950/*
60951 * register_device() is called first and performs initialisation.
60952 * Only one device may be registered or unregistered at a time.
60953 */
60954static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
60955
60956/*
60957 * Number of active registrations.
60958 */
60959static int _register_count = 0;
60960static struct dm_pool *_mem_pool = NULL;
60961static void *_lvm_handle = NULL;
60962
60963DM_EVENT_LOG_FN("#lvm")
60964
60965static void _lvm2_print_log(int level, const char *file, int line,
60966 int dm_errno_or_class, const char *msg)
60967{
60968 print_log(level, file, line, dm_errno_or_class, "%s", msg);
60969}
60970
60971/*
60972 * Currently only one event can be processed at a time.
60973 */
60974static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
60975
60976void dmeventd_lvm2_lock(void)
60977{
60978 pthread_mutex_lock(&_event_mutex);
60979}
60980
60981void dmeventd_lvm2_unlock(void)
60982{
60983 pthread_mutex_unlock(&_event_mutex);
60984}
60985
60986int dmeventd_lvm2_init(void)
60987{
60988 int r = 0;
60989
60990 pthread_mutex_lock(&_register_mutex);
60991
60992 if (!_lvm_handle) {
60993 lvm2_log_fn(_lvm2_print_log);
60994
60995 if (!(_lvm_handle = lvm2_init()))
60996 goto out;
60997
60998 /*
60999 * Need some space for allocations. 1024 should be more
61000 * than enough for what we need (device mapper name splitting)
61001 */
61002 if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024))) {
61003 lvm2_exit(_lvm_handle);
61004 _lvm_handle = NULL;
61005 goto out;
61006 }
61007
61008 lvm2_disable_dmeventd_monitoring(_lvm_handle);
61009 /* FIXME Temporary: move to dmeventd core */
61010 lvm2_run(_lvm_handle, "_memlock_inc");
61011 log_debug("lvm plugin initilized.");
61012 }
61013
61014 _register_count++;
61015 r = 1;
61016
61017out:
61018 pthread_mutex_unlock(&_register_mutex);
61019 return r;
61020}
61021
61022void dmeventd_lvm2_exit(void)
61023{
61024 pthread_mutex_lock(&_register_mutex);
61025
61026 if (!--_register_count) {
61027 log_debug("lvm plugin shuting down.");
61028 lvm2_run(_lvm_handle, "_memlock_dec");
61029 dm_pool_destroy(_mem_pool);
61030 _mem_pool = NULL;
61031 lvm2_exit(_lvm_handle);
61032 _lvm_handle = NULL;
61033 log_debug("lvm plugin exited.");
61034 }
61035
61036 pthread_mutex_unlock(&_register_mutex);
61037}
61038
61039struct dm_pool *dmeventd_lvm2_pool(void)
61040{
61041 return _mem_pool;
61042}
61043
61044int dmeventd_lvm2_run(const char *cmdline)
61045{
61046 return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
61047}
61048
61049int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
61050 const char *cmd, const char *device)
61051{
61052 char *vg = NULL, *lv = NULL, *layer;
61053 int r;
61054
61055 if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
61056 log_error("Unable to determine VG name from %s.",
61057 device);
61058 return 0;
61059 }
61060
61061 /* strip off the mirror component designations */
61062 if ((layer = strstr(lv, "_mimagetmp")) ||
61063 (layer = strstr(lv, "_mlog")))
61064 *layer = '\0';
61065
61066 r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
61067
61068 dm_pool_free(mem, vg);
61069
61070 if (r < 0) {
61071 log_error("Unable to form LVM command. (too long).");
61072 return 0;
61073 }
61074
61075 return 1;
61076}
61077\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002022\013062740170\0024025\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
61078# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
61079# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved.
61080#
61081# This file is part of LVM2.
61082#
61083# This copyrighted material is made available to anyone wishing to use,
61084# modify, copy, or redistribute it subject to the terms and conditions
61085# of the GNU General Public License v.2.
61086#
61087# You should have received a copy of the GNU General Public License
61088# along with this program; if not, write to the Free Software Foundation,
61089# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61090
61091srcdir = @srcdir@
61092top_srcdir = @top_srcdir@
61093top_builddir = @top_builddir@
61094
61095SUBDIRS += lvm2
61096
61097ifneq ("@MIRRORS@", "none")
61098 SUBDIRS += mirror
61099endif
61100
61101ifneq ("@SNAPSHOTS@", "none")
61102 SUBDIRS += snapshot
61103endif
61104
61105ifneq ("@RAID@", "none")
61106 SUBDIRS += raid
61107endif
61108
61109ifneq ("@THIN@", "none")
61110 SUBDIRS += thin
61111endif
61112
61113ifeq ($(MAKECMDGOALS),distclean)
61114 SUBDIRS = lvm2 mirror snapshot raid thin
61115endif
61116
61117include $(top_builddir)/make.tmpl
61118
61119snapshot: lvm2
61120mirror: lvm2
61121raid: lvm2
61122thin: lvm2
61123\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/mirror/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0023276\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/mirror/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000060\013062740170\0026675\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0process_event
61124register_device
61125unregister_device
61126\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/mirror/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002123\013062740170\0025341\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
61127# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
61128# Copyright (C) 2004-2005, 2008-2014 Red Hat, Inc. All rights reserved.
61129#
61130# This file is part of LVM2.
61131#
61132# This copyrighted material is made available to anyone wishing to use,
61133# modify, copy, or redistribute it subject to the terms and conditions
61134# of the GNU General Public License v.2.
61135#
61136# You should have received a copy of the GNU General Public License
61137# along with this program; if not, write to the Free Software Foundation,
61138# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61139
61140srcdir = @srcdir@
61141top_srcdir = @top_srcdir@
61142top_builddir = @top_builddir@
61143
61144INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
61145CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
61146
61147SOURCES = dmeventd_mirror.c
61148
61149LIB_NAME = libdevmapper-event-lvm2mirror
61150LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
61151LIB_VERSION = $(LIB_VERSION_LVM)
61152
61153CFLOW_LIST = $(SOURCES)
61154CFLOW_LIST_TARGET = $(LIB_NAME).cflow
61155
61156include $(top_builddir)/make.tmpl
61157
61158LIBS += -ldevmapper-event-lvm2 -ldevmapper
61159
61160install_lvm2: install_dm_plugin
61161
61162install: install_lvm2
61163\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000013403\013062740170\0026643\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
61164 * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
61165 *
61166 * This file is part of LVM2.
61167 *
61168 * This copyrighted material is made available to anyone wishing to use,
61169 * modify, copy, or redistribute it subject to the terms and conditions
61170 * of the GNU Lesser General Public License v.2.1.
61171 *
61172 * You should have received a copy of the GNU Lesser General Public License
61173 * along with this program; if not, write to the Free Software Foundation,
61174 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61175 */
61176
61177#include "lib.h"
61178#include "libdevmapper-event.h"
61179#include "dmeventd_lvm.h"
61180#include "activate.h" /* For TARGET_NAME* */
61181
61182/* FIXME Reformat to 80 char lines. */
61183
61184#define ME_IGNORE 0
61185#define ME_INSYNC 1
61186#define ME_FAILURE 2
61187
61188struct dso_state {
61189 struct dm_pool *mem;
61190 char cmd_lvscan[512];
61191 char cmd_lvconvert[512];
61192};
61193
61194DM_EVENT_LOG_FN("mirr")
61195
61196static void _process_status_code(dm_status_mirror_health_t health,
61197 uint32_t major, uint32_t minor,
61198 const char *dev_type, int *r)
61199{
61200 /*
61201 * A => Alive - No failures
61202 * D => Dead - A write failure occurred leaving mirror out-of-sync
61203 * F => Flush failed.
61204 * S => Sync - A sychronization failure occurred, mirror out-of-sync
61205 * R => Read - A read failure occurred, mirror data unaffected
61206 * U => Unclassified failure (bug)
61207 */
61208 switch (health) {
61209 case DM_STATUS_MIRROR_ALIVE:
61210 return;
61211 case DM_STATUS_MIRROR_FLUSH_FAILED:
61212 log_error("%s device %u:%u flush failed.",
61213 dev_type, major, minor);
61214 *r = ME_FAILURE;
61215 break;
61216 case DM_STATUS_MIRROR_SYNC_FAILED:
61217 log_error("%s device %u:%u sync failed.",
61218 dev_type, major, minor);
61219 break;
61220 case DM_STATUS_MIRROR_READ_FAILED:
61221 log_error("%s device %u:%u read failed.",
61222 dev_type, major, minor);
61223 break;
61224 default:
61225 log_error("%s device %u:%u has failed (%c).",
61226 dev_type, major, minor, (char)health);
61227 *r = ME_FAILURE;
61228 break;
61229 }
61230}
61231
61232static int _get_mirror_event(struct dso_state *state, char *params)
61233{
61234 int r = ME_INSYNC;
61235 unsigned i;
61236 struct dm_status_mirror *ms;
61237
61238 if (!dm_get_status_mirror(state->mem, params, &ms)) {
61239 log_error("Unable to parse mirror status string.");
61240 return ME_IGNORE;
61241 }
61242
61243 /* Check for bad mirror devices */
61244 for (i = 0; i < ms->dev_count; ++i)
61245 _process_status_code(ms->devs[i].health,
61246 ms->devs[i].major, ms->devs[i].minor,
61247 i ? "Secondary mirror" : "Primary mirror", &r);
61248
61249 /* Check for bad disk log device */
61250 for (i = 0; i < ms->log_count; ++i)
61251 _process_status_code(ms->logs[i].health,
61252 ms->logs[i].major, ms->logs[i].minor,
61253 "Log", &r);
61254
61255 /* Ignore if not in-sync */
61256 if ((r == ME_INSYNC) && (ms->insync_regions != ms->total_regions))
61257 r = ME_IGNORE;
61258
61259 dm_pool_free(state->mem, ms);
61260
61261 return r;
61262}
61263
61264static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert,
61265 const char *device)
61266{
61267 if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
61268 log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
61269
61270 /* if repair goes OK, report success even if lvscan has failed */
61271 if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
61272 log_error("Repair of mirrored device %s failed.", device);
61273 return 0;
61274 }
61275
61276 log_info("Repair of mirrored device %s finished successfully.", device);
61277
61278 return 1;
61279}
61280
61281void process_event(struct dm_task *dmt,
61282 enum dm_event_mask event __attribute__((unused)),
61283 void **user)
61284{
61285 struct dso_state *state = *user;
61286 void *next = NULL;
61287 uint64_t start, length;
61288 char *target_type = NULL;
61289 char *params;
61290 const char *device = dm_task_get_name(dmt);
61291
61292 do {
61293 next = dm_get_next_target(dmt, next, &start, &length,
61294 &target_type, &params);
61295
61296 if (!target_type) {
61297 log_info("%s mapping lost.", device);
61298 continue;
61299 }
61300
61301 if (strcmp(target_type, TARGET_NAME_MIRROR)) {
61302 log_info("%s has unmirrored portion.", device);
61303 continue;
61304 }
61305
61306 switch(_get_mirror_event(state, params)) {
61307 case ME_INSYNC:
61308 /* FIXME: all we really know is that this
61309 _part_ of the device is in sync
61310 Also, this is not an error
61311 */
61312 log_notice("%s is now in-sync.", device);
61313 break;
61314 case ME_FAILURE:
61315 log_error("Device failure in %s.", device);
61316 if (!_remove_failed_devices(state->cmd_lvscan,
61317 state->cmd_lvconvert,
61318 device))
61319 /* FIXME Why are all the error return codes unused? Get rid of them? */
61320 log_error("Failed to remove faulty devices in %s.",
61321 device);
61322 /* Should check before warning user that device is now linear
61323 else
61324 log_notice("%s is now a linear device.",
61325 device);
61326 */
61327 break;
61328 case ME_IGNORE:
61329 break;
61330 default:
61331 /* FIXME Provide value then! */
61332 log_warn("WARNING: %s received unknown event.", device);
61333 }
61334 } while (next);
61335}
61336
61337int register_device(const char *device,
61338 const char *uuid __attribute__((unused)),
61339 int major __attribute__((unused)),
61340 int minor __attribute__((unused)),
61341 void **user)
61342{
61343 struct dso_state *state;
61344
61345 if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
61346 goto_bad;
61347
61348 if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
61349 "lvscan --cache", device)) {
61350 dmeventd_lvm2_exit_with_pool(state);
61351 goto_bad;
61352 }
61353
61354 if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
61355 "lvconvert --repair --use-policies", device)) {
61356 dmeventd_lvm2_exit_with_pool(state);
61357 goto_bad;
61358 }
61359
61360 *user = state;
61361
61362 log_info("Monitoring mirror device %s for events.", device);
61363
61364 return 1;
61365bad:
61366 log_error("Failed to monitor mirror %s.", device);
61367
61368 return 0;
61369}
61370
61371int unregister_device(const char *device,
61372 const char *uuid __attribute__((unused)),
61373 int major __attribute__((unused)),
61374 int minor __attribute__((unused)),
61375 void **user)
61376{
61377 struct dso_state *state = *user;
61378
61379 dmeventd_lvm2_exit_with_pool(state);
61380 log_info("No longer monitoring mirror device %s for events.",
61381 device);
61382
61383 return 1;
61384}
61385\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/raid/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0022703\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/raid/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000060\013062740170\0026302\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0process_event
61386register_device
61387unregister_device
61388\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/raid/dmeventd_raid.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010552\013062740170\0025657\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
61389 * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
61390 *
61391 * This file is part of LVM2.
61392 *
61393 * This copyrighted material is made available to anyone wishing to use,
61394 * modify, copy, or redistribute it subject to the terms and conditions
61395 * of the GNU Lesser General Public License v.2.1.
61396 *
61397 * You should have received a copy of the GNU Lesser General Public License
61398 * along with this program; if not, write to the Free Software Foundation,
61399 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61400 */
61401
61402#include "lib.h"
61403#include "defaults.h"
61404#include "dmeventd_lvm.h"
61405#include "libdevmapper-event.h"
61406
61407/* Hold enough elements for the mximum number of RAID images */
61408#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
61409
61410struct dso_state {
61411 struct dm_pool *mem;
61412 char cmd_lvscan[512];
61413 char cmd_lvconvert[512];
61414 uint64_t raid_devs[RAID_DEVS_ELEMS];
61415 int failed;
61416 int warned;
61417};
61418
61419DM_EVENT_LOG_FN("raid")
61420
61421/* FIXME Reformat to 80 char lines. */
61422
61423static int _process_raid_event(struct dso_state *state, char *params, const char *device)
61424{
61425 struct dm_status_raid *status;
61426 const char *d;
61427 int dead = 0, r = 1;
61428
61429 if (!dm_get_status_raid(state->mem, params, &status)) {
61430 log_error("Failed to process status line for %s.", device);
61431 return 0;
61432 }
61433
61434 d = status->dev_health;
61435 while ((d = strchr(d, 'D'))) {
61436 uint32_t dev = (uint32_t)(d - status->dev_health);
61437
61438 if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64))))
61439 log_error("Device #%u of %s array, %s, has failed.",
61440 dev, status->raid_type, device);
61441
61442 state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64));
61443 d++;
61444 dead = 1;
61445 }
61446
61447 if (dead) {
61448 if (status->insync_regions < status->total_regions) {
61449 if (!state->warned)
61450 log_warn("WARNING: waiting for resynchronization to finish "
61451 "before initiating repair on RAID device %s.", device);
61452
61453 state->warned = 1;
61454 goto out; /* Not yet done syncing with accessible devices */
61455 }
61456
61457 if (state->failed)
61458 goto out; /* already reported */
61459
61460 state->failed = 1;
61461 if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
61462 log_warn("WARNING: Re-scan of RAID device %s failed.", device);
61463
61464 /* if repair goes OK, report success even if lvscan has failed */
61465 if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
61466 log_error("Repair of RAID device %s failed.", device);
61467 r = 0;
61468 }
61469 } else {
61470 state->failed = 0;
61471 log_info("%s array, %s, is %s in-sync.",
61472 status->raid_type, device,
61473 (status->insync_regions == status->total_regions) ? "now" : "not");
61474 }
61475out:
61476 dm_pool_free(state->mem, status);
61477
61478 return r;
61479}
61480
61481void process_event(struct dm_task *dmt,
61482 enum dm_event_mask event __attribute__((unused)),
61483 void **user)
61484{
61485 struct dso_state *state = *user;
61486 void *next = NULL;
61487 uint64_t start, length;
61488 char *target_type = NULL;
61489 char *params;
61490 const char *device = dm_task_get_name(dmt);
61491
61492 do {
61493 next = dm_get_next_target(dmt, next, &start, &length,
61494 &target_type, &params);
61495
61496 if (!target_type) {
61497 log_info("%s mapping lost.", device);
61498 continue;
61499 }
61500
61501 if (strcmp(target_type, "raid")) {
61502 log_info("%s has non-raid portion.", device);
61503 continue;
61504 }
61505
61506 if (!_process_raid_event(state, params, device))
61507 log_error("Failed to process event for %s.",
61508 device);
61509 } while (next);
61510}
61511
61512int register_device(const char *device,
61513 const char *uuid __attribute__((unused)),
61514 int major __attribute__((unused)),
61515 int minor __attribute__((unused)),
61516 void **user)
61517{
61518 struct dso_state *state;
61519
61520 if (!dmeventd_lvm2_init_with_pool("raid_state", state))
61521 goto_bad;
61522
61523 if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
61524 "lvscan --cache", device) ||
61525 !dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
61526 "lvconvert --config devices{ignore_suspended_devices=1} "
61527 "--repair --use-policies", device)) {
61528 dmeventd_lvm2_exit_with_pool(state);
61529 goto_bad;
61530 }
61531
61532 *user = state;
61533
61534 log_info("Monitoring RAID device %s for events.", device);
61535
61536 return 1;
61537bad:
61538 log_error("Failed to monitor RAID %s.", device);
61539
61540 return 0;
61541}
61542
61543int unregister_device(const char *device,
61544 const char *uuid __attribute__((unused)),
61545 int major __attribute__((unused)),
61546 int minor __attribute__((unused)),
61547 void **user)
61548{
61549 struct dso_state *state = *user;
61550
61551 dmeventd_lvm2_exit_with_pool(state);
61552 log_info("No longer monitoring RAID device %s for events.",
61553 device);
61554
61555 return 1;
61556}
61557\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/raid/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001776\013062740170\0024763\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
61558# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
61559#
61560# This file is part of LVM2.
61561#
61562# This copyrighted material is made available to anyone wishing to use,
61563# modify, copy, or redistribute it subject to the terms and conditions
61564# of the GNU General Public License v.2.
61565#
61566# You should have received a copy of the GNU General Public License
61567# along with this program; if not, write to the Free Software Foundation,
61568# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61569
61570srcdir = @srcdir@
61571top_srcdir = @top_srcdir@
61572top_builddir = @top_builddir@
61573
61574INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
61575CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
61576
61577SOURCES = dmeventd_raid.c
61578
61579LIB_NAME = libdevmapper-event-lvm2raid
61580LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
61581LIB_VERSION = $(LIB_VERSION_LVM)
61582
61583CFLOW_LIST = $(SOURCES)
61584CFLOW_LIST_TARGET = $(LIB_NAME).cflow
61585
61586include $(top_builddir)/make.tmpl
61587
61588LIBS += -ldevmapper-event-lvm2 -ldevmapper
61589
61590install_lvm2: install_dm_plugin
61591
61592install: install_lvm2
61593\0\0LVM2.2.02.168/daemons/dmeventd/plugins/thin/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0022726\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/thin/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001776\013062740170\0025006\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
61594# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
61595#
61596# This file is part of LVM2.
61597#
61598# This copyrighted material is made available to anyone wishing to use,
61599# modify, copy, or redistribute it subject to the terms and conditions
61600# of the GNU General Public License v.2.
61601#
61602# You should have received a copy of the GNU General Public License
61603# along with this program; if not, write to the Free Software Foundation,
61604# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61605
61606srcdir = @srcdir@
61607top_srcdir = @top_srcdir@
61608top_builddir = @top_builddir@
61609
61610INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
61611CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
61612
61613SOURCES = dmeventd_thin.c
61614
61615LIB_NAME = libdevmapper-event-lvm2thin
61616LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
61617LIB_VERSION = $(LIB_VERSION_LVM)
61618
61619CFLOW_LIST = $(SOURCES)
61620CFLOW_LIST_TARGET = $(LIB_NAME).cflow
61621
61622include $(top_builddir)/make.tmpl
61623
61624LIBS += -ldevmapper-event-lvm2 -ldevmapper
61625
61626install_lvm2: install_dm_plugin
61627
61628install: install_lvm2
61629\0\0LVM2.2.02.168/daemons/dmeventd/plugins/thin/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000060\013062740170\0026325\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0process_event
61630register_device
61631unregister_device
61632\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/plugins/thin/dmeventd_thin.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000026746\013062740170\0025741\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
61633 * Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved.
61634 *
61635 * This file is part of LVM2.
61636 *
61637 * This copyrighted material is made available to anyone wishing to use,
61638 * modify, copy, or redistribute it subject to the terms and conditions
61639 * of the GNU Lesser General Public License v.2.1.
61640 *
61641 * You should have received a copy of the GNU Lesser General Public License
61642 * along with this program; if not, write to the Free Software Foundation,
61643 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
61644 */
61645
61646#include "lib.h" /* using here lvm log */
61647#include "dmeventd_lvm.h"
61648#include "libdevmapper-event.h"
61649
61650#include <sys/wait.h>
61651#include <stdarg.h>
61652#include <pthread.h>
61653
61654/* TODO - move this mountinfo code into library to be reusable */
61655#ifdef __linux__
61656# include "kdev_t.h"
61657#else
61658# define MAJOR(x) major((x))
61659# define MINOR(x) minor((x))
61660#endif
61661
61662/* First warning when thin data or metadata is 80% full. */
61663#define WARNING_THRESH (DM_PERCENT_1 * 80)
61664/* Umount thin LVs when thin data or metadata LV is >=
61665 * and lvextend --use-policies has failed. */
61666#define UMOUNT_THRESH (DM_PERCENT_1 * 95)
61667/* Run a check every 5%. */
61668#define CHECK_STEP (DM_PERCENT_1 * 5)
61669/* Do not bother checking thin data or metadata is less than 50% full. */
61670#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
61671
61672#define UMOUNT_COMMAND "/bin/umount"
61673
61674#define MAX_FAILS (10)
61675
61676#define THIN_DEBUG 0
61677
61678struct dso_state {
61679 struct dm_pool *mem;
61680 int metadata_percent_check;
61681 int data_percent_check;
61682 uint64_t known_metadata_size;
61683 uint64_t known_data_size;
61684 unsigned fails;
61685 char cmd_str[1024];
61686};
61687
61688DM_EVENT_LOG_FN("thin")
61689
61690#define UUID_PREFIX "LVM-"
61691
61692/* Figure out device UUID has LVM- prefix and is OPEN */
61693static int _has_unmountable_prefix(int major, int minor)
61694{
61695 struct dm_task *dmt;
61696 struct dm_info info;
61697 const char *uuid;
61698 int r = 0;
61699
61700 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
61701 return_0;
61702
61703 if (!dm_task_set_major_minor(dmt, major, minor, 1))
61704 goto_out;
61705
61706 if (!dm_task_no_flush(dmt))
61707 stack;
61708
61709 if (!dm_task_run(dmt))
61710 goto out;
61711
61712 if (!dm_task_get_info(dmt, &info))
61713 goto out;
61714
61715 if (!info.exists || !info.open_count)
61716 goto out; /* Not open -> not mounted */
61717
61718 if (!(uuid = dm_task_get_uuid(dmt)))
61719 goto out;
61720
61721 /* Check it's public mountable LV
61722 * has prefix LVM- and UUID size is 68 chars */
61723 if (memcmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) ||
61724 strlen(uuid) != 68)
61725 goto out;
61726
61727#if THIN_DEBUG
61728 log_debug("Found logical volume %s (%u:%u).", uuid, major, minor);
61729#endif
61730 r = 1;
61731out:
61732 dm_task_destroy(dmt);
61733
61734 return r;
61735}
61736
61737/* Get dependencies for device, and try to find matching device */
61738static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
61739{
61740 struct dm_task *dmt;
61741 const struct dm_deps *deps;
61742 struct dm_info info;
61743 int major, minor;
61744 int r = 0;
61745
61746 if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
61747 return 0;
61748
61749 if (!dm_task_set_name(dmt, name))
61750 goto out;
61751
61752 if (!dm_task_no_open_count(dmt))
61753 goto out;
61754
61755 if (!dm_task_run(dmt))
61756 goto out;
61757
61758 if (!dm_task_get_info(dmt, &info))
61759 goto out;
61760
61761 if (!(deps = dm_task_get_deps(dmt)))
61762 goto out;
61763
61764 if (!info.exists || deps->count != 1)
61765 goto out;
61766
61767 major = (int) MAJOR(deps->device[0]);
61768 minor = (int) MINOR(deps->device[0]);
61769 if ((major != tp_major) || (minor != tp_minor))
61770 goto out;
61771
61772 *dev_minor = info.minor;
61773
61774 if (!_has_unmountable_prefix(major, info.minor))
61775 goto out;
61776
61777#if THIN_DEBUG
61778 {
61779 char dev_name[PATH_MAX];
61780 if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name)))
61781 log_debug("Found %s (%u:%u) depends on %s.",
61782 name, major, *dev_minor, dev_name);
61783 }
61784#endif
61785 r = 1;
61786out:
61787 dm_task_destroy(dmt);
61788
61789 return r;
61790}
61791
61792/* Get all active devices */
61793static int _find_all_devs(dm_bitset_t bs, int tp_major, int tp_minor)
61794{
61795 struct dm_task *dmt;
61796 struct dm_names *names;
61797 unsigned next = 0;
61798 int minor, r = 1;
61799
61800 if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
61801 return 0;
61802
61803 if (!dm_task_run(dmt)) {
61804 r = 0;
61805 goto out;
61806 }
61807
61808 if (!(names = dm_task_get_names(dmt))) {
61809 r = 0;
61810 goto out;
61811 }
61812
61813 if (!names->dev)
61814 goto out;
61815
61816 do {
61817 names = (struct dm_names *)((char *) names + next);
61818 if (_has_deps(names->name, tp_major, tp_minor, &minor))
61819 dm_bit_set(bs, minor);
61820 next = names->next;
61821 } while (next);
61822
61823out:
61824 dm_task_destroy(dmt);
61825
61826 return r;
61827}
61828
61829static int _run(const char *cmd, ...)
61830{
61831 va_list ap;
61832 int argc = 1; /* for argv[0], i.e. cmd */
61833 int i = 0;
61834 const char **argv;
61835 pid_t pid = fork();
61836 int status;
61837
61838 if (pid == 0) { /* child */
61839 va_start(ap, cmd);
61840 while (va_arg(ap, const char *))
61841 ++argc;
61842 va_end(ap);
61843
61844 /* + 1 for the terminating NULL */
61845 argv = alloca(sizeof(const char *) * (argc + 1));
61846
61847 argv[0] = cmd;
61848 va_start(ap, cmd);
61849 while ((argv[++i] = va_arg(ap, const char *)));
61850 va_end(ap);
61851
61852 execvp(cmd, (char **)argv);
61853 log_sys_error("exec", cmd);
61854 exit(127);
61855 }
61856
61857 if (pid > 0) { /* parent */
61858 if (waitpid(pid, &status, 0) != pid)
61859 return 0; /* waitpid failed */
61860 if (!WIFEXITED(status) || WEXITSTATUS(status))
61861 return 0; /* the child failed */
61862 }
61863
61864 if (pid < 0)
61865 return 0; /* fork failed */
61866
61867 return 1; /* all good */
61868}
61869
61870struct mountinfo_s {
61871 const char *device;
61872 struct dm_info info;
61873 dm_bitset_t minors; /* Bitset for active thin pool minors */
61874};
61875
61876static int _umount_device(char *buffer, unsigned major, unsigned minor,
61877 char *target, void *cb_data)
61878{
61879 struct mountinfo_s *data = cb_data;
61880 char *words[10];
61881
61882 if ((major == data->info.major) && dm_bit(data->minors, minor)) {
61883 if (dm_split_words(buffer, DM_ARRAY_SIZE(words), 0, words) < DM_ARRAY_SIZE(words))
61884 words[9] = NULL; /* just don't show device name */
61885 log_info("Unmounting thin %s (%d:%d) of thin pool %s (%u:%u) from mount point \"%s\".",
61886 words[9] ? : "", major, minor, data->device,
61887 data->info.major, data->info.minor,
61888 target);
61889 if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
61890 log_error("Failed to lazy umount thin %s (%d:%d) from %s: %s.",
61891 words[9], major, minor, target, strerror(errno));
61892 }
61893
61894 return 1;
61895}
61896
61897/*
61898 * Find all thin pool LV users and try to umount them.
61899 * TODO: work with read-only thin pool support
61900 */
61901static void _umount(struct dm_task *dmt)
61902{
61903 /* TODO: Convert to use hash to reduce memory usage */
61904 static const size_t MINORS = (1U << 20); /* 20 bit */
61905 struct mountinfo_s data = { NULL };
61906
61907 if (!dm_task_get_info(dmt, &data.info))
61908 return;
61909
61910 data.device = dm_task_get_name(dmt);
61911
61912 if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
61913 log_error("Failed to allocate bitset. Not unmounting %s.", data.device);
61914 goto out;
61915 }
61916
61917 if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
61918 log_error("Failed to detect mounted volumes for %s.", data.device);
61919 goto out;
61920 }
61921
61922 if (!dm_mountinfo_read(_umount_device, &data)) {
61923 log_error("Could not parse mountinfo file.");
61924 goto out;
61925 }
61926
61927out:
61928 if (data.minors)
61929 dm_bitset_destroy(data.minors);
61930}
61931
61932static int _use_policy(struct dm_task *dmt, struct dso_state *state)
61933{
61934#if THIN_DEBUG
61935 log_debug("dmeventd executes: %s.", state->cmd_str);
61936#endif
61937 if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
61938 log_error("Failed to extend thin pool %s.",
61939 dm_task_get_name(dmt));
61940 state->fails++;
61941 return 0;
61942 }
61943
61944 state->fails = 0;
61945 return 1;
61946}
61947
61948void process_event(struct dm_task *dmt,
61949 enum dm_event_mask event __attribute__((unused)),
61950 void **user)
61951{
61952 const char *device = dm_task_get_name(dmt);
61953 int percent;
61954 struct dso_state *state = *user;
61955 struct dm_status_thin_pool *tps = NULL;
61956 void *next = NULL;
61957 uint64_t start, length;
61958 char *target_type = NULL;
61959 char *params;
61960 int needs_policy = 0;
61961 int needs_umount = 0;
61962
61963#if THIN_DEBUG
61964 log_debug("Watch for tp-data:%.2f%% tp-metadata:%.2f%%.",
61965 dm_percent_to_float(state->data_percent_check),
61966 dm_percent_to_float(state->metadata_percent_check));
61967#endif
61968
61969#if 0
61970 /* No longer monitoring, waiting for remove */
61971 if (!state->meta_percent_check && !state->data_percent_check)
61972 return;
61973#endif
61974 if (event & DM_EVENT_DEVICE_ERROR) {
61975 /* Error -> no need to check and do instant resize */
61976 if (_use_policy(dmt, state))
61977 goto out;
61978
61979 stack;
61980 }
61981
61982 dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
61983
61984 if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
61985 log_error("Invalid target type.");
61986 goto out;
61987 }
61988
61989 if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
61990 log_error("Failed to parse status.");
61991 needs_umount = 1;
61992 goto out;
61993 }
61994
61995#if THIN_DEBUG
61996 log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
61997 FMTu64 "/" FMTu64 ".",
61998 tps->used_metadata_blocks, tps->total_metadata_blocks,
61999 tps->used_data_blocks, tps->total_data_blocks);
62000#endif
62001
62002 /* Thin pool size had changed. Clear the threshold. */
62003 if (state->known_metadata_size != tps->total_metadata_blocks) {
62004 state->metadata_percent_check = CHECK_MINIMUM;
62005 state->known_metadata_size = tps->total_metadata_blocks;
62006 }
62007
62008 if (state->known_data_size != tps->total_data_blocks) {
62009 state->data_percent_check = CHECK_MINIMUM;
62010 state->known_data_size = tps->total_data_blocks;
62011 }
62012
62013 percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
62014 if (percent >= state->metadata_percent_check) {
62015 /*
62016 * Usage has raised more than CHECK_STEP since the last
62017 * time. Run actions.
62018 */
62019 state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
62020
62021 /* FIXME: extension of metadata needs to be written! */
62022 if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
62023 log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
62024 device, dm_percent_to_float(percent));
62025 needs_policy = 1;
62026
62027 if (percent >= UMOUNT_THRESH)
62028 needs_umount = 1;
62029 }
62030
62031 percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
62032 if (percent >= state->data_percent_check) {
62033 /*
62034 * Usage has raised more than CHECK_STEP since
62035 * the last time. Run actions.
62036 */
62037 state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
62038
62039 if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
62040 log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
62041 device, dm_percent_to_float(percent));
62042 needs_policy = 1;
62043
62044 if (percent >= UMOUNT_THRESH)
62045 needs_umount = 1;
62046 }
62047
62048 if (needs_policy &&
62049 _use_policy(dmt, state))
62050 needs_umount = 0; /* No umount when command was successful */
62051out:
62052 if (needs_umount) {
62053 _umount(dmt);
62054 /* Until something changes, do not retry any more actions */
62055 state->data_percent_check = state->metadata_percent_check = (DM_PERCENT_1 * 101);
62056 }
62057
62058 if (tps)
62059 dm_pool_free(state->mem, tps);
62060
62061 if (state->fails >= MAX_FAILS) {
62062 log_warn("WARNING: Dropping monitoring of %s. "
62063 "lvm2 command fails too often (%u times in row).",
62064 device, state->fails);
62065 pthread_kill(pthread_self(), SIGALRM);
62066 }
62067}
62068
62069int register_device(const char *device,
62070 const char *uuid __attribute__((unused)),
62071 int major __attribute__((unused)),
62072 int minor __attribute__((unused)),
62073 void **user)
62074{
62075 struct dso_state *state;
62076
62077 if (!dmeventd_lvm2_init_with_pool("thin_pool_state", state))
62078 goto_bad;
62079
62080 if (!dmeventd_lvm2_command(state->mem, state->cmd_str,
62081 sizeof(state->cmd_str),
62082 "lvextend --use-policies",
62083 device)) {
62084 dmeventd_lvm2_exit_with_pool(state);
62085 goto_bad;
62086 }
62087
62088 state->metadata_percent_check = CHECK_MINIMUM;
62089 state->data_percent_check = CHECK_MINIMUM;
62090 *user = state;
62091
62092 log_info("Monitoring thin pool %s.", device);
62093
62094 return 1;
62095bad:
62096 log_error("Failed to monitor thin pool %s.", device);
62097
62098 return 0;
62099}
62100
62101int unregister_device(const char *device,
62102 const char *uuid __attribute__((unused)),
62103 int major __attribute__((unused)),
62104 int minor __attribute__((unused)),
62105 void **user)
62106{
62107 struct dso_state *state = *user;
62108
62109 dmeventd_lvm2_exit_with_pool(state);
62110 log_info("No longer monitoring thin pool %s.", device);
62111
62112 return 1;
62113}
62114\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/dmeventd.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000004607\013062740170\0022271\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
62115 * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
62116 *
62117 * This file is part of the device-mapper userspace tools.
62118 *
62119 * This copyrighted material is made available to anyone wishing to use,
62120 * modify, copy, or redistribute it subject to the terms and conditions
62121 * of the GNU Lesser General Public License v.2.1.
62122 *
62123 * You should have received a copy of the GNU Lesser General Public License
62124 * along with this program; if not, write to the Free Software Foundation,
62125 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
62126 */
62127
62128#ifndef __DMEVENTD_DOT_H__
62129#define __DMEVENTD_DOT_H__
62130
62131/* FIXME This stuff must be configurable. */
62132
62133#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
62134#define DM_EVENT_FIFO_SERVER DEFAULT_DM_RUN_DIR "/dmeventd-server"
62135
62136#define DM_EVENT_DEFAULT_TIMEOUT 10
62137
62138/* Commands for the daemon passed in the message below. */
62139enum dm_event_command {
62140 DM_EVENT_CMD_ACTIVE = 1,
62141 DM_EVENT_CMD_REGISTER_FOR_EVENT,
62142 DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
62143 DM_EVENT_CMD_GET_REGISTERED_DEVICE,
62144 DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
62145 DM_EVENT_CMD_SET_TIMEOUT,
62146 DM_EVENT_CMD_GET_TIMEOUT,
62147 DM_EVENT_CMD_HELLO,
62148 DM_EVENT_CMD_DIE,
62149 DM_EVENT_CMD_GET_STATUS,
62150 DM_EVENT_CMD_GET_PARAMETERS,
62151};
62152
62153/* Message passed between client and daemon. */
62154struct dm_event_daemon_message {
62155 uint32_t cmd;
62156 uint32_t size;
62157 char *data;
62158};
62159
62160/* FIXME Is this meant to be exported? I can't see where the
62161 interface uses it. */
62162/* Fifos for client/daemon communication. */
62163struct dm_event_fifos {
62164 int client;
62165 int server;
62166 const char *client_path;
62167 const char *server_path;
62168};
62169
62170/* EXIT_SUCCESS 0 -- stdlib.h */
62171/* EXIT_FAILURE 1 -- stdlib.h */
62172/* EXIT_LOCKFILE_INUSE 2 -- obsoleted */
62173#define EXIT_DESC_CLOSE_FAILURE 3
62174#define EXIT_DESC_OPEN_FAILURE 4
62175/* EXIT_OPEN_PID_FAILURE 5 -- obsoleted */
62176#define EXIT_FIFO_FAILURE 6
62177#define EXIT_CHDIR_FAILURE 7
62178
62179/* Implemented in libdevmapper-event.c, but not part of public API. */
62180// FIXME misuse of bitmask as enum
62181int daemon_talk(struct dm_event_fifos *fifos,
62182 struct dm_event_daemon_message *msg, int cmd,
62183 const char *dso_name, const char *dev_name,
62184 enum dm_event_mask evmask, uint32_t timeout);
62185int init_fifos(struct dm_event_fifos *fifos);
62186void fini_fifos(struct dm_event_fifos *fifos);
62187int dm_event_get_version(struct dm_event_fifos *fifos, int *version);
62188
62189#endif /* __DMEVENTD_DOT_H__ */
62190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/libdevmapper-event.pc.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000407\013062740170\0025026\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0prefix=@prefix@
62191exec_prefix=@exec_prefix@
62192libdir=@libdir@
62193includedir=@includedir@
62194
62195Name: devmapper-event
62196Description: device-mapper event library
62197Version: @DM_LIB_PATCHLEVEL@
62198Cflags: -I${includedir}
62199Libs: -L${libdir} -ldevmapper-event
62200Requires.private: devmapper
62201\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/dmeventd.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000156411\013062740170\0022265\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
62202 * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
62203 *
62204 * This file is part of the device-mapper userspace tools.
62205 *
62206 * This copyrighted material is made available to anyone wishing to use,
62207 * modify, copy, or redistribute it subject to the terms and conditions
62208 * of the GNU Lesser General Public License v.2.1.
62209 *
62210 * You should have received a copy of the GNU Lesser General Public License
62211 * along with this program; if not, write to the Free Software Foundation,
62212 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
62213 */
62214
62215/*
62216 * dmeventd - dm event daemon to monitor active mapped devices
62217 */
62218
62219#include "dm-logging.h"
62220
62221#include "libdevmapper-event.h"
62222#include "dmeventd.h"
62223
62224#include "tool.h"
62225
62226#include <dlfcn.h>
62227#include <pthread.h>
62228#include <sys/file.h>
62229#include <sys/stat.h>
62230#include <sys/wait.h>
62231#include <sys/time.h>
62232#include <sys/resource.h>
62233#include <signal.h>
62234#include <arpa/inet.h> /* for htonl, ntohl */
62235#include <fcntl.h> /* for musl libc */
62236
62237#ifdef __linux__
62238/*
62239 * Kernel version 2.6.36 and higher has
62240 * new OOM killer adjustment interface.
62241 */
62242# define OOM_ADJ_FILE_OLD "/proc/self/oom_adj"
62243# define OOM_ADJ_FILE "/proc/self/oom_score_adj"
62244
62245/* From linux/oom.h */
62246/* Old interface */
62247# define OOM_DISABLE (-17)
62248# define OOM_ADJUST_MIN (-16)
62249/* New interface */
62250# define OOM_SCORE_ADJ_MIN (-1000)
62251
62252/* Systemd on-demand activation support */
62253# define SD_RUNTIME_UNIT_FILE_DIR DEFAULT_DM_RUN_DIR "/systemd/system/"
62254# define SD_ACTIVATION_ENV_VAR_NAME "SD_ACTIVATION"
62255# define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
62256# define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
62257# define SD_LISTEN_FDS_START 3
62258# define SD_FD_FIFO_SERVER SD_LISTEN_FDS_START
62259# define SD_FD_FIFO_CLIENT (SD_LISTEN_FDS_START + 1)
62260
62261#endif
62262
62263#include <syslog.h>
62264
62265static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
62266
62267/* List (un)link macros. */
62268#define LINK(x, head) dm_list_add(head, &(x)->list)
62269#define LINK_DSO(dso) LINK(dso, &_dso_registry)
62270#define LINK_THREAD(thread) LINK(thread, &_thread_registry)
62271
62272#define UNLINK(x) dm_list_del(&(x)->list)
62273#define UNLINK_DSO(x) UNLINK(x)
62274#define UNLINK_THREAD(x) UNLINK(x)
62275
62276#define DAEMON_NAME "dmeventd"
62277
62278/*
62279 Global mutex for thread list access. Has to be held when:
62280 - iterating thread list
62281 - adding or removing elements from thread list
62282 - changing or reading thread_status's fields:
62283 processing, status, events
62284 Use _lock_mutex() and _unlock_mutex() to hold/release it
62285*/
62286static pthread_mutex_t _global_mutex;
62287
62288static const size_t THREAD_STACK_SIZE = 300 * 1024;
62289
62290/* Default idle exit timeout 1 hour (in seconds) */
62291static const time_t DMEVENTD_IDLE_EXIT_TIMEOUT = 60 * 60;
62292
62293static int _debug_level = 0;
62294static int _use_syslog = 1;
62295static int _systemd_activation = 0;
62296static int _foreground = 0;
62297static int _restart = 0;
62298static time_t _idle_since = 0;
62299static char **_initial_registrations = 0;
62300
62301/* FIXME Make configurable at runtime */
62302
62303/* All libdm messages */
62304__attribute__((format(printf, 5, 6)))
62305static void _libdm_log(int level, const char *file, int line,
62306 int dm_errno_or_class, const char *format, ...)
62307{
62308 va_list ap;
62309 va_start(ap, format);
62310 dm_event_log("#dm", level, file, line, dm_errno_or_class, format, ap);
62311 va_end(ap);
62312}
62313
62314/* All dmeventd messages */
62315#undef LOG_MESG
62316#define LOG_MESG(l, f, ln, e, x...) _dmeventd_log(l, f, ln, e, ## x)
62317__attribute__((format(printf, 5, 6)))
62318static void _dmeventd_log(int level, const char *file, int line,
62319 int dm_errno_or_class, const char *format, ...)
62320{
62321 va_list ap;
62322 va_start(ap, format);
62323 dm_event_log("dmeventd", level, file, line, dm_errno_or_class, format, ap);
62324 va_end(ap);
62325}
62326
62327#ifdef DEBUG
62328# define DEBUGLOG log_debug
62329static const char *decode_cmd(uint32_t cmd)
62330{
62331 switch (cmd) {
62332 case DM_EVENT_CMD_ACTIVE: return "ACTIVE";
62333 case DM_EVENT_CMD_REGISTER_FOR_EVENT: return "REGISTER_FOR_EVENT";
62334 case DM_EVENT_CMD_UNREGISTER_FOR_EVENT: return "UNREGISTER_FOR_EVENT";
62335 case DM_EVENT_CMD_GET_REGISTERED_DEVICE: return "GET_REGISTERED_DEVICE";
62336 case DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE: return "GET_NEXT_REGISTERED_DEVICE";
62337 case DM_EVENT_CMD_SET_TIMEOUT: return "SET_TIMEOUT";
62338 case DM_EVENT_CMD_GET_TIMEOUT: return "GET_TIMEOUT";
62339 case DM_EVENT_CMD_HELLO: return "HELLO";
62340 case DM_EVENT_CMD_DIE: return "DIE";
62341 case DM_EVENT_CMD_GET_STATUS: return "GET_STATUS";
62342 case DM_EVENT_CMD_GET_PARAMETERS: return "GET_PARAMETERS";
62343 default: return "unknown";
62344 }
62345}
62346
62347#else
62348# define DEBUGLOG(fmt, args...) do { } while (0)
62349#endif
62350
62351/* Data kept about a DSO. */
62352struct dso_data {
62353 struct dm_list list;
62354
62355 char *dso_name; /* DSO name (eg, "evms", "dmraid", "lvm2"). */
62356
62357 void *dso_handle; /* Opaque handle as returned from dlopen(). */
62358 unsigned int ref_count; /* Library reference count. */
62359
62360 /*
62361 * Event processing.
62362 *
62363 * The DSO can do whatever appropriate steps if an event
62364 * happens such as changing the mapping in case a mirror
62365 * fails, update the application metadata etc.
62366 *
62367 * This function gets a dm_task that is a result of
62368 * DM_DEVICE_WAITEVENT ioctl (results equivalent to
62369 * DM_DEVICE_STATUS). It should not destroy it.
62370 * The caller must dispose of the task.
62371 */
62372 void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user);
62373
62374 /*
62375 * Device registration.
62376 *
62377 * When an application registers a device for an event, the DSO
62378 * can carry out appropriate steps so that a later call to
62379 * the process_event() function is sane (eg, read metadata
62380 * and activate a mapping).
62381 */
62382 int (*register_device)(const char *device, const char *uuid, int major,
62383 int minor, void **user);
62384
62385 /*
62386 * Device unregistration.
62387 *
62388 * In case all devices of a mapping (eg, RAID10) are unregistered
62389 * for events, the DSO can recognize this and carry out appropriate
62390 * steps (eg, deactivate mapping, metadata update).
62391 */
62392 int (*unregister_device)(const char *device, const char *uuid,
62393 int major, int minor, void **user);
62394};
62395static DM_LIST_INIT(_dso_registry);
62396
62397/* Structure to keep parsed register variables from client message. */
62398struct message_data {
62399 char *id;
62400 char *dso_name; /* Name of DSO. */
62401 char *device_uuid; /* Mapped device path. */
62402 char *events_str; /* Events string as fetched from message. */
62403 enum dm_event_mask events_field; /* Events bitfield. */
62404 char *timeout_str;
62405 uint32_t timeout_secs;
62406 struct dm_event_daemon_message *msg; /* Pointer to message buffer. */
62407};
62408
62409/* There are three states a thread can attain. */
62410enum {
62411 DM_THREAD_REGISTERING, /* Registering, transitions to RUNNING */
62412 DM_THREAD_RUNNING, /* Working on events, transitions to DONE */
62413 DM_THREAD_DONE /* Terminated and cleanup is pending */
62414};
62415
62416/*
62417 * Housekeeping of thread+device states.
62418 *
62419 * One thread per mapped device which can block on it until an event
62420 * occurs and the event processing function of the DSO gets called.
62421 */
62422struct thread_status {
62423 struct dm_list list;
62424
62425 pthread_t thread;
62426
62427 struct dso_data *dso_data; /* DSO this thread accesses. */
62428
62429 struct {
62430 char *uuid;
62431 char *name;
62432 int major, minor;
62433 } device;
62434 int processing; /* Set when event is being processed */
62435
62436 int status; /* See DM_THREAD_{REGISTERING,RUNNING,DONE} */
62437
62438 int events; /* bitfield for event filter. */
62439 int current_events; /* bitfield for occured events. */
62440 struct dm_task *wait_task;
62441 int pending; /* Set when event filter change is pending */
62442 time_t next_time;
62443 uint32_t timeout;
62444 struct dm_list timeout_list;
62445 void *dso_private; /* dso per-thread status variable */
62446 /* TODO per-thread mutex */
62447};
62448
62449static DM_LIST_INIT(_thread_registry);
62450static DM_LIST_INIT(_thread_registry_unused);
62451
62452static int _timeout_running;
62453static DM_LIST_INIT(_timeout_registry);
62454static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
62455static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
62456
62457
62458/**********
62459 * DSO
62460 **********/
62461
62462/* DSO data allocate/free. */
62463static void _free_dso_data(struct dso_data *data)
62464{
62465 dm_free(data->dso_name);
62466 dm_free(data);
62467}
62468
62469static struct dso_data *_alloc_dso_data(struct message_data *data)
62470{
62471 struct dso_data *ret = (typeof(ret)) dm_zalloc(sizeof(*ret));
62472
62473 if (!ret)
62474 return_NULL;
62475
62476 if (!(ret->dso_name = dm_strdup(data->dso_name))) {
62477 dm_free(ret);
62478 return_NULL;
62479 }
62480
62481 return ret;
62482}
62483
62484/* DSO reference counting. */
62485static void _lib_get(struct dso_data *data)
62486{
62487 data->ref_count++;
62488}
62489
62490static void _lib_put(struct dso_data *data)
62491{
62492 if (!--data->ref_count) {
62493 dlclose(data->dso_handle);
62494 UNLINK_DSO(data);
62495 _free_dso_data(data);
62496
62497 /* Close control device if there is no plugin in-use */
62498 if (dm_list_empty(&_dso_registry)) {
62499 DEBUGLOG("Unholding control device.");
62500 dm_hold_control_dev(0);
62501 dm_lib_release();
62502 _idle_since = time(NULL);
62503 }
62504 }
62505}
62506
62507/* Find DSO data. */
62508static struct dso_data *_lookup_dso(struct message_data *data)
62509{
62510 struct dso_data *dso_data, *ret = NULL;
62511
62512 dm_list_iterate_items(dso_data, &_dso_registry)
62513 if (!strcmp(data->dso_name, dso_data->dso_name)) {
62514 ret = dso_data;
62515 break;
62516 }
62517
62518 return ret;
62519}
62520
62521/* Lookup DSO symbols we need. */
62522static int _lookup_symbol(void *dl, void **symbol, const char *name)
62523{
62524 if (!(*symbol = dlsym(dl, name)))
62525 return_0;
62526
62527 return 1;
62528}
62529
62530static int _lookup_symbols(void *dl, struct dso_data *data)
62531{
62532 return _lookup_symbol(dl, (void *) &data->process_event,
62533 "process_event") &&
62534 _lookup_symbol(dl, (void *) &data->register_device,
62535 "register_device") &&
62536 _lookup_symbol(dl, (void *) &data->unregister_device,
62537 "unregister_device");
62538}
62539
62540/* Load an application specific DSO. */
62541static struct dso_data *_load_dso(struct message_data *data)
62542{
62543 void *dl;
62544 struct dso_data *ret;
62545 const char *dlerr;
62546
62547 if (!(dl = dlopen(data->dso_name, RTLD_NOW))) {
62548 dlerr = dlerror();
62549 goto_bad;
62550 }
62551
62552 if (!(ret = _alloc_dso_data(data))) {
62553 dlclose(dl);
62554 dlerr = "no memory";
62555 goto_bad;
62556 }
62557
62558 if (!(_lookup_symbols(dl, ret))) {
62559 _free_dso_data(ret);
62560 dlclose(dl);
62561 dlerr = "symbols missing";
62562 goto_bad;
62563 }
62564
62565 /* Keep control device open until last user closes */
62566 if (dm_list_empty(&_dso_registry)) {
62567 DEBUGLOG("Holding control device open.");
62568 dm_hold_control_dev(1);
62569 _idle_since = 0;
62570 }
62571
62572 /*
62573 * Keep handle to close the library once
62574 * we've got no references to it any more.
62575 */
62576 ret->dso_handle = dl;
62577 LINK_DSO(ret);
62578
62579 return ret;
62580bad:
62581 log_error("dmeventd %s dlopen failed: %s.", data->dso_name, dlerr);
62582 data->msg->size = dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
62583 data->id, data->dso_name, dlerr);
62584 return NULL;
62585}
62586
62587/************
62588 * THREAD
62589 ************/
62590
62591/* Allocate/free the thread status structure for a monitoring thread. */
62592static void _free_thread_status(struct thread_status *thread)
62593{
62594
62595 _lib_put(thread->dso_data);
62596 if (thread->wait_task)
62597 dm_task_destroy(thread->wait_task);
62598 dm_free(thread->device.uuid);
62599 dm_free(thread->device.name);
62600 dm_free(thread);
62601}
62602
62603/* Note: events_field must not be 0, ensured by caller */
62604static struct thread_status *_alloc_thread_status(const struct message_data *data,
62605 struct dso_data *dso_data)
62606{
62607 struct thread_status *thread;
62608
62609 if (!(thread = dm_zalloc(sizeof(*thread)))) {
62610 log_error("Cannot create new thread, out of memory.");
62611 return NULL;
62612 }
62613
62614 _lib_get(dso_data);
62615 thread->dso_data = dso_data;
62616
62617 if (!(thread->wait_task = dm_task_create(DM_DEVICE_WAITEVENT)))
62618 goto_out;
62619
62620 if (!dm_task_set_uuid(thread->wait_task, data->device_uuid))
62621 goto_out;
62622
62623 if (!(thread->device.uuid = dm_strdup(data->device_uuid)))
62624 goto_out;
62625
62626 /* Until real name resolved, use UUID */
62627 if (!(thread->device.name = dm_strdup(data->device_uuid)))
62628 goto_out;
62629
62630 /* runs ioctl and may register lvm2 pluging */
62631 thread->processing = 1;
62632 thread->status = DM_THREAD_REGISTERING;
62633
62634 thread->events = data->events_field;
62635 thread->pending = DM_EVENT_REGISTRATION_PENDING;
62636 thread->timeout = data->timeout_secs;
62637 dm_list_init(&thread->timeout_list);
62638
62639 return thread;
62640
62641out:
62642 _free_thread_status(thread);
62643
62644 return NULL;
62645}
62646
62647/*
62648 * Create a device monitoring thread.
62649 * N.B. Error codes returned are positive.
62650 */
62651static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg)
62652{
62653 int r;
62654 pthread_t tmp;
62655 pthread_attr_t attr;
62656
62657 /*
62658 * From pthread_attr_init man page:
62659 * POSIX.1-2001 documents an ENOMEM error for pthread_attr_init(); on
62660 * Linux these functions always succeed (but portable and future-proof
62661 * applications should nevertheless handle a possible error return).
62662 */
62663 if ((r = pthread_attr_init(&attr)) != 0) {
62664 log_sys_error("pthread_attr_init", "");
62665 return r;
62666 }
62667
62668 /*
62669 * We use a smaller stack since it gets preallocated in its entirety
62670 */
62671 pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
62672
62673 /*
62674 * If no-one will be waiting, we need to detach.
62675 */
62676 if (!t) {
62677 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
62678 t = &tmp;
62679 }
62680
62681 if ((r = pthread_create(t, &attr, fun, arg)))
62682 log_sys_error("pthread_create", "");
62683
62684 pthread_attr_destroy(&attr);
62685
62686 return r;
62687}
62688
62689/*
62690 * Fetch a string off src and duplicate it into *ptr.
62691 * Pay attention to zero-length and 'empty' strings ('-').
62692 */
62693/* FIXME? move to libdevmapper to share with the client lib (need to
62694 make delimiter a parameter then) */
62695static int _fetch_string(char **ptr, char **src, const int delimiter)
62696{
62697 int ret = 1;
62698 char *p;
62699 size_t len;
62700 *ptr = NULL; /* Empty field returns NULL pointer */
62701
62702 if ((*src)[0] == '-') {
62703 /* Could be empty field '-', handle without allocation */
62704 if ((*src)[1] == '\0') {
62705 (*src)++;
62706 goto out;
62707 } else if ((*src)[1] == delimiter) {
62708 (*src) += 2;
62709 goto out;
62710 }
62711 }
62712
62713 if ((p = strchr(*src, delimiter))) {
62714 if (*src < p) {
62715 *p = 0; /* Temporary exit with \0 */
62716 if (!(*ptr = dm_strdup(*src))) {
62717 log_error("Failed to fetch item %s.", *src);
62718 ret = 0; /* Allocation fail */
62719 }
62720 *p = delimiter;
62721 *src = p;
62722 }
62723 (*src)++; /* Skip delmiter, next field */
62724 } else if ((len = strlen(*src))) {
62725 /* No delimiter, item ends with '\0' */
62726 if (!(*ptr = dm_strdup(*src))) {
62727 log_error("Failed to fetch last item %s.", *src);
62728 ret = 0; /* Fail */
62729 }
62730 *src += len + 1;
62731 }
62732out:
62733 return ret;
62734}
62735
62736/* Free message memory. */
62737static void _free_message(struct message_data *message_data)
62738{
62739 dm_free(message_data->id);
62740 dm_free(message_data->dso_name);
62741 dm_free(message_data->device_uuid);
62742 dm_free(message_data->events_str);
62743 dm_free(message_data->timeout_str);
62744}
62745
62746/* Parse a register message from the client. */
62747static int _parse_message(struct message_data *message_data)
62748{
62749 int ret = 0;
62750 struct dm_event_daemon_message *msg = message_data->msg;
62751 char *p = msg->data;
62752
62753 if (!msg->data)
62754 return 0;
62755
62756 /*
62757 * Retrieve application identifier, mapped device
62758 * path and events # string from message.
62759 */
62760 if (_fetch_string(&message_data->id, &p, ' ') &&
62761 _fetch_string(&message_data->dso_name, &p, ' ') &&
62762 _fetch_string(&message_data->device_uuid, &p, ' ') &&
62763 _fetch_string(&message_data->events_str, &p, ' ') &&
62764 _fetch_string(&message_data->timeout_str, &p, ' ')) {
62765 if (message_data->events_str)
62766 message_data->events_field =
62767 atoi(message_data->events_str);
62768 if (message_data->timeout_str)
62769 message_data->timeout_secs =
62770 atoi(message_data->timeout_str)
62771 ? : DM_EVENT_DEFAULT_TIMEOUT;
62772 ret = 1;
62773 }
62774
62775 dm_free(msg->data);
62776 msg->data = NULL;
62777
62778 return ret;
62779}
62780
62781/* Global mutex to lock access to lists et al. See _global_mutex
62782 above. */
62783static int _lock_mutex(void)
62784{
62785 return pthread_mutex_lock(&_global_mutex);
62786}
62787
62788static int _unlock_mutex(void)
62789{
62790 return pthread_mutex_unlock(&_global_mutex);
62791}
62792
62793/* Check, if a device exists. */
62794static int _fill_device_data(struct thread_status *ts)
62795{
62796 struct dm_task *dmt;
62797 struct dm_info dmi;
62798 int ret = 0;
62799
62800 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
62801 return 0;
62802
62803 if (!dm_task_set_uuid(dmt, ts->device.uuid))
62804 goto fail;
62805
62806 if (!dm_task_run(dmt))
62807 goto fail;
62808
62809 dm_free(ts->device.name);
62810 if (!(ts->device.name = dm_strdup(dm_task_get_name(dmt))))
62811 goto fail;
62812
62813 if (!dm_task_get_info(dmt, &dmi))
62814 goto fail;
62815
62816 ts->device.major = dmi.major;
62817 ts->device.minor = dmi.minor;
62818 dm_task_set_event_nr(ts->wait_task, dmi.event_nr);
62819
62820 ret = 1;
62821fail:
62822 dm_task_destroy(dmt);
62823
62824 return ret;
62825}
62826
62827static struct dm_task *_get_device_status(struct thread_status *ts)
62828{
62829 struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
62830
62831 if (!dmt)
62832 return_NULL;
62833
62834 if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
62835 dm_task_destroy(dmt);
62836 return_NULL;
62837 }
62838
62839 /* Non-blocking status read */
62840 if (!dm_task_no_flush(dmt))
62841 log_warn("WARNING: Can't set no_flush for dm status.");
62842
62843 if (!dm_task_run(dmt)) {
62844 dm_task_destroy(dmt);
62845 return_NULL;
62846 }
62847
62848 return dmt;
62849}
62850
62851/*
62852 * Find an existing thread for a device.
62853 *
62854 * Mutex must be held when calling this.
62855 */
62856static struct thread_status *_lookup_thread_status(struct message_data *data)
62857{
62858 struct thread_status *thread;
62859
62860 dm_list_iterate_items(thread, &_thread_registry)
62861 if (!strcmp(data->device_uuid, thread->device.uuid))
62862 return thread;
62863
62864 return NULL;
62865}
62866
62867static int _get_status(struct message_data *message_data)
62868{
62869 struct dm_event_daemon_message *msg = message_data->msg;
62870 struct thread_status *thread;
62871 int i = 0, j;
62872 int ret = -ENOMEM;
62873 int count;
62874 int size = 0, current;
62875 size_t len;
62876 char **buffers;
62877 char *message;
62878
62879 _lock_mutex();
62880 count = dm_list_size(&_thread_registry);
62881 buffers = alloca(sizeof(char*) * count);
62882 dm_list_iterate_items(thread, &_thread_registry) {
62883 if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
62884 i, thread->dso_data->dso_name,
62885 thread->device.uuid, thread->events,
62886 thread->timeout)) < 0) {
62887 _unlock_mutex();
62888 goto out;
62889 }
62890 ++i;
62891 size += current; /* count with trailing '\0' */
62892 }
62893 _unlock_mutex();
62894
62895 len = strlen(message_data->id);
62896 msg->size = size + len + 1;
62897 dm_free(msg->data);
62898 if (!(msg->data = dm_malloc(msg->size)))
62899 goto out;
62900
62901 memcpy(msg->data, message_data->id, len);
62902 message = msg->data + len;
62903 *message++ = ' ';
62904 for (j = 0; j < i; ++j) {
62905 len = strlen(buffers[j]);
62906 memcpy(message, buffers[j], len);
62907 message += len;
62908 }
62909
62910 ret = 0;
62911 out:
62912 for (j = 0; j < i; ++j)
62913 dm_free(buffers[j]);
62914
62915 return ret;
62916}
62917
62918static int _get_parameters(struct message_data *message_data) {
62919 struct dm_event_daemon_message *msg = message_data->msg;
62920 int size;
62921
62922 dm_free(msg->data);
62923 if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
62924 message_data->id, getpid(),
62925 _foreground ? "no" : "yes",
62926 _systemd_activation ? "systemd" : "direct")) < 0) {
62927 stack;
62928 return -ENOMEM;
62929 }
62930
62931 msg->size = (uint32_t) size;
62932
62933 return 0;
62934}
62935
62936/* Cleanup at exit. */
62937static void _exit_dm_lib(void)
62938{
62939 dm_lib_release();
62940 dm_lib_exit();
62941}
62942
62943static void _exit_timeout(void *unused __attribute__((unused)))
62944{
62945 _timeout_running = 0;
62946 pthread_mutex_unlock(&_timeout_mutex);
62947}
62948
62949/* Wake up monitor threads every so often. */
62950static void *_timeout_thread(void *unused __attribute__((unused)))
62951{
62952 struct thread_status *thread;
62953 struct timespec timeout;
62954 time_t curr_time;
62955
62956 DEBUGLOG("Timeout thread starting.");
62957 pthread_cleanup_push(_exit_timeout, NULL);
62958 pthread_mutex_lock(&_timeout_mutex);
62959
62960 while (!dm_list_empty(&_timeout_registry)) {
62961 timeout.tv_sec = 0;
62962 timeout.tv_nsec = 0;
62963 curr_time = time(NULL);
62964
62965 dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
62966 if (thread->next_time <= curr_time) {
62967 thread->next_time = curr_time + thread->timeout;
62968 _lock_mutex();
62969 if (thread->processing) {
62970 /* Cannot signal processing monitoring thread */
62971 log_debug("Skipping SIGALRM to processing Thr %x for timeout.",
62972 (int) thread->thread);
62973 } else {
62974 DEBUGLOG("Sending SIGALRM to Thr %x for timeout.",
62975 (int) thread->thread);
62976 pthread_kill(thread->thread, SIGALRM);
62977 }
62978 _unlock_mutex();
62979 }
62980
62981 if (thread->next_time < timeout.tv_sec || !timeout.tv_sec)
62982 timeout.tv_sec = thread->next_time;
62983 }
62984
62985 pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
62986 &timeout);
62987 }
62988
62989 DEBUGLOG("Timeout thread finished.");
62990 pthread_cleanup_pop(1);
62991
62992 return NULL;
62993}
62994
62995static int _register_for_timeout(struct thread_status *thread)
62996{
62997 int ret = 0;
62998
62999 pthread_mutex_lock(&_timeout_mutex);
63000
63001 if (dm_list_empty(&thread->timeout_list)) {
63002 thread->next_time = time(NULL) + thread->timeout;
63003 dm_list_add(&_timeout_registry, &thread->timeout_list);
63004 if (_timeout_running)
63005 pthread_cond_signal(&_timeout_cond);
63006 }
63007
63008 if (!_timeout_running &&
63009 !(ret = _pthread_create_smallstack(NULL, _timeout_thread, NULL)))
63010 _timeout_running = 1;
63011
63012 pthread_mutex_unlock(&_timeout_mutex);
63013
63014 return ret;
63015}
63016
63017static void _unregister_for_timeout(struct thread_status *thread)
63018{
63019 pthread_mutex_lock(&_timeout_mutex);
63020 if (!dm_list_empty(&thread->timeout_list)) {
63021 dm_list_del(&thread->timeout_list);
63022 dm_list_init(&thread->timeout_list);
63023 if (dm_list_empty(&_timeout_registry))
63024 /* No more work -> wakeup to finish quickly */
63025 pthread_cond_signal(&_timeout_cond);
63026 }
63027 pthread_mutex_unlock(&_timeout_mutex);
63028}
63029
63030#ifdef DEBUG_SIGNALS
63031/* Print list of signals within a signal set */
63032static void _print_sigset(const char *prefix, const sigset_t *sigset)
63033{
63034 int sig, cnt = 0;
63035
63036 for (sig = 1; sig < NSIG; sig++)
63037 if (!sigismember(sigset, sig)) {
63038 cnt++;
63039 log_debug("%s%d (%s)", prefix, sig, strsignal(sig));
63040 }
63041
63042 if (!cnt)
63043 log_debug("%s<empty signal set>", prefix);
63044}
63045#endif
63046
63047enum {
63048 DM_WAIT_RETRY,
63049 DM_WAIT_INTR,
63050 DM_WAIT_FATAL
63051};
63052
63053/* Wait on a device until an event occurs. */
63054static int _event_wait(struct thread_status *thread)
63055{
63056 sigset_t set, old;
63057 int ret = DM_WAIT_RETRY;
63058 struct dm_info info;
63059
63060 /* TODO: audit libdm thread usage */
63061
63062 /*
63063 * This is so that you can break out of waiting on an event,
63064 * either for a timeout event, or to cancel the thread.
63065 */
63066 sigemptyset(&set);
63067 sigaddset(&set, SIGALRM);
63068 if (pthread_sigmask(SIG_UNBLOCK, &set, &old) != 0) {
63069 log_sys_error("pthread_sigmask", "unblock alarm");
63070 return ret; /* What better */
63071 }
63072
63073 if (dm_task_run(thread->wait_task)) {
63074 thread->current_events |= DM_EVENT_DEVICE_ERROR;
63075 ret = DM_WAIT_INTR;
63076 /* Update event_nr */
63077 if (dm_task_get_info(thread->wait_task, &info))
63078 dm_task_set_event_nr(thread->wait_task, info.event_nr);
63079 } else {
63080 switch (dm_task_get_errno(thread->wait_task)) {
63081 case ENXIO:
63082 log_error("%s disappeared, detaching.",
63083 thread->device.name);
63084 ret = DM_WAIT_FATAL;
63085 break;
63086 case EINTR:
63087 thread->current_events |= DM_EVENT_TIMEOUT;
63088 ret = DM_WAIT_INTR;
63089 break;
63090 default:
63091 log_sys_error("dm_task_run", "waitevent");
63092 }
63093 }
63094
63095 if (pthread_sigmask(SIG_SETMASK, &old, NULL) != 0)
63096 log_sys_error("pthread_sigmask", "block alarm");
63097
63098#ifdef DEBUG_SIGNALS
63099 _print_sigset("dmeventd blocking ", &old);
63100#endif
63101 DEBUGLOG("Completed waitevent task for %s.", thread->device.name);
63102
63103 return ret;
63104}
63105
63106/* Register a device with the DSO. */
63107static int _do_register_device(struct thread_status *thread)
63108{
63109 return thread->dso_data->register_device(thread->device.name,
63110 thread->device.uuid,
63111 thread->device.major,
63112 thread->device.minor,
63113 &(thread->dso_private));
63114}
63115
63116/* Unregister a device with the DSO. */
63117static int _do_unregister_device(struct thread_status *thread)
63118{
63119 return thread->dso_data->unregister_device(thread->device.name,
63120 thread->device.uuid,
63121 thread->device.major,
63122 thread->device.minor,
63123 &(thread->dso_private));
63124}
63125
63126/* Process an event in the DSO. */
63127static void _do_process_event(struct thread_status *thread)
63128{
63129 struct dm_task *task;
63130
63131 /* NOTE: timeout event gets status */
63132 task = (thread->current_events & DM_EVENT_TIMEOUT)
63133 ? _get_device_status(thread) : thread->wait_task;
63134
63135 if (!task)
63136 log_error("Lost event in Thr %x.", (int)thread->thread);
63137 else {
63138 thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
63139 if (task != thread->wait_task)
63140 dm_task_destroy(task);
63141 }
63142}
63143
63144static void _thread_unused(struct thread_status *thread)
63145{
63146 UNLINK_THREAD(thread);
63147 LINK(thread, &_thread_registry_unused);
63148}
63149
63150/* Thread cleanup handler to unregister device. */
63151static void _monitor_unregister(void *arg)
63152{
63153 struct thread_status *thread = arg, *thread_iter;
63154
63155 dm_list_iterate_items(thread_iter, &_thread_registry)
63156 if (thread_iter == thread) {
63157 /* Relink to _unused */
63158 _thread_unused(thread);
63159 break;
63160 }
63161
63162 thread->events = 0; /* Filter is now empty */
63163 thread->pending = 0; /* Event pending resolved */
63164 thread->processing = 1; /* Process unregistering */
63165
63166 _unlock_mutex();
63167
63168 DEBUGLOG("Unregistering monitor for %s.", thread->device.name);
63169 _unregister_for_timeout(thread);
63170
63171 if ((thread->status != DM_THREAD_REGISTERING) &&
63172 !_do_unregister_device(thread))
63173 log_error("%s: %s unregister failed.", __func__,
63174 thread->device.name);
63175
63176 DEBUGLOG("Marking Thr %x as DONE and unused.", (int)thread->thread);
63177
63178 _lock_mutex();
63179 thread->status = DM_THREAD_DONE; /* Last access to thread memory! */
63180 _unlock_mutex();
63181}
63182
63183/* Device monitoring thread. */
63184static void *_monitor_thread(void *arg)
63185{
63186 struct thread_status *thread = arg;
63187 int ret;
63188 sigset_t pendmask;
63189
63190 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
63191 pthread_cleanup_push(_monitor_unregister, thread);
63192
63193 if (!_fill_device_data(thread)) {
63194 log_error("Failed to fill device data for %s.", thread->device.uuid);
63195 _lock_mutex();
63196 goto out;
63197 }
63198
63199 if (!_do_register_device(thread)) {
63200 log_error("Failed to register device %s.", thread->device.name);
63201 _lock_mutex();
63202 goto out;
63203 }
63204
63205 _lock_mutex();
63206 thread->status = DM_THREAD_RUNNING;
63207 thread->processing = 0;
63208
63209 /* Loop awaiting/analyzing device events. */
63210 while (thread->events) {
63211
63212 thread->pending = 0; /* Event is no longer pending... */
63213
63214 /*
63215 * Check against bitmask filter.
63216 *
63217 * If there's current events delivered from _event_wait() AND
63218 * the device got registered for those events AND
63219 * those events haven't been processed yet, call
63220 * the DSO's process_event() handler.
63221 */
63222 if (thread->events & thread->current_events) {
63223 thread->processing = 1; /* Cannot be removed/signaled */
63224 _unlock_mutex();
63225
63226 _do_process_event(thread);
63227 thread->current_events = 0; /* Current events processed */
63228
63229 _lock_mutex();
63230 thread->processing = 0;
63231
63232 /*
63233 * Thread can terminate itself from plugin via SIGALRM
63234 * Timer thread will not send signal while processing
63235 * TODO: maybe worth API change and return value for
63236 * _do_process_event() instead of this signal solution
63237 */
63238 if (sigpending(&pendmask) < 0)
63239 log_sys_error("sigpending", "");
63240 else if (sigismember(&pendmask, SIGALRM))
63241 break;
63242 } else {
63243 _unlock_mutex();
63244
63245 if ((ret = _event_wait(thread)) == DM_WAIT_RETRY)
63246 usleep(100); /* Avoid busy loop, wait without mutex */
63247
63248 _lock_mutex();
63249
63250 if (ret == DM_WAIT_FATAL)
63251 break;
63252 }
63253 }
63254out:
63255 /* ';' fixes gcc compilation problem with older pthread macros
63256 * "label at end of compound statement" */
63257 ;
63258
63259 pthread_cleanup_pop(1);
63260
63261 return NULL;
63262}
63263
63264/* Create a device monitoring thread. */
63265static int _create_thread(struct thread_status *thread)
63266{
63267 return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread);
63268}
63269
63270/* Update events - needs to be locked */
63271static int _update_events(struct thread_status *thread, int events)
63272{
63273 int ret = 0;
63274
63275 if (thread->events == events)
63276 return 0; /* Nothing has changed */
63277
63278 thread->events = events;
63279 thread->pending = DM_EVENT_REGISTRATION_PENDING;
63280
63281 /* Only non-processing threads can be notified */
63282 if (!thread->processing) {
63283 DEBUGLOG("Sending SIGALRM to wakeup Thr %x.", (int)thread->thread);
63284
63285 /* Notify thread waiting in ioctl (to speed-up) */
63286 if ((ret = pthread_kill(thread->thread, SIGALRM))) {
63287 if (ret == ESRCH)
63288 thread->events = 0; /* thread is gone */
63289 else
63290 log_error("Unable to wakeup thread: %s",
63291 strerror(ret));
63292 }
63293 }
63294
63295 /* Threads with no events has to be moved to unused */
63296 if (!thread->events)
63297 _thread_unused(thread);
63298
63299 return -ret;
63300}
63301
63302/* Return success on daemon active check. */
63303static int _active(struct message_data *message_data)
63304{
63305 return 0;
63306}
63307
63308/*
63309 * Unregister for an event.
63310 *
63311 * Only one caller at a time here as with register_for_event().
63312 */
63313static int _unregister_for_event(struct message_data *message_data)
63314{
63315 struct thread_status *thread;
63316 int ret;
63317
63318 /*
63319 * Clear event in bitfield and deactivate
63320 * monitoring thread in case bitfield is 0.
63321 */
63322 _lock_mutex();
63323
63324 if (!(thread = _lookup_thread_status(message_data))) {
63325 _unlock_mutex();
63326 return -ENODEV;
63327 }
63328
63329 /* AND mask event ~# from events bitfield. */
63330 ret = _update_events(thread, (thread->events & ~message_data->events_field));
63331
63332 _unlock_mutex();
63333
63334 /* If there are no events, thread is later garbage
63335 * collected by _cleanup_unused_threads */
63336 if (message_data->events_field & DM_EVENT_TIMEOUT)
63337 _unregister_for_timeout(thread);
63338
63339 DEBUGLOG("Unregistered event for %s.", thread->device.name);
63340
63341 return ret;
63342}
63343
63344/*
63345 * Register for an event.
63346 *
63347 * Only one caller at a time here, because we use
63348 * a FIFO and lock it against multiple accesses.
63349 */
63350static int _register_for_event(struct message_data *message_data)
63351{
63352 int ret = 0;
63353 struct thread_status *thread;
63354 struct dso_data *dso_data;
63355
63356 if (!(dso_data = _lookup_dso(message_data)) &&
63357 !(dso_data = _load_dso(message_data))) {
63358 stack;
63359#ifdef ELIBACC
63360 ret = ELIBACC;
63361#else
63362 ret = ENODEV;
63363#endif
63364 return ret;
63365 }
63366
63367 _lock_mutex();
63368
63369 if ((thread = _lookup_thread_status(message_data))) {
63370 /* OR event # into events bitfield. */
63371 ret = _update_events(thread, (thread->events | message_data->events_field));
63372 } else {
63373 _unlock_mutex();
63374
63375 /* Only creating thread during event processing
63376 * Remaining initialization happens within monitoring thread */
63377 if (!(thread = _alloc_thread_status(message_data, dso_data))) {
63378 stack;
63379 return -ENOMEM;
63380 }
63381
63382 if ((ret = _create_thread(thread))) {
63383 stack;
63384 _free_thread_status(thread);
63385 return -ret;
63386 }
63387
63388 _lock_mutex();
63389 /* Note: same uuid can't be added in parallel */
63390 LINK_THREAD(thread);
63391 }
63392
63393 _unlock_mutex();
63394
63395 /* If creation of timeout thread fails (as it may), we fail
63396 here completely. The client is responsible for either
63397 retrying later or trying to register without timeout
63398 events. However, if timeout thread cannot be started, it
63399 usually means we are so starved on resources that we are
63400 almost as good as dead already... */
63401 if ((message_data->events_field & DM_EVENT_TIMEOUT) &&
63402 (ret = _register_for_timeout(thread))) {
63403 stack;
63404 _unregister_for_event(message_data);
63405 }
63406
63407 return -ret;
63408}
63409
63410/*
63411 * Get registered device.
63412 *
63413 * Only one caller at a time here as with register_for_event().
63414 */
63415static int _registered_device(struct message_data *message_data,
63416 struct thread_status *thread)
63417{
63418 int r;
63419 struct dm_event_daemon_message *msg = message_data->msg;
63420
63421 dm_free(msg->data);
63422
63423 if ((r = dm_asprintf(&(msg->data), "%s %s %s %u",
63424 message_data->id,
63425 thread->dso_data->dso_name,
63426 thread->device.uuid,
63427 thread->events | thread->pending)) < 0)
63428 return -ENOMEM;
63429
63430 msg->size = (uint32_t) r;
63431 DEBUGLOG("Registered %s.", msg->data);
63432
63433 return 0;
63434}
63435
63436static int _want_registered_device(char *dso_name, char *device_uuid,
63437 struct thread_status *thread)
63438{
63439 /* If DSO names and device paths are equal. */
63440 if (dso_name && device_uuid)
63441 return !strcmp(dso_name, thread->dso_data->dso_name) &&
63442 !strcmp(device_uuid, thread->device.uuid);
63443
63444 /* If DSO names are equal. */
63445 if (dso_name)
63446 return !strcmp(dso_name, thread->dso_data->dso_name);
63447
63448 /* If device paths are equal. */
63449 if (device_uuid)
63450 return !strcmp(device_uuid, thread->device.uuid);
63451
63452 return 1;
63453}
63454
63455static int _get_registered_dev(struct message_data *message_data, int next)
63456{
63457 struct thread_status *thread, *hit = NULL;
63458 int ret = -ENOENT;
63459
63460 DEBUGLOG("Get%s dso:%s uuid:%s.", next ? "" : "Next",
63461 message_data->dso_name,
63462 message_data->device_uuid);
63463 _lock_mutex();
63464
63465 /* Iterate list of threads checking if we want a particular one. */
63466 dm_list_iterate_items(thread, &_thread_registry)
63467 if (_want_registered_device(message_data->dso_name,
63468 message_data->device_uuid,
63469 thread)) {
63470 hit = thread;
63471 break;
63472 }
63473
63474 /*
63475 * If we got a registered device and want the next one ->
63476 * fetch next conforming element off the list.
63477 */
63478 if (hit && !next)
63479 goto reg;
63480
63481 /*
63482 * If we didn't get a match, try the threads waiting to be deleted.
63483 * FIXME Do something similar if 'next' is set.
63484 */
63485 if (!hit && !next)
63486 dm_list_iterate_items(thread, &_thread_registry_unused)
63487 if (_want_registered_device(message_data->dso_name,
63488 message_data->device_uuid, thread)) {
63489 hit = thread;
63490 goto reg;
63491 }
63492
63493 if (!hit) {
63494 DEBUGLOG("Get%s not registered", next ? "" : "Next");
63495 goto out;
63496 }
63497
63498 while (1) {
63499 if (dm_list_end(&_thread_registry, &thread->list))
63500 goto out;
63501
63502 thread = dm_list_item(thread->list.n, struct thread_status);
63503 if (_want_registered_device(message_data->dso_name, NULL, thread)) {
63504 hit = thread;
63505 break;
63506 }
63507 }
63508
63509 reg:
63510 ret = _registered_device(message_data, hit);
63511
63512 out:
63513 _unlock_mutex();
63514
63515 return ret;
63516}
63517
63518static int _get_registered_device(struct message_data *message_data)
63519{
63520 return _get_registered_dev(message_data, 0);
63521}
63522
63523static int _get_next_registered_device(struct message_data *message_data)
63524{
63525 return _get_registered_dev(message_data, 1);
63526}
63527
63528static int _set_timeout(struct message_data *message_data)
63529{
63530 struct thread_status *thread;
63531
63532 _lock_mutex();
63533 thread = _lookup_thread_status(message_data);
63534 _unlock_mutex();
63535
63536 if (!thread)
63537 return -ENODEV;
63538
63539 /* Lets reprogram timer */
63540 pthread_mutex_lock(&_timeout_mutex);
63541 thread->timeout = message_data->timeout_secs;
63542 thread->next_time = 0;
63543 pthread_cond_signal(&_timeout_cond);
63544 pthread_mutex_unlock(&_timeout_mutex);
63545
63546 return 0;
63547}
63548
63549static int _get_timeout(struct message_data *message_data)
63550{
63551 struct thread_status *thread;
63552 struct dm_event_daemon_message *msg = message_data->msg;
63553
63554 _lock_mutex();
63555 thread = _lookup_thread_status(message_data);
63556 _unlock_mutex();
63557
63558 if (!thread)
63559 return -ENODEV;
63560
63561 dm_free(msg->data);
63562 msg->size = dm_asprintf(&(msg->data), "%s %" PRIu32,
63563 message_data->id, thread->timeout);
63564
63565 return (msg->data && msg->size) ? 0 : -ENOMEM;
63566}
63567
63568static int _open_fifo(const char *path)
63569{
63570 struct stat st;
63571 int fd = -1;
63572
63573 /*
63574 * FIXME Explicitly verify the code's requirement that path is secure:
63575 * - All parent directories owned by root without group/other write access unless sticky.
63576 */
63577
63578 /* If path exists, only use it if it is root-owned fifo mode 0600 */
63579 if ((lstat(path, &st) < 0)) {
63580 if (errno != ENOENT) {
63581 log_sys_error("stat", path);
63582 return -1;
63583 }
63584 } else if (!S_ISFIFO(st.st_mode) || st.st_uid ||
63585 (st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
63586 log_warn("WARNING: %s has wrong attributes: Replacing.", path);
63587 if (unlink(path)) {
63588 log_sys_error("unlink", path);
63589 return -1;
63590 }
63591 }
63592
63593 /* Create fifo. */
63594 (void) dm_prepare_selinux_context(path, S_IFIFO);
63595 if ((mkfifo(path, 0600) == -1) && errno != EEXIST) {
63596 log_sys_error("mkfifo", path);
63597 (void) dm_prepare_selinux_context(NULL, 0);
63598 goto fail;
63599 }
63600
63601 (void) dm_prepare_selinux_context(NULL, 0);
63602
63603 /* Need to open read+write or we will block or fail */
63604 if ((fd = open(path, O_RDWR)) < 0) {
63605 log_sys_error("open", path);
63606 goto fail;
63607 }
63608
63609 /* Warn about wrong permissions if applicable */
63610 if (fstat(fd, &st)) {
63611 log_sys_error("fstat", path);
63612 goto fail;
63613 }
63614
63615 if (!S_ISFIFO(st.st_mode) || st.st_uid ||
63616 (st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
63617 log_error("%s: fifo has incorrect attributes", path);
63618 goto fail;
63619 }
63620
63621 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
63622 log_sys_error("fcntl(FD_CLOEXEC)", path);
63623 goto fail;
63624 }
63625
63626 return fd;
63627
63628fail:
63629 if ((fd >= 0) && close(fd))
63630 log_sys_error("close", path);
63631
63632 return -1;
63633}
63634
63635/* Open fifos used for client communication. */
63636static int _open_fifos(struct dm_event_fifos *fifos)
63637{
63638 /* Create client fifo. */
63639 if ((fifos->client = _open_fifo(fifos->client_path)) < 0)
63640 goto fail;
63641
63642 /* Create server fifo. */
63643 if ((fifos->server = _open_fifo(fifos->server_path)) < 0)
63644 goto fail;
63645
63646 return 1;
63647
63648fail:
63649 if (fifos->client >= 0 && close(fifos->client))
63650 log_sys_error("close", fifos->client_path);
63651
63652 return 0;
63653}
63654
63655/*
63656 * Read message from client making sure that data is available
63657 * and a complete message is read. Must not block indefinitely.
63658 */
63659static int _client_read(struct dm_event_fifos *fifos,
63660 struct dm_event_daemon_message *msg)
63661{
63662 struct timeval t;
63663 unsigned bytes = 0;
63664 int ret = 0;
63665 fd_set fds;
63666 size_t size = 2 * sizeof(uint32_t); /* status + size */
63667 uint32_t *header = alloca(size);
63668 char *buf = (char *)header;
63669
63670 msg->data = NULL;
63671
63672 errno = 0;
63673 while (bytes < size && errno != EOF) {
63674 /* Watch client read FIFO for input. */
63675 FD_ZERO(&fds);
63676 FD_SET(fifos->client, &fds);
63677 t.tv_sec = 1;
63678 t.tv_usec = 0;
63679 ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
63680
63681 if (!ret && !bytes) /* nothing to read */
63682 return 0;
63683
63684 if (!ret) /* trying to finish read */
63685 continue;
63686
63687 if (ret < 0) /* error */
63688 return 0;
63689
63690 ret = read(fifos->client, buf + bytes, size - bytes);
63691 bytes += ret > 0 ? ret : 0;
63692 if (header && (bytes == 2 * sizeof(uint32_t))) {
63693 msg->cmd = ntohl(header[0]);
63694 size = msg->size = ntohl(header[1]);
63695 bytes = 0;
63696 if (!size)
63697 break; /* No data -> error */
63698 buf = msg->data = dm_malloc(msg->size);
63699 if (!buf)
63700 break; /* No mem -> error */
63701 header = 0;
63702 }
63703 }
63704
63705 if (bytes != size) {
63706 dm_free(msg->data);
63707 msg->data = NULL;
63708 return 0;
63709 }
63710
63711 return 1;
63712}
63713
63714/*
63715 * Write a message to the client making sure that it is ready to write.
63716 */
63717static int _client_write(struct dm_event_fifos *fifos,
63718 struct dm_event_daemon_message *msg)
63719{
63720 uint32_t temp[2];
63721 unsigned bytes = 0;
63722 int ret = 0;
63723 fd_set fds;
63724
63725 size_t size = 2 * sizeof(uint32_t) + ((msg->data) ? msg->size : 0);
63726 uint32_t *header = dm_malloc(size);
63727 char *buf = (char *)header;
63728
63729 if (!header) {
63730 /* Reply with ENOMEM message */
63731 header = temp;
63732 size = sizeof(temp);
63733 header[0] = htonl(-ENOMEM);
63734 header[1] = 0;
63735 } else {
63736 header[0] = htonl(msg->cmd);
63737 header[1] = htonl((msg->data) ? msg->size : 0);
63738 if (msg->data)
63739 memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
63740 }
63741
63742 while (bytes < size) {
63743 do {
63744 /* Watch client write FIFO to be ready for output. */
63745 FD_ZERO(&fds);
63746 FD_SET(fifos->server, &fds);
63747 } while (select(fifos->server + 1, NULL, &fds, NULL, NULL) != 1);
63748
63749 if ((ret = write(fifos->server, buf + bytes, size - bytes)) > 0)
63750 bytes += ret;
63751 else if (errno == EIO)
63752 break;
63753 }
63754
63755 if (header != temp)
63756 dm_free(header);
63757
63758 return (bytes == size);
63759}
63760
63761/*
63762 * Handle a client request.
63763 *
63764 * We put the request handling functions into
63765 * a list because of the growing number.
63766 */
63767static int _handle_request(struct dm_event_daemon_message *msg,
63768 struct message_data *message_data)
63769{
63770 switch (msg->cmd) {
63771 case DM_EVENT_CMD_REGISTER_FOR_EVENT:
63772 if (!message_data->events_field)
63773 return -EINVAL;
63774 return _register_for_event(message_data);
63775 case DM_EVENT_CMD_UNREGISTER_FOR_EVENT:
63776 return _unregister_for_event(message_data);
63777 case DM_EVENT_CMD_GET_REGISTERED_DEVICE:
63778 return _get_registered_device(message_data);
63779 case DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE:
63780 return _get_next_registered_device(message_data);
63781 case DM_EVENT_CMD_SET_TIMEOUT:
63782 return _set_timeout(message_data);
63783 case DM_EVENT_CMD_GET_TIMEOUT:
63784 return _get_timeout(message_data);
63785 case DM_EVENT_CMD_ACTIVE:
63786 return _active(message_data);
63787 case DM_EVENT_CMD_GET_STATUS:
63788 return _get_status(message_data);
63789 /* dmeventd parameters of running dmeventd,
63790 * returns 'pid=<pid> daemon=<no/yes> exec_method=<direct/systemd>'
63791 * pid - pidfile of running dmeventd
63792 * daemon - running as a daemon or not (foreground)?
63793 * exec_method - "direct" if executed directly or
63794 * "systemd" if executed via systemd
63795 */
63796 case DM_EVENT_CMD_GET_PARAMETERS:
63797 return _get_parameters(message_data);
63798 default:
63799 return -EINVAL;
63800 }
63801}
63802
63803/* Process a request passed from the communication thread. */
63804static int _do_process_request(struct dm_event_daemon_message *msg)
63805{
63806 int ret;
63807 char *answer;
63808 struct message_data message_data = { .msg = msg };
63809
63810 /* Parse the message. */
63811 if (msg->cmd == DM_EVENT_CMD_HELLO || msg->cmd == DM_EVENT_CMD_DIE) {
63812 ret = 0;
63813 answer = msg->data;
63814 if (answer) {
63815 msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer,
63816 (msg->cmd == DM_EVENT_CMD_DIE) ? "DYING" : "HELLO",
63817 DM_EVENT_PROTOCOL_VERSION);
63818 dm_free(answer);
63819 }
63820 } else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
63821 stack;
63822 ret = -EINVAL;
63823 } else
63824 ret = _handle_request(msg, &message_data);
63825
63826 msg->cmd = ret;
63827 if (!msg->data)
63828 msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
63829
63830 _free_message(&message_data);
63831
63832 return ret;
63833}
63834
63835/* Only one caller at a time. */
63836static void _process_request(struct dm_event_fifos *fifos)
63837{
63838 struct dm_event_daemon_message msg = { 0 };
63839 int cmd;
63840 /*
63841 * Read the request from the client (client_read, client_write
63842 * give true on success and false on failure).
63843 */
63844 if (!_client_read(fifos, &msg))
63845 return;
63846
63847 cmd = msg.cmd;
63848
63849 DEBUGLOG(">>> CMD:%s (0x%x) processing...", decode_cmd(cmd), cmd);
63850
63851 /* _do_process_request fills in msg (if memory allows for
63852 data, otherwise just cmd and size = 0) */
63853 _do_process_request(&msg);
63854
63855 if (!_client_write(fifos, &msg))
63856 stack;
63857
63858 DEBUGLOG("<<< CMD:%s (0x%x) completed (result %d).", decode_cmd(cmd), cmd, msg.cmd);
63859
63860 dm_free(msg.data);
63861
63862 if (cmd == DM_EVENT_CMD_DIE) {
63863 if (unlink(DMEVENTD_PIDFILE))
63864 log_sys_error("unlink", DMEVENTD_PIDFILE);
63865 _exit(0);
63866 }
63867}
63868
63869static void _process_initial_registrations(void)
63870{
63871 int i;
63872 char *reg;
63873 struct dm_event_daemon_message msg = { 0 };
63874
63875 for (i = 0; (reg = _initial_registrations[i]); ++i) {
63876 msg.cmd = DM_EVENT_CMD_REGISTER_FOR_EVENT;
63877 if ((msg.size = strlen(reg))) {
63878 msg.data = reg;
63879 _do_process_request(&msg);
63880 }
63881 }
63882}
63883
63884static void _cleanup_unused_threads(void)
63885{
63886 struct dm_list *l;
63887 struct thread_status *thread;
63888 int ret;
63889
63890 _lock_mutex();
63891
63892 while ((l = dm_list_first(&_thread_registry_unused))) {
63893 thread = dm_list_item(l, struct thread_status);
63894 if (thread->status != DM_THREAD_DONE) {
63895 if (thread->processing)
63896 break; /* cleanup on the next round */
63897
63898 /* Signal possibly sleeping thread */
63899 ret = pthread_kill(thread->thread, SIGALRM);
63900 if (!ret || (ret != ESRCH))
63901 break; /* check again on the next round */
63902
63903 /* thread is likely gone */
63904 }
63905
63906 dm_list_del(l);
63907 _unlock_mutex();
63908
63909 DEBUGLOG("Destroying Thr %x.", (int)thread->thread);
63910
63911 if (pthread_join(thread->thread, NULL))
63912 log_sys_error("pthread_join", "");
63913
63914 _free_thread_status(thread);
63915 _lock_mutex();
63916 }
63917
63918 _unlock_mutex();
63919}
63920
63921static void _sig_alarm(int signum __attribute__((unused)))
63922{
63923 /* empty SIG_IGN */;
63924}
63925
63926/* Init thread signal handling. */
63927static void _init_thread_signals(void)
63928{
63929 sigset_t my_sigset;
63930 struct sigaction act = { .sa_handler = _sig_alarm };
63931
63932 sigaction(SIGALRM, &act, NULL);
63933 sigfillset(&my_sigset);
63934
63935 /* These are used for exiting */
63936 sigdelset(&my_sigset, SIGTERM);
63937 sigdelset(&my_sigset, SIGINT);
63938 sigdelset(&my_sigset, SIGHUP);
63939 sigdelset(&my_sigset, SIGQUIT);
63940
63941 pthread_sigmask(SIG_BLOCK, &my_sigset, NULL);
63942}
63943
63944/*
63945 * exit_handler
63946 * @sig
63947 *
63948 * Set the global variable which the process should
63949 * be watching to determine when to exit.
63950 */
63951static void _exit_handler(int sig __attribute__((unused)))
63952{
63953 _exit_now = 1;
63954}
63955
63956#ifdef __linux__
63957static int _set_oom_adj(const char *oom_adj_path, int val)
63958{
63959 FILE *fp;
63960
63961 if (!(fp = fopen(oom_adj_path, "w"))) {
63962 log_sys_error("open", oom_adj_path);
63963 return 0;
63964 }
63965
63966 fprintf(fp, "%i", val);
63967
63968 if (dm_fclose(fp))
63969 log_sys_error("fclose", oom_adj_path);
63970
63971 return 1;
63972}
63973
63974/*
63975 * Protection against OOM killer if kernel supports it
63976 */
63977static int _protect_against_oom_killer(void)
63978{
63979 struct stat st;
63980
63981 if (stat(OOM_ADJ_FILE, &st) == -1) {
63982 if (errno != ENOENT)
63983 log_sys_error("stat", OOM_ADJ_FILE);
63984
63985 /* Try old oom_adj interface as a fallback */
63986 if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
63987 log_sys_error("stat", OOM_ADJ_FILE_OLD);
63988 return 1;
63989 }
63990
63991 return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) ||
63992 _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN);
63993 }
63994
63995 return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
63996}
63997
63998static int _handle_preloaded_fifo(int fd, const char *path)
63999{
64000 struct stat st_fd, st_path;
64001 int flags;
64002
64003 if ((flags = fcntl(fd, F_GETFD)) < 0)
64004 return 0;
64005
64006 if (flags & FD_CLOEXEC)
64007 return 0;
64008
64009 if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode))
64010 return 0;
64011
64012 if (stat(path, &st_path) < 0 ||
64013 st_path.st_dev != st_fd.st_dev ||
64014 st_path.st_ino != st_fd.st_ino)
64015 return 0;
64016
64017 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
64018 return 0;
64019
64020 return 1;
64021}
64022
64023static int _systemd_handover(struct dm_event_fifos *fifos)
64024{
64025 const char *e;
64026 char *p;
64027 unsigned long env_pid, env_listen_fds;
64028 int r = 0;
64029
64030 /* SD_ACTIVATION must be set! */
64031 if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1"))
64032 goto out;
64033
64034 /* LISTEN_PID must be equal to our PID! */
64035 if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
64036 goto out;
64037
64038 errno = 0;
64039 env_pid = strtoul(e, &p, 10);
64040 if (errno || !p || *p || env_pid <= 0 ||
64041 getpid() != (pid_t) env_pid)
64042 goto out;
64043
64044 /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */
64045 if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
64046 goto out;
64047
64048 errno = 0;
64049 env_listen_fds = strtoul(e, &p, 10);
64050 if (errno || !p || *p || env_listen_fds != 2)
64051 goto out;
64052
64053 /* Check and handle the FIFOs passed in */
64054 r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) &&
64055 _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT));
64056
64057 if (r) {
64058 fifos->server = SD_FD_FIFO_SERVER;
64059 fifos->server_path = DM_EVENT_FIFO_SERVER;
64060 fifos->client = SD_FD_FIFO_CLIENT;
64061 fifos->client_path = DM_EVENT_FIFO_CLIENT;
64062 }
64063
64064out:
64065 unsetenv(SD_ACTIVATION_ENV_VAR_NAME);
64066 unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
64067 unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
64068 return r;
64069}
64070
64071#endif
64072
64073static void _remove_files_on_exit(void)
64074{
64075 if (unlink(DMEVENTD_PIDFILE))
64076 log_sys_error("unlink", DMEVENTD_PIDFILE);
64077
64078 if (!_systemd_activation) {
64079 if (unlink(DM_EVENT_FIFO_CLIENT))
64080 log_sys_error("unlink", DM_EVENT_FIFO_CLIENT);
64081
64082 if (unlink(DM_EVENT_FIFO_SERVER))
64083 log_sys_error("unlink", DM_EVENT_FIFO_SERVER);
64084 }
64085}
64086
64087static void _daemonize(void)
64088{
64089 int child_status;
64090 int fd;
64091 pid_t pid;
64092 struct rlimit rlim;
64093 struct timeval tval;
64094 sigset_t my_sigset;
64095
64096 sigemptyset(&my_sigset);
64097 if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
64098 fprintf(stderr, "Unable to restore signals.\n");
64099 exit(EXIT_FAILURE);
64100 }
64101 signal(SIGTERM, &_exit_handler);
64102
64103 switch (pid = fork()) {
64104 case -1:
64105 log_sys_error("fork", "");
64106 exit(EXIT_FAILURE);
64107 case 0: /* Child */
64108 break;
64109
64110 default:
64111 /* Wait for response from child */
64112 while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) {
64113 tval.tv_sec = 0;
64114 tval.tv_usec = 250000; /* .25 sec */
64115 select(0, NULL, NULL, NULL, &tval);
64116 }
64117
64118 if (_exit_now) /* Child has signaled it is ok - we can exit now */
64119 exit(EXIT_SUCCESS);
64120
64121 /* Problem with child. Determine what it is by exit code */
64122 switch (WEXITSTATUS(child_status)) {
64123 case EXIT_DESC_CLOSE_FAILURE:
64124 case EXIT_DESC_OPEN_FAILURE:
64125 case EXIT_FIFO_FAILURE:
64126 case EXIT_CHDIR_FAILURE:
64127 default:
64128 fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
64129 break;
64130 }
64131
64132 exit(WEXITSTATUS(child_status));
64133 }
64134
64135 if (chdir("/"))
64136 exit(EXIT_CHDIR_FAILURE);
64137
64138 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
64139 fd = 256; /* just have to guess */
64140 else
64141 fd = rlim.rlim_cur;
64142
64143 for (--fd; fd >= 0; fd--) {
64144#ifdef __linux__
64145 /* Do not close fds preloaded by systemd! */
64146 if (_systemd_activation &&
64147 (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
64148 continue;
64149#endif
64150 (void) close(fd);
64151 }
64152
64153 if ((open("/dev/null", O_RDONLY) < 0) ||
64154 (open("/dev/null", O_WRONLY) < 0) ||
64155 (open("/dev/null", O_WRONLY) < 0))
64156 exit(EXIT_DESC_OPEN_FAILURE);
64157
64158 setsid();
64159}
64160
64161static int _reinstate_registrations(struct dm_event_fifos *fifos)
64162{
64163 static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
64164 static const char *_delim = " ";
64165 struct dm_event_daemon_message msg = { 0 };
64166 char *endp, *dso_name, *dev_name, *mask, *timeout;
64167 unsigned long mask_value, timeout_value;
64168 int i, ret;
64169
64170 ret = dm_event_daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
64171 dm_free(msg.data);
64172 msg.data = NULL;
64173
64174 if (ret) {
64175 fprintf(stderr, "Failed to communicate with new instance of dmeventd.\n");
64176 return 0;
64177 }
64178
64179 for (i = 0; _initial_registrations[i]; ++i) {
64180 if (!(strtok(_initial_registrations[i], _delim)) ||
64181 !(dso_name = strtok(NULL, _delim)) ||
64182 !(dev_name = strtok(NULL, _delim)) ||
64183 !(mask = strtok(NULL, _delim)) ||
64184 !(timeout = strtok(NULL, _delim))) {
64185 fputs(_failed_parsing_msg, stderr);
64186 continue;
64187 }
64188
64189 errno = 0;
64190 mask_value = strtoul(mask, &endp, 10);
64191 if (errno || !endp || *endp) {
64192 fputs(_failed_parsing_msg, stderr);
64193 continue;
64194 }
64195
64196 errno = 0;
64197 timeout_value = strtoul(timeout, &endp, 10);
64198 if (errno || !endp || *endp) {
64199 fputs(_failed_parsing_msg, stderr);
64200 continue;
64201 }
64202
64203 if (dm_event_daemon_talk(fifos, &msg, DM_EVENT_CMD_REGISTER_FOR_EVENT,
64204 dso_name,
64205 dev_name,
64206 (enum dm_event_mask) mask_value,
64207 timeout_value))
64208 fprintf(stderr, "Failed to reinstate monitoring for device %s.\n", dev_name);
64209 }
64210
64211 return 1;
64212}
64213
64214static void _restart_dmeventd(void)
64215{
64216 struct dm_event_fifos fifos = {
64217 .server = -1,
64218 .client = -1,
64219 /* FIXME Make these either configurable or depend directly on dmeventd_path */
64220 .client_path = DM_EVENT_FIFO_CLIENT,
64221 .server_path = DM_EVENT_FIFO_SERVER
64222 };
64223 struct dm_event_daemon_message msg = { 0 };
64224 int i, count = 0;
64225 char *message;
64226 int version;
64227 const char *e;
64228
64229 /* Get the list of registrations from the running daemon. */
64230 if (!dm_event_daemon_init_fifos(&fifos)) {
64231 fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
64232 exit(EXIT_FAILURE);
64233 }
64234
64235 if (!dm_event_get_version(&fifos, &version)) {
64236 fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n");
64237 goto bad;
64238 }
64239
64240 if (version < 1) {
64241 fprintf(stderr, "WARNING: The running dmeventd instance is too old.\n"
64242 "Protocol version %d (required: 1). Action cancelled.\n",
64243 version);
64244 goto bad;
64245 }
64246
64247 if (dm_event_daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
64248 goto bad;
64249
64250 message = strchr(msg.data, ' ') + 1;
64251 for (i = 0; msg.data[i]; ++i)
64252 if (msg.data[i] == ';') {
64253 msg.data[i] = 0;
64254 ++count;
64255 }
64256
64257 if (!(_initial_registrations = dm_malloc(sizeof(char*) * (count + 1)))) {
64258 fprintf(stderr, "Memory allocation registration failed.\n");
64259 goto bad;
64260 }
64261
64262 for (i = 0; i < count; ++i) {
64263 if (!(_initial_registrations[i] = dm_strdup(message))) {
64264 fprintf(stderr, "Memory allocation for message failed.\n");
64265 goto bad;
64266 }
64267 message += strlen(message) + 1;
64268 }
64269 _initial_registrations[count] = NULL;
64270
64271 if (version >= 2) {
64272 if (dm_event_daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
64273 fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
64274 goto bad;
64275 }
64276 if (strstr(msg.data, "exec_method=systemd"))
64277 _systemd_activation = 1;
64278 }
64279#ifdef __linux__
64280 /*
64281 * If the protocol version is old, just assume that if systemd is running,
64282 * the dmeventd is also run as a systemd service via fifo activation.
64283 */
64284 if (version < 2) {
64285 /* This check is copied from sd-daemon.c. */
64286 struct stat st;
64287 if (!lstat(SD_RUNTIME_UNIT_FILE_DIR, &st) && !!S_ISDIR(st.st_mode))
64288 _systemd_activation = 1;
64289 }
64290#endif
64291
64292 if (dm_event_daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
64293 fprintf(stderr, "Old dmeventd refused to die.\n");
64294 goto bad;
64295 }
64296
64297 if (!_systemd_activation &&
64298 ((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
64299 _systemd_activation = 1;
64300
64301 for (i = 0; i < 10; ++i) {
64302 if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
64303 break;
64304 usleep(10);
64305 }
64306
64307 if (!_systemd_activation) {
64308 dm_event_daemon_fini_fifos(&fifos);
64309 return;
64310 }
64311
64312 /* Reopen fifos. */
64313 dm_event_daemon_fini_fifos(&fifos);
64314 if (!dm_event_daemon_init_fifos(&fifos)) {
64315 fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
64316 exit(EXIT_FAILURE);
64317 }
64318
64319 if (!_reinstate_registrations(&fifos)) {
64320 fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
64321 goto bad;
64322 }
64323
64324 dm_event_daemon_fini_fifos(&fifos);
64325 exit(EXIT_SUCCESS);
64326bad:
64327 dm_event_daemon_fini_fifos(&fifos);
64328 exit(EXIT_FAILURE);
64329}
64330
64331static void _usage(char *prog, FILE *file)
64332{
64333 fprintf(file, "Usage:\n"
64334 "%s [-d [-d [-d]]] [-f] [-h] [-l] [-R] [-V] [-?]\n\n"
64335 " -d Log debug messages to syslog (-d, -dd, -ddd)\n"
64336 " -f Don't fork, run in the foreground\n"
64337 " -h Show this help information\n"
64338 " -l Log to stdout,stderr instead of syslog\n"
64339 " -? Show this help information on stderr\n"
64340 " -R Restart dmeventd\n"
64341 " -V Show version of dmeventd\n\n", prog);
64342}
64343
64344int main(int argc, char *argv[])
64345{
64346 signed char opt;
64347 struct dm_event_fifos fifos = {
64348 .client = -1,
64349 .server = -1,
64350 .client_path = DM_EVENT_FIFO_CLIENT,
64351 .server_path = DM_EVENT_FIFO_SERVER
64352 };
64353 time_t now, idle_exit_timeout = DMEVENTD_IDLE_EXIT_TIMEOUT;
64354 opterr = 0;
64355 optind = 0;
64356
64357 while ((opt = getopt(argc, argv, "?fhVdlR")) != EOF) {
64358 switch (opt) {
64359 case 'h':
64360 _usage(argv[0], stdout);
64361 exit(EXIT_SUCCESS);
64362 case '?':
64363 _usage(argv[0], stderr);
64364 exit(EXIT_SUCCESS);
64365 case 'R':
64366 _restart++;
64367 break;
64368 case 'f':
64369 _foreground++;
64370 break;
64371 case 'd':
64372 _debug_level++;
64373 break;
64374 case 'l':
64375 _use_syslog = 0;
64376 break;
64377 case 'V':
64378 printf("dmeventd version: %s\n", DM_LIB_VERSION);
64379 exit(EXIT_SUCCESS);
64380 }
64381 }
64382
64383 if (!_foreground && !_use_syslog) {
64384 printf("WARNING: Ignoring logging to stdout, needs options -f\n");
64385 _use_syslog = 1;
64386 }
64387 /*
64388 * Switch to C locale to avoid reading large locale-archive file
64389 * used by some glibc (on some distributions it takes over 100MB).
64390 * Daemon currently needs to use mlockall().
64391 */
64392 if (setenv("LC_ALL", "C", 1))
64393 perror("Cannot set LC_ALL to C");
64394
64395 if (_restart)
64396 _restart_dmeventd();
64397
64398#ifdef __linux__
64399 _systemd_activation = _systemd_handover(&fifos);
64400#endif
64401
64402 if (!_foreground)
64403 _daemonize();
64404
64405 if (_use_syslog)
64406 openlog("dmeventd", LOG_PID, LOG_DAEMON);
64407
64408 dm_event_log_set(_debug_level, _use_syslog);
64409 dm_log_with_errno_init(_libdm_log);
64410
64411 (void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
64412 if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
64413 exit(EXIT_FAILURE);
64414
64415 atexit(_remove_files_on_exit);
64416 (void) dm_prepare_selinux_context(NULL, 0);
64417
64418 /* Set the rest of the signals to cause '_exit_now' to be set */
64419 signal(SIGTERM, &_exit_handler);
64420 signal(SIGINT, &_exit_handler);
64421 signal(SIGHUP, &_exit_handler);
64422 signal(SIGQUIT, &_exit_handler);
64423
64424#ifdef __linux__
64425 /* Systemd has adjusted oom killer for us already */
64426 if (!_systemd_activation && !_protect_against_oom_killer())
64427 log_warn("WARNING: Failed to protect against OOM killer.");
64428#endif
64429
64430 _init_thread_signals();
64431
64432 pthread_mutex_init(&_global_mutex, NULL);
64433
64434 if (!_systemd_activation && !_open_fifos(&fifos))
64435 exit(EXIT_FIFO_FAILURE);
64436
64437 /* Signal parent, letting them know we are ready to go. */
64438 if (!_foreground)
64439 kill(getppid(), SIGTERM);
64440
64441 log_notice("dmeventd ready for processing.");
64442
64443 _idle_since = time(NULL);
64444
64445 if (_initial_registrations)
64446 _process_initial_registrations();
64447
64448 for (;;) {
64449 if (_idle_since) {
64450 if (_exit_now) {
64451 log_info("dmeventd detected break while being idle "
64452 "for %ld second(s), exiting.",
64453 (long) (time(NULL) - _idle_since));
64454 break;
64455 } else if (idle_exit_timeout) {
64456 now = time(NULL);
64457 if (now < _idle_since)
64458 _idle_since = now; /* clock change? */
64459 now -= _idle_since;
64460 if (now >= idle_exit_timeout) {
64461 log_info("dmeventd was idle for %ld second(s), "
64462 "exiting.", (long) now);
64463 break;
64464 }
64465 }
64466 } else if (_exit_now) {
64467 _exit_now = 0;
64468 /*
64469 * When '_exit_now' is set, signal has been received,
64470 * but can not simply exit unless all
64471 * threads are done processing.
64472 */
64473 log_warn("WARNING: There are still devices being monitored.");
64474 log_warn("WARNING: Refusing to exit.");
64475 }
64476 _process_request(&fifos);
64477 _cleanup_unused_threads();
64478 }
64479
64480 pthread_mutex_destroy(&_global_mutex);
64481
64482 log_notice("dmeventd shutting down.");
64483
64484 if (fifos.client >= 0 && close(fifos.client))
64485 log_sys_error("client close", fifos.client_path);
64486 if (fifos.server >= 0 && close(fifos.server))
64487 log_sys_error("server close", fifos.server_path);
64488
64489 if (_use_syslog)
64490 closelog();
64491
64492 _exit_dm_lib();
64493
64494 exit(EXIT_SUCCESS);
64495}
64496\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/libdevmapper-event.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011671\013062740170\0024253\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
64497 * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
64498 *
64499 * This file is part of the device-mapper userspace tools.
64500 *
64501 * This copyrighted material is made available to anyone wishing to use,
64502 * modify, copy, or redistribute it subject to the terms and conditions
64503 * of the GNU Lesser General Public License v.2.1.
64504 *
64505 * You should have received a copy of the GNU Lesser General Public License
64506 * along with this program; if not, write to the Free Software Foundation,
64507 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
64508 */
64509
64510/*
64511 * Note that this file is released only as part of a technology preview
64512 * and its contents may change in future updates in ways that do not
64513 * preserve compatibility.
64514 */
64515
64516#ifndef LIB_DMEVENT_H
64517#define LIB_DMEVENT_H
64518
64519#include <stdint.h>
64520
64521/*
64522 * Event library interface.
64523 */
64524
64525enum dm_event_mask {
64526 DM_EVENT_SETTINGS_MASK = 0x0000FF,
64527 DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
64528 DM_EVENT_MULTI = 0x000002, /* Report all of them. */
64529
64530 DM_EVENT_ERROR_MASK = 0x00FF00,
64531 DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
64532 DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
64533 DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
64534 DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
64535
64536 DM_EVENT_STATUS_MASK = 0xFF0000,
64537 DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
64538 DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
64539
64540 DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
64541};
64542
64543#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
64544#define DM_EVENT_PROTOCOL_VERSION 2
64545
64546struct dm_task;
64547struct dm_event_handler;
64548
64549struct dm_event_handler *dm_event_handler_create(void);
64550void dm_event_handler_destroy(struct dm_event_handler *dmevh);
64551
64552/*
64553 * Path of shared library to handle events.
64554 *
64555 * All of dmeventd, dso, device_name and uuid strings are duplicated so
64556 * you do not need to keep the pointers valid after the call succeeds.
64557 * They may return -ENOMEM though.
64558 */
64559int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
64560
64561/*
64562 * Path of dmeventd binary.
64563 */
64564int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
64565
64566/*
64567 * Identify the device to monitor by exactly one of device_name, uuid or
64568 * device number. String arguments are duplicated, see above.
64569 */
64570int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
64571
64572int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
64573
64574void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
64575void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
64576void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
64577
64578/*
64579 * Specify mask for events to monitor.
64580 */
64581// FIXME misuse of bitmask as enum
64582void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
64583 enum dm_event_mask evmask);
64584
64585const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
64586const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
64587const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
64588int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
64589int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
64590int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
64591// FIXME misuse of bitmask as enum
64592enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
64593
64594/* FIXME Review interface (what about this next thing?) */
64595int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
64596
64597/*
64598 * Initiate monitoring using dmeventd.
64599 */
64600int dm_event_register_handler(const struct dm_event_handler *dmevh);
64601int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
64602
64603/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
64604void dm_event_log_set(int debug_log_level, int use_syslog);
64605
64606/* Log messages acroding to current debug level */
64607__attribute__((format(printf, 6, 0)))
64608void dm_event_log(const char *subsys, int level, const char *file,
64609 int line, int dm_errno_or_class,
64610 const char *format, va_list ap);
64611/* Macro to route print_log do dm_event_log() */
64612#define DM_EVENT_LOG_FN(subsys) \
64613void print_log(int level, const char *file, int line, int dm_errno_or_class,\
64614 const char *format, ...)\
64615{\
64616 va_list ap;\
64617 va_start(ap, format);\
64618 dm_event_log(subsys, level, file, line, dm_errno_or_class, format, ap);\
64619 va_end(ap);\
64620}
64621
64622/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
64623 detailed descriptions. */
64624// FIXME misuse of bitmask as enum
64625void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
64626int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
64627int unregister_device(const char *device_name, const char *uuid, int major,
64628 int minor, void **user);
64629
64630#endif
64631\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/dmeventd/.exported_symbols\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000140\013062740170\0023701\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dm_event_daemon_init_fifos
64632dm_event_daemon_fini_fifos
64633dm_event_daemon_talk
64634dm_event_get_version
64635\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020310\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockd-dlm.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000043654\013062740170\0023055\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
64636 * Copyright (C) 2014-2015 Red Hat, Inc.
64637 *
64638 * This file is part of LVM2.
64639 *
64640 * This copyrighted material is made available to anyone wishing to use,
64641 * modify, copy, or redistribute it subject to the terms and conditions
64642 * of the GNU Lesser General Public License v.2.1.
64643 */
64644
64645#define _XOPEN_SOURCE 500 /* pthread */
64646#define _ISOC99_SOURCE
64647
64648#include "tool.h"
64649
64650#include "daemon-server.h"
64651#include "xlate.h"
64652
64653#include "lvmlockd-internal.h"
64654#include "lvmlockd-client.h"
64655
64656/*
64657 * Using synchronous _wait dlm apis so do not define _REENTRANT and
64658 * link with non-threaded version of library, libdlm_lt.
64659 */
64660#include "libdlm.h"
64661
64662#include <stddef.h>
64663#include <poll.h>
64664#include <errno.h>
64665#include <endian.h>
64666#include <fcntl.h>
64667#include <byteswap.h>
64668#include <syslog.h>
64669#include <dirent.h>
64670
64671struct lm_dlm {
64672 dlm_lshandle_t *dh;
64673};
64674
64675struct rd_dlm {
64676 struct dlm_lksb lksb;
64677 struct val_blk *vb;
64678};
64679
64680int lm_data_size_dlm(void)
64681{
64682 return sizeof(struct rd_dlm);
64683}
64684
64685/*
64686 * lock_args format
64687 *
64688 * vg_lock_args format for dlm is
64689 * vg_version_string:undefined:cluster_name
64690 *
64691 * lv_lock_args are not used for dlm
64692 *
64693 * version_string is MAJOR.MINOR.PATCH
64694 * undefined may contain ":"
64695 */
64696
64697#define VG_LOCK_ARGS_MAJOR 1
64698#define VG_LOCK_ARGS_MINOR 0
64699#define VG_LOCK_ARGS_PATCH 0
64700
64701static int dlm_has_lvb_bug;
64702
64703static int cluster_name_from_args(char *vg_args, char *clustername)
64704{
64705 return last_string_from_args(vg_args, clustername);
64706}
64707
64708static int check_args_version(char *vg_args)
64709{
64710 unsigned int major = 0;
64711 int rv;
64712
64713 rv = version_from_args(vg_args, &major, NULL, NULL);
64714 if (rv < 0) {
64715 log_error("check_args_version %s error %d", vg_args, rv);
64716 return rv;
64717 }
64718
64719 if (major > VG_LOCK_ARGS_MAJOR) {
64720 log_error("check_args_version %s major %d %d", vg_args, major, VG_LOCK_ARGS_MAJOR);
64721 return -1;
64722 }
64723
64724 return 0;
64725}
64726
64727/* This will be set after dlm_controld is started. */
64728#define DLM_CLUSTER_NAME_PATH "/sys/kernel/config/dlm/cluster/cluster_name"
64729
64730static int read_cluster_name(char *clustername)
64731{
64732 static const char close_error_msg[] = "read_cluster_name: close_error %d";
64733 char *n;
64734 int fd;
64735 int rv;
64736
64737 if (daemon_test) {
64738 sprintf(clustername, "%s", "test");
64739 return 0;
64740 }
64741
64742 fd = open(DLM_CLUSTER_NAME_PATH, O_RDONLY);
64743 if (fd < 0) {
64744 log_debug("read_cluster_name: open error %d, check dlm_controld", fd);
64745 return fd;
64746 }
64747
64748 rv = read(fd, clustername, MAX_ARGS);
64749 if (rv < 0) {
64750 log_error("read_cluster_name: cluster name read error %d, check dlm_controld", fd);
64751 if (close(fd))
64752 log_error(close_error_msg, fd);
64753 return rv;
64754 }
64755
64756 n = strstr(clustername, "\n");
64757 if (n)
64758 *n = '\0';
64759 if (close(fd))
64760 log_error(close_error_msg, fd);
64761 return 0;
64762}
64763
64764int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
64765{
64766 char clustername[MAX_ARGS+1];
64767 char lock_args_version[MAX_ARGS+1];
64768 int rv;
64769
64770 memset(clustername, 0, sizeof(clustername));
64771 memset(lock_args_version, 0, sizeof(lock_args_version));
64772
64773 snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
64774 VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
64775
64776 rv = read_cluster_name(clustername);
64777 if (rv < 0)
64778 return -EMANAGER;
64779
64780 if (strlen(clustername) + strlen(lock_args_version) + 2 > MAX_ARGS) {
64781 log_error("init_vg_dlm args too long");
64782 return -EARGS;
64783 }
64784
64785 snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, clustername);
64786 rv = 0;
64787
64788 log_debug("init_vg_dlm done %s vg_args %s", ls_name, vg_args);
64789 return rv;
64790}
64791
64792int lm_prepare_lockspace_dlm(struct lockspace *ls)
64793{
64794 char sys_clustername[MAX_ARGS+1];
64795 char arg_clustername[MAX_ARGS+1];
64796 uint32_t major = 0, minor = 0, patch = 0;
64797 struct lm_dlm *lmd;
64798 int rv;
64799
64800 if (daemon_test)
64801 goto skip_args;
64802
64803 memset(sys_clustername, 0, sizeof(sys_clustername));
64804 memset(arg_clustername, 0, sizeof(arg_clustername));
64805
64806 rv = read_cluster_name(sys_clustername);
64807 if (rv < 0)
64808 return -EMANAGER;
64809
64810 rv = dlm_kernel_version(&major, &minor, &patch);
64811 if (rv < 0) {
64812 log_error("prepare_lockspace_dlm kernel_version not detected %d", rv);
64813 dlm_has_lvb_bug = 1;
64814 }
64815
64816 if ((major == 6) && (minor == 0) && (patch == 1)) {
64817 log_debug("dlm kernel version %u.%u.%u has lvb bug", major, minor, patch);
64818 dlm_has_lvb_bug = 1;
64819 }
64820
64821 if (!ls->vg_args[0]) {
64822 /* global lockspace has no vg args */
64823 goto skip_args;
64824 }
64825
64826 rv = check_args_version(ls->vg_args);
64827 if (rv < 0)
64828 return -EARGS;
64829
64830 rv = cluster_name_from_args(ls->vg_args, arg_clustername);
64831 if (rv < 0) {
64832 log_error("prepare_lockspace_dlm %s no cluster name from args %s", ls->name, ls->vg_args);
64833 return -EARGS;
64834 }
64835
64836 if (strcmp(sys_clustername, arg_clustername)) {
64837 log_error("prepare_lockspace_dlm %s mismatching cluster names sys %s arg %s",
64838 ls->name, sys_clustername, arg_clustername);
64839 return -EARGS;
64840 }
64841
64842 skip_args:
64843 lmd = malloc(sizeof(struct lm_dlm));
64844 if (!lmd)
64845 return -ENOMEM;
64846
64847 ls->lm_data = lmd;
64848 return 0;
64849}
64850
64851int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
64852{
64853 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
64854
64855 if (daemon_test)
64856 return 0;
64857
64858 if (adopt)
64859 lmd->dh = dlm_open_lockspace(ls->name);
64860 else
64861 lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
64862
64863 if (!lmd->dh) {
64864 log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
64865 free(lmd);
64866 ls->lm_data = NULL;
64867 return -1;
64868 }
64869
64870 return 0;
64871}
64872
64873int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
64874{
64875 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
64876 int rv;
64877
64878 if (daemon_test)
64879 goto out;
64880
64881 /*
64882 * If free_vg is set, it means we are doing vgremove, and we may want
64883 * to tell any other nodes to leave the lockspace. This is not really
64884 * necessary since there should be no harm in having an unused
64885 * lockspace sitting around. A new "notification lock" would need to
64886 * be added with a callback to signal this.
64887 */
64888
64889 rv = dlm_release_lockspace(ls->name, lmd->dh, 1);
64890 if (rv < 0) {
64891 log_error("rem_lockspace_dlm error %d", rv);
64892 return rv;
64893 }
64894 out:
64895 free(lmd);
64896 ls->lm_data = NULL;
64897 return 0;
64898}
64899
64900static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
64901{
64902 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
64903 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
64904 uint32_t flags = 0;
64905 char *buf;
64906 int rv;
64907
64908 if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
64909 buf = malloc(sizeof(struct val_blk) + DLM_LVB_LEN);
64910 if (!buf)
64911 return -ENOMEM;
64912 memset(buf, 0, sizeof(struct val_blk) + DLM_LVB_LEN);
64913
64914 rdd->vb = (struct val_blk *)buf;
64915 rdd->lksb.sb_lvbptr = buf + sizeof(struct val_blk);
64916
64917 flags |= LKF_VALBLK;
64918 }
64919
64920 if (!with_lock_nl)
64921 goto out;
64922
64923 /* because this is a new NL lock request */
64924 flags |= LKF_EXPEDITE;
64925
64926 if (daemon_test)
64927 goto out;
64928
64929 rv = dlm_ls_lock_wait(lmd->dh, LKM_NLMODE, &rdd->lksb, flags,
64930 r->name, strlen(r->name),
64931 0, NULL, NULL, NULL);
64932 if (rv < 0) {
64933 log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv);
64934 return rv;
64935 }
64936 out:
64937 return 0;
64938}
64939
64940int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
64941{
64942 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
64943 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
64944 struct dlm_lksb *lksb;
64945 int rv = 0;
64946
64947 if (daemon_test)
64948 goto out;
64949
64950 lksb = &rdd->lksb;
64951
64952 if (!lksb->sb_lkid)
64953 goto out;
64954
64955 rv = dlm_ls_unlock_wait(lmd->dh, lksb->sb_lkid, 0, lksb);
64956 if (rv < 0) {
64957 log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
64958 }
64959 out:
64960 if (rdd->vb)
64961 free(rdd->vb);
64962
64963 memset(rdd, 0, sizeof(struct rd_dlm));
64964 r->lm_init = 0;
64965 return rv;
64966}
64967
64968static int to_dlm_mode(int ld_mode)
64969{
64970 switch (ld_mode) {
64971 case LD_LK_EX:
64972 return LKM_EXMODE;
64973 case LD_LK_SH:
64974 return LKM_PRMODE;
64975 };
64976 return -1;
64977}
64978
64979static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
64980 struct val_blk *vb_out)
64981{
64982 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
64983 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
64984 struct dlm_lksb *lksb;
64985 uint32_t flags = 0;
64986 int mode;
64987 int rv;
64988
64989 memset(vb_out, 0, sizeof(struct val_blk));
64990
64991 if (!r->lm_init) {
64992 rv = lm_add_resource_dlm(ls, r, 0);
64993 if (rv < 0)
64994 return rv;
64995 r->lm_init = 1;
64996 }
64997
64998 lksb = &rdd->lksb;
64999
65000 flags |= LKF_PERSISTENT;
65001 flags |= LKF_ORPHAN;
65002
65003 if (rdd->vb)
65004 flags |= LKF_VALBLK;
65005
65006 mode = to_dlm_mode(ld_mode);
65007 if (mode < 0) {
65008 log_error("adopt_dlm invalid mode %d", ld_mode);
65009 rv = -EINVAL;
65010 goto fail;
65011 }
65012
65013 log_debug("S %s R %s adopt_dlm", ls->name, r->name);
65014
65015 if (daemon_test)
65016 return 0;
65017
65018 /*
65019 * dlm returns 0 for success, -EAGAIN if an orphan is
65020 * found with another mode, and -ENOENT if no orphan.
65021 *
65022 * cast/bast/param are (void *)1 because the kernel
65023 * returns errors if some are null.
65024 */
65025
65026 rv = dlm_ls_lockx(lmd->dh, mode, lksb, flags,
65027 r->name, strlen(r->name), 0,
65028 (void *)1, (void *)1, (void *)1,
65029 NULL, NULL);
65030
65031 if (rv == -1 && errno == -EAGAIN) {
65032 log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
65033 ls->name, r->name, ld_mode);
65034 rv = -EUCLEAN;
65035 goto fail;
65036 }
65037 if (rv < 0) {
65038 log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
65039 ls->name, r->name, mode, flags, rv, errno);
65040 goto fail;
65041 }
65042
65043 /*
65044 * FIXME: For GL/VG locks we probably want to read the lvb,
65045 * especially if adopting an ex lock, because when we
65046 * release this adopted ex lock we may want to write new
65047 * lvb values based on the current lvb values (at lease
65048 * in the GL case where we increment the current values.)
65049 *
65050 * It should be possible to read the lvb by requesting
65051 * this lock in the same mode it's already in.
65052 */
65053
65054 return rv;
65055
65056 fail:
65057 lm_rem_resource_dlm(ls, r);
65058 return rv;
65059}
65060
65061/*
65062 * Use PERSISTENT so that if lvmlockd exits while holding locks,
65063 * the locks will remain orphaned in the dlm, still protecting what
65064 * they were acquired to protect.
65065 */
65066
65067int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
65068 struct val_blk *vb_out, int adopt)
65069{
65070 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
65071 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
65072 struct dlm_lksb *lksb;
65073 struct val_blk vb;
65074 uint32_t flags = 0;
65075 int mode;
65076 int rv;
65077
65078 if (adopt) {
65079 /* When adopting, we don't follow the normal method
65080 of acquiring a NL lock then converting it to the
65081 desired mode. */
65082 return lm_adopt_dlm(ls, r, ld_mode, vb_out);
65083 }
65084
65085 if (!r->lm_init) {
65086 rv = lm_add_resource_dlm(ls, r, 1);
65087 if (rv < 0)
65088 return rv;
65089 r->lm_init = 1;
65090 }
65091
65092 lksb = &rdd->lksb;
65093
65094 flags |= LKF_CONVERT;
65095 flags |= LKF_NOQUEUE;
65096 flags |= LKF_PERSISTENT;
65097
65098 if (rdd->vb)
65099 flags |= LKF_VALBLK;
65100
65101 mode = to_dlm_mode(ld_mode);
65102 if (mode < 0) {
65103 log_error("lock_dlm invalid mode %d", ld_mode);
65104 return -EINVAL;
65105 }
65106
65107 log_debug("S %s R %s lock_dlm", ls->name, r->name);
65108
65109 if (daemon_test) {
65110 if (rdd->vb) {
65111 vb_out->version = le16_to_cpu(rdd->vb->version);
65112 vb_out->flags = le16_to_cpu(rdd->vb->flags);
65113 vb_out->r_version = le32_to_cpu(rdd->vb->r_version);
65114 }
65115 return 0;
65116 }
65117
65118 /*
65119 * The dlm lvb bug means that converting NL->EX will not return
65120 * the latest lvb, so we have to convert NL->PR->EX to reread it.
65121 */
65122 if (dlm_has_lvb_bug && (ld_mode == LD_LK_EX)) {
65123 rv = dlm_ls_lock_wait(lmd->dh, LKM_PRMODE, lksb, flags,
65124 r->name, strlen(r->name),
65125 0, NULL, NULL, NULL);
65126 if (rv == -1) {
65127 log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d",
65128 ls->name, r->name, mode, rv);
65129 goto lockrv;
65130 }
65131
65132 /* Fall through to request EX. */
65133 }
65134
65135 rv = dlm_ls_lock_wait(lmd->dh, mode, lksb, flags,
65136 r->name, strlen(r->name),
65137 0, NULL, NULL, NULL);
65138lockrv:
65139 if (rv == -1 && errno == EAGAIN) {
65140 log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
65141 return -EAGAIN;
65142 }
65143 if (rv < 0) {
65144 log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
65145 return rv;
65146 }
65147
65148 if (rdd->vb) {
65149 if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
65150 log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
65151 memset(rdd->vb, 0, sizeof(struct val_blk));
65152 memset(vb_out, 0, sizeof(struct val_blk));
65153 goto out;
65154 }
65155
65156 /*
65157 * 'vb' contains disk endian values, not host endian.
65158 * It is copied directly to rdd->vb which is also kept
65159 * in disk endian form.
65160 * vb_out is returned to the caller in host endian form.
65161 */
65162 memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
65163 memcpy(rdd->vb, &vb, sizeof(vb));
65164
65165 vb_out->version = le16_to_cpu(vb.version);
65166 vb_out->flags = le16_to_cpu(vb.flags);
65167 vb_out->r_version = le32_to_cpu(vb.r_version);
65168 }
65169out:
65170 return 0;
65171}
65172
65173int lm_convert_dlm(struct lockspace *ls, struct resource *r,
65174 int ld_mode, uint32_t r_version)
65175{
65176 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
65177 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
65178 struct dlm_lksb *lksb = &rdd->lksb;
65179 uint32_t mode;
65180 uint32_t flags = 0;
65181 int rv;
65182
65183 log_debug("S %s R %s convert_dlm", ls->name, r->name);
65184
65185 flags |= LKF_CONVERT;
65186 flags |= LKF_NOQUEUE;
65187 flags |= LKF_PERSISTENT;
65188
65189 if (rdd->vb && r_version && (r->mode == LD_LK_EX)) {
65190 if (!rdd->vb->version) {
65191 /* first time vb has been written */
65192 rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
65193 }
65194 rdd->vb->r_version = cpu_to_le32(r_version);
65195 memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
65196
65197 log_debug("S %s R %s convert_dlm set r_version %u",
65198 ls->name, r->name, r_version);
65199
65200 flags |= LKF_VALBLK;
65201 }
65202
65203 mode = to_dlm_mode(ld_mode);
65204
65205 if (daemon_test)
65206 return 0;
65207
65208 rv = dlm_ls_lock_wait(lmd->dh, mode, lksb, flags,
65209 r->name, strlen(r->name),
65210 0, NULL, NULL, NULL);
65211 if (rv == -1 && errno == EAGAIN) {
65212 /* FIXME: When does this happen? Should something different be done? */
65213 log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
65214 return -EAGAIN;
65215 }
65216 if (rv < 0) {
65217 log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
65218 }
65219 return rv;
65220}
65221
65222int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
65223 uint32_t r_version, uint32_t lmu_flags)
65224{
65225 struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
65226 struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
65227 struct dlm_lksb *lksb = &rdd->lksb;
65228 struct val_blk vb_prev;
65229 struct val_blk vb_next;
65230 uint32_t flags = 0;
65231 int new_vb = 0;
65232 int rv;
65233
65234 /*
65235 * Do not set PERSISTENT, because we don't need an orphan
65236 * NL lock to protect anything.
65237 */
65238
65239 flags |= LKF_CONVERT;
65240
65241 if (rdd->vb && (r->mode == LD_LK_EX)) {
65242
65243 /* vb_prev and vb_next are in disk endian form */
65244 memcpy(&vb_prev, rdd->vb, sizeof(struct val_blk));
65245 memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
65246
65247 if (!vb_prev.version) {
65248 vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
65249 new_vb = 1;
65250 }
65251
65252 if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
65253 vb_next.flags = cpu_to_le16(VBF_REMOVED);
65254 new_vb = 1;
65255 }
65256
65257 if (r_version) {
65258 vb_next.r_version = cpu_to_le32(r_version);
65259 new_vb = 1;
65260 }
65261
65262 if (new_vb) {
65263 memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
65264 memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
65265
65266 log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
65267 ls->name, r->name,
65268 le16_to_cpu(vb_prev.version),
65269 le16_to_cpu(vb_prev.flags),
65270 le32_to_cpu(vb_prev.r_version),
65271 le16_to_cpu(vb_next.version),
65272 le16_to_cpu(vb_next.flags),
65273 le32_to_cpu(vb_next.r_version));
65274 } else {
65275 log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
65276 }
65277
65278 flags |= LKF_VALBLK;
65279 } else {
65280 log_debug("S %s R %s unlock_dlm", ls->name, r->name);
65281 }
65282
65283 if (daemon_test)
65284 return 0;
65285
65286 rv = dlm_ls_lock_wait(lmd->dh, LKM_NLMODE, lksb, flags,
65287 r->name, strlen(r->name),
65288 0, NULL, NULL, NULL);
65289 if (rv < 0) {
65290 log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
65291 }
65292
65293 return rv;
65294}
65295
65296/*
65297 * This list could be read from dlm_controld via libdlmcontrol,
65298 * but it's simpler to get it from sysfs.
65299 */
65300
65301#define DLM_LOCKSPACES_PATH "/sys/kernel/config/dlm/cluster/spaces"
65302
65303/*
65304 * FIXME: this should be implemented differently.
65305 * It's not nice to use an aspect of the dlm clustering
65306 * implementation, which could change. It would be
65307 * better to do something like use a special lock in the
65308 * lockspace that was held PR by all nodes, and then an
65309 * EX request on it could check if it's started (and
65310 * possibly also notify others to stop it automatically).
65311 * Or, possibly an enhancement to libdlm that would give
65312 * info about lockspace members.
65313 *
65314 * (We could let the VG be removed while others still
65315 * have the lockspace running, which largely works, but
65316 * introduces problems if another VG with the same name is
65317 * recreated while others still have the lockspace running
65318 * for the previous VG. We'd also want a way to clean up
65319 * the stale lockspaces on the others eventually.)
65320 */
65321
65322int lm_hosts_dlm(struct lockspace *ls, int notify)
65323{
65324 static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
65325 char ls_nodes_path[PATH_MAX];
65326 struct dirent *de;
65327 DIR *ls_dir;
65328 int count = 0;
65329
65330 if (daemon_test)
65331 return 0;
65332
65333 memset(ls_nodes_path, 0, sizeof(ls_nodes_path));
65334 snprintf(ls_nodes_path, PATH_MAX-1, "%s/%s/nodes",
65335 DLM_LOCKSPACES_PATH, ls->name);
65336
65337 if (!(ls_dir = opendir(ls_nodes_path)))
65338 return -ECONNREFUSED;
65339
65340 while ((de = readdir(ls_dir))) {
65341 if (de->d_name[0] == '.')
65342 continue;
65343 count++;
65344 }
65345
65346 if (closedir(ls_dir))
65347 log_error(closedir_err_msg);
65348
65349 if (!count) {
65350 log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
65351 return 0;
65352 }
65353
65354 /*
65355 * Assume that a count of one node represents ourself,
65356 * and any value over one represents other nodes.
65357 */
65358
65359 return count - 1;
65360}
65361
65362int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
65363{
65364 static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
65365 struct lockspace *ls;
65366 struct dirent *de;
65367 DIR *ls_dir;
65368
65369 if (!(ls_dir = opendir(DLM_LOCKSPACES_PATH)))
65370 return -ECONNREFUSED;
65371
65372 while ((de = readdir(ls_dir))) {
65373 if (de->d_name[0] == '.')
65374 continue;
65375
65376 if (strncmp(de->d_name, LVM_LS_PREFIX, strlen(LVM_LS_PREFIX)))
65377 continue;
65378
65379 if (!(ls = alloc_lockspace())) {
65380 if (closedir(ls_dir))
65381 log_error(closedir_err_msg);
65382 return -ENOMEM;
65383 }
65384
65385 ls->lm_type = LD_LM_DLM;
65386 strncpy(ls->name, de->d_name, MAX_NAME);
65387 strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), MAX_NAME);
65388 list_add_tail(&ls->list, ls_rejoin);
65389 }
65390
65391 if (closedir(ls_dir))
65392 log_error(closedir_err_msg);
65393 return 0;
65394}
65395
65396int lm_is_running_dlm(void)
65397{
65398 char sys_clustername[MAX_ARGS+1];
65399 int rv;
65400
65401 if (daemon_test)
65402 return gl_use_dlm;
65403
65404 memset(sys_clustername, 0, sizeof(sys_clustername));
65405
65406 rv = read_cluster_name(sys_clustername);
65407 if (rv < 0)
65408 return 0;
65409 return 1;
65410}
65411
65412\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockctl.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000040613\013062740170\0022632\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
65413 * Copyright (C) 2014-2015 Red Hat, Inc.
65414 *
65415 * This file is part of LVM2.
65416 *
65417 * This copyrighted material is made available to anyone wishing to use,
65418 * modify, copy, or redistribute it subject to the terms and conditions
65419 * of the GNU Lesser General Public License v.2.1.
65420 */
65421
65422#include "tool.h"
65423
65424#include "lvmlockd-client.h"
65425
65426#include <stddef.h>
65427#include <getopt.h>
65428#include <signal.h>
65429#include <errno.h>
65430#include <fcntl.h>
65431#include <syslog.h>
65432#include <sys/socket.h>
65433#include <sys/un.h>
65434
65435static int quit = 0;
65436static int info = 0;
65437static int dump = 0;
65438static int wait_opt = 0;
65439static int force_opt = 0;
65440static int kill_vg = 0;
65441static int drop_vg = 0;
65442static int gl_enable = 0;
65443static int gl_disable = 0;
65444static int stop_lockspaces = 0;
65445static char *arg_vg_name = NULL;
65446
65447#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
65448#define DUMP_BUF_SIZE (1024 * 1024)
65449static char dump_buf[DUMP_BUF_SIZE+1];
65450static int dump_len;
65451static struct sockaddr_un dump_addr;
65452static socklen_t dump_addrlen;
65453
65454daemon_handle _lvmlockd;
65455
65456#define log_error(fmt, args...) \
65457do { \
65458 printf(fmt "\n", ##args); \
65459} while (0)
65460
65461#define MAX_LINE 512
65462
65463/* copied from lvmlockd-internal.h */
65464#define MAX_NAME 64
65465#define MAX_ARGS 64
65466
65467/*
65468 * lvmlockd dumps the client info before the lockspaces,
65469 * so we can look up client info when printing lockspace info.
65470 */
65471
65472#define MAX_CLIENTS 100
65473
65474struct client_info {
65475 uint32_t client_id;
65476 int pid;
65477 char name[MAX_NAME+1];
65478};
65479
65480static struct client_info clients[MAX_CLIENTS];
65481static int num_clients;
65482
65483static void save_client_info(char *line)
65484{
65485 uint32_t pid = 0;
65486 int fd = 0;
65487 int pi = 0;
65488 uint32_t client_id = 0;
65489 char name[MAX_NAME+1] = { 0 };
65490
65491 (void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
65492 &pid, &fd, &pi, &client_id, name);
65493
65494 clients[num_clients].client_id = client_id;
65495 clients[num_clients].pid = pid;
65496 strcpy(clients[num_clients].name, name);
65497 num_clients++;
65498}
65499
65500static void find_client_info(uint32_t client_id, uint32_t *pid, char *cl_name)
65501{
65502 int i;
65503
65504 for (i = 0; i < num_clients; i++) {
65505 if (clients[i].client_id == client_id) {
65506 *pid = clients[i].pid;
65507 strcpy(cl_name, clients[i].name);
65508 return;
65509 }
65510 }
65511}
65512
65513static int first_ls = 1;
65514
65515static void format_info_ls(char *line)
65516{
65517 char ls_name[MAX_NAME+1] = { 0 };
65518 char vg_name[MAX_NAME+1] = { 0 };
65519 char vg_uuid[MAX_NAME+1] = { 0 };
65520 char vg_sysid[MAX_NAME+1] = { 0 };
65521 char lock_args[MAX_ARGS+1] = { 0 };
65522 char lock_type[MAX_NAME+1] = { 0 };
65523
65524 (void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
65525 ls_name, vg_name, vg_uuid, vg_sysid, lock_args, lock_type);
65526
65527 if (!first_ls)
65528 printf("\n");
65529 first_ls = 0;
65530
65531 printf("VG %s lock_type=%s %s\n", vg_name, lock_type, vg_uuid);
65532
65533 printf("LS %s %s\n", lock_type, ls_name);
65534}
65535
65536static void format_info_ls_action(char *line)
65537{
65538 uint32_t client_id = 0;
65539 char flags[MAX_NAME+1] = { 0 };
65540 char version[MAX_NAME+1] = { 0 };
65541 char op[MAX_NAME+1] = { 0 };
65542 uint32_t pid = 0;
65543 char cl_name[MAX_NAME+1] = { 0 };
65544
65545 (void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
65546 &client_id, flags, version, op);
65547
65548 find_client_info(client_id, &pid, cl_name);
65549
65550 printf("OP %s pid %u (%s)\n", op, pid, cl_name);
65551}
65552
65553static void format_info_r(char *line, char *r_name_out, char *r_type_out)
65554{
65555 char r_name[MAX_NAME+1] = { 0 };
65556 char r_type[4] = { 0 };
65557 char mode[4] = { 0 };
65558 char sh_count[MAX_NAME+1] = { 0 };
65559 uint32_t ver = 0;
65560
65561 (void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
65562 r_name, r_type, mode, sh_count, &ver);
65563
65564 strcpy(r_name_out, r_name);
65565 strcpy(r_type_out, r_type);
65566
65567 /* when mode is not un, wait and print each lk line */
65568 if (strcmp(mode, "un"))
65569 return;
65570
65571 /* when mode is un, there will be no lk lines, so print now */
65572
65573 if (!strcmp(r_type, "gl")) {
65574 printf("LK GL un ver %u\n", ver);
65575
65576 } else if (!strcmp(r_type, "vg")) {
65577 printf("LK VG un ver %u\n", ver);
65578
65579 } else if (!strcmp(r_type, "lv")) {
65580 printf("LK LV un %s\n", r_name);
65581 }
65582}
65583
65584static void format_info_lk(char *line, char *r_name, char *r_type)
65585{
65586 char mode[4] = { 0 };
65587 uint32_t ver = 0;
65588 char flags[MAX_NAME+1] = { 0 };
65589 uint32_t client_id = 0;
65590 uint32_t pid = 0;
65591 char cl_name[MAX_NAME+1] = { 0 };
65592
65593 if (!r_name[0] || !r_type[0]) {
65594 printf("format_info_lk error r_name %s r_type %s\n", r_name, r_type);
65595 printf("%s\n", line);
65596 return;
65597 }
65598
65599 (void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
65600 mode, &ver, flags, &client_id);
65601
65602 find_client_info(client_id, &pid, cl_name);
65603
65604 if (!strcmp(r_type, "gl")) {
65605 printf("LK GL %s ver %u pid %u (%s)\n", mode, ver, pid, cl_name);
65606
65607 } else if (!strcmp(r_type, "vg")) {
65608 printf("LK VG %s ver %u pid %u (%s)\n", mode, ver, pid, cl_name);
65609
65610 } else if (!strcmp(r_type, "lv")) {
65611 printf("LK LV %s %s\n", mode, r_name);
65612 }
65613}
65614
65615static void format_info_r_action(char *line, char *r_name, char *r_type)
65616{
65617 uint32_t client_id = 0;
65618 char flags[MAX_NAME+1] = { 0 };
65619 char version[MAX_NAME+1] = { 0 };
65620 char op[MAX_NAME+1] = { 0 };
65621 char rt[4] = { 0 };
65622 char mode[4] = { 0 };
65623 char lm[MAX_NAME+1] = { 0 };
65624 char result[MAX_NAME+1] = { 0 };
65625 char lm_rv[MAX_NAME+1] = { 0 };
65626 uint32_t pid = 0;
65627 char cl_name[MAX_NAME+1] = { 0 };
65628
65629 if (!r_name[0] || !r_type[0]) {
65630 printf("format_info_r_action error r_name %s r_type %s\n", r_name, r_type);
65631 printf("%s\n", line);
65632 return;
65633 }
65634
65635 (void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
65636 &client_id, flags, version, op, rt, mode, lm, result, lm_rv);
65637
65638 find_client_info(client_id, &pid, cl_name);
65639
65640 if (strcmp(op, "lock")) {
65641 printf("OP %s pid %u (%s)\n", op, pid, cl_name);
65642 return;
65643 }
65644
65645 if (!strcmp(r_type, "gl")) {
65646 printf("LW GL %s ver %u pid %u (%s)\n", mode, 0, pid, cl_name);
65647
65648 } else if (!strcmp(r_type, "vg")) {
65649 printf("LW VG %s ver %u pid %u (%s)\n", mode, 0, pid, cl_name);
65650
65651 } else if (!strcmp(r_type, "lv")) {
65652 printf("LW LV %s %s\n", mode, r_name);
65653 }
65654}
65655
65656static void format_info_line(char *line, char *r_name, char *r_type)
65657{
65658 if (!strncmp(line, "info=structs ", strlen("info=structs "))) {
65659 /* only print this in the raw info dump */
65660
65661 } else if (!strncmp(line, "info=client ", strlen("info=client "))) {
65662 save_client_info(line);
65663
65664 } else if (!strncmp(line, "info=ls ", strlen("info=ls "))) {
65665 format_info_ls(line);
65666
65667 } else if (!strncmp(line, "info=ls_action ", strlen("info=ls_action "))) {
65668 format_info_ls_action(line);
65669
65670 } else if (!strncmp(line, "info=r ", strlen("info=r "))) {
65671 /*
65672 * r_name/r_type are reset when a new resource is found.
65673 * They are reused for the lock and action lines that
65674 * follow a resource line.
65675 */
65676 memset(r_name, 0, MAX_NAME+1);
65677 memset(r_type, 0, MAX_NAME+1);
65678 format_info_r(line, r_name, r_type);
65679
65680 } else if (!strncmp(line, "info=lk ", strlen("info=lk "))) {
65681 /* will use info from previous r */
65682 format_info_lk(line, r_name, r_type);
65683
65684 } else if (!strncmp(line, "info=r_action ", strlen("info=r_action "))) {
65685 /* will use info from previous r */
65686 format_info_r_action(line, r_name, r_type);
65687 } else {
65688 printf("UN %s\n", line);
65689 }
65690}
65691
65692static void format_info(void)
65693{
65694 char line[MAX_LINE];
65695 char r_name[MAX_NAME+1];
65696 char r_type[MAX_NAME+1];
65697 int i, j;
65698
65699 j = 0;
65700 memset(line, 0, sizeof(line));
65701
65702 for (i = 0; i < dump_len; i++) {
65703 line[j++] = dump_buf[i];
65704
65705 if ((line[j-1] == '\n') || (line[j-1] == '\0')) {
65706 format_info_line(line, r_name, r_type);
65707 j = 0;
65708 memset(line, 0, sizeof(line));
65709 }
65710 }
65711}
65712
65713
65714static daemon_reply _lvmlockd_send(const char *req_name, ...)
65715{
65716 va_list ap;
65717 daemon_reply repl;
65718 daemon_request req;
65719
65720 req = daemon_request_make(req_name);
65721
65722 va_start(ap, req_name);
65723 daemon_request_extend_v(req, ap);
65724 va_end(ap);
65725
65726 repl = daemon_send(_lvmlockd, req);
65727
65728 daemon_request_destroy(req);
65729
65730 return repl;
65731}
65732
65733/* See the same in lib/locking/lvmlockd.c */
65734#define NO_LOCKD_RESULT -1000
65735
65736static int _lvmlockd_result(daemon_reply reply, int *result)
65737{
65738 int reply_result;
65739
65740 if (reply.error) {
65741 log_error("lvmlockd_result reply error %d", reply.error);
65742 return 0;
65743 }
65744
65745 if (strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
65746 log_error("lvmlockd_result bad response");
65747 return 0;
65748 }
65749
65750 reply_result = daemon_reply_int(reply, "op_result", NO_LOCKD_RESULT);
65751 if (reply_result == -1000) {
65752 log_error("lvmlockd_result no op_result");
65753 return 0;
65754 }
65755
65756 *result = reply_result;
65757
65758 return 1;
65759}
65760
65761static int do_quit(void)
65762{
65763 daemon_reply reply;
65764 int rv = 0;
65765
65766 reply = daemon_send_simple(_lvmlockd, "quit", NULL);
65767
65768 if (reply.error) {
65769 log_error("reply error %d", reply.error);
65770 rv = reply.error;
65771 }
65772
65773 daemon_reply_destroy(reply);
65774 return rv;
65775}
65776
65777static int setup_dump_socket(void)
65778{
65779 int s, rv;
65780
65781 s = socket(AF_LOCAL, SOCK_DGRAM, 0);
65782 if (s < 0)
65783 return s;
65784
65785 memset(&dump_addr, 0, sizeof(dump_addr));
65786 dump_addr.sun_family = AF_LOCAL;
65787 strcpy(&dump_addr.sun_path[1], DUMP_SOCKET_NAME);
65788 dump_addrlen = sizeof(sa_family_t) + strlen(dump_addr.sun_path+1) + 1;
65789
65790 rv = bind(s, (struct sockaddr *) &dump_addr, dump_addrlen);
65791 if (rv < 0) {
65792 rv = -errno;
65793 if (!close(s))
65794 log_error("failed to close dump socket");
65795 return rv;
65796 }
65797
65798 return s;
65799}
65800
65801static int do_dump(const char *req_name)
65802{
65803 daemon_reply reply;
65804 int result;
65805 int fd, rv = 0;
65806 int count = 0;
65807
65808 fd = setup_dump_socket();
65809 if (fd < 0) {
65810 log_error("socket error %d", fd);
65811 return fd;
65812 }
65813
65814 reply = daemon_send_simple(_lvmlockd, req_name, NULL);
65815
65816 if (reply.error) {
65817 log_error("reply error %d", reply.error);
65818 rv = reply.error;
65819 goto out;
65820 }
65821
65822 result = daemon_reply_int(reply, "result", 0);
65823 dump_len = daemon_reply_int(reply, "dump_len", 0);
65824
65825 daemon_reply_destroy(reply);
65826
65827 if (result < 0) {
65828 rv = result;
65829 log_error("result %d", result);
65830 }
65831
65832 if (!dump_len)
65833 goto out;
65834
65835 memset(dump_buf, 0, sizeof(dump_buf));
65836
65837retry:
65838 rv = recvfrom(fd, dump_buf + count, dump_len - count, MSG_WAITALL,
65839 (struct sockaddr *)&dump_addr, &dump_addrlen);
65840 if (rv < 0) {
65841 log_error("recvfrom error %d %d", rv, errno);
65842 rv = -errno;
65843 goto out;
65844 }
65845 count += rv;
65846
65847 if (count < dump_len)
65848 goto retry;
65849
65850 rv = 0;
65851 if ((info && dump) || !strcmp(req_name, "dump"))
65852 printf("%s\n", dump_buf);
65853 else
65854 format_info();
65855out:
65856 if (close(fd))
65857 log_error("failed to close dump socket %d", fd);
65858 return rv;
65859}
65860
65861static int do_able(const char *req_name)
65862{
65863 daemon_reply reply;
65864 int result;
65865 int rv;
65866
65867 reply = _lvmlockd_send(req_name,
65868 "cmd = %s", "lvmlockctl",
65869 "pid = " FMTd64, (int64_t) getpid(),
65870 "vg_name = %s", arg_vg_name,
65871 NULL);
65872
65873 if (!_lvmlockd_result(reply, &result)) {
65874 log_error("lvmlockd result %d", result);
65875 rv = result;
65876 } else {
65877 rv = 0;
65878 }
65879
65880 daemon_reply_destroy(reply);
65881 return rv;
65882}
65883
65884static int do_stop_lockspaces(void)
65885{
65886 daemon_reply reply;
65887 char opts[32];
65888 int result;
65889 int rv;
65890
65891 memset(opts, 0, sizeof(opts));
65892
65893 if (wait_opt)
65894 strcat(opts, "wait ");
65895 if (force_opt)
65896 strcat(opts, "force ");
65897
65898 reply = _lvmlockd_send("stop_all",
65899 "cmd = %s", "lvmlockctl",
65900 "pid = " FMTd64, (int64_t) getpid(),
65901 "opts = %s", opts[0] ? opts : "none",
65902 NULL);
65903
65904 if (!_lvmlockd_result(reply, &result)) {
65905 log_error("lvmlockd result %d", result);
65906 rv = result;
65907 } else {
65908 rv = 0;
65909 }
65910
65911 daemon_reply_destroy(reply);
65912 return rv;
65913}
65914
65915static int do_kill(void)
65916{
65917 daemon_reply reply;
65918 int result;
65919 int rv;
65920
65921 syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
65922 /* These two lines explain the manual alternative to the FIXME below. */
65923 syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
65924 syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
65925
65926 /*
65927 * It may not be strictly necessary to notify lvmlockd of the kill, but
65928 * lvmlockd can use this information to avoid attempting any new lock
65929 * requests in the VG (which would fail anyway), and can return an
65930 * error indicating that the VG has been killed.
65931 */
65932
65933 reply = _lvmlockd_send("kill_vg",
65934 "cmd = %s", "lvmlockctl",
65935 "pid = " FMTd64, (int64_t) getpid(),
65936 "vg_name = %s", arg_vg_name,
65937 NULL);
65938
65939 if (!_lvmlockd_result(reply, &result)) {
65940 log_error("lvmlockd result %d", result);
65941 rv = result;
65942 } else {
65943 rv = 0;
65944 }
65945
65946 daemon_reply_destroy(reply);
65947
65948 /*
65949 * FIXME: here is where we should implement a strong form of
65950 * blkdeactivate, and if it completes successfully, automatically call
65951 * do_drop() afterward. (The drop step may not always be necessary
65952 * if the lvm commands run while shutting things down release all the
65953 * leases.)
65954 *
65955 * run_strong_blkdeactivate();
65956 * do_drop();
65957 */
65958
65959 return rv;
65960}
65961
65962static int do_drop(void)
65963{
65964 daemon_reply reply;
65965 int result;
65966 int rv;
65967
65968 syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
65969
65970 /*
65971 * Check for misuse by looking for any active LVs in the VG
65972 * and refusing this operation if found? One possible way
65973 * to kill LVs (e.g. if fs cannot be unmounted) is to suspend
65974 * them, or replace them with the error target. In that
65975 * case the LV will still appear to be active, but it is
65976 * safe to release the lock.
65977 */
65978
65979 reply = _lvmlockd_send("drop_vg",
65980 "cmd = %s", "lvmlockctl",
65981 "pid = " FMTd64, (int64_t) getpid(),
65982 "vg_name = %s", arg_vg_name,
65983 NULL);
65984
65985 if (!_lvmlockd_result(reply, &result)) {
65986 log_error("lvmlockd result %d", result);
65987 rv = result;
65988 } else {
65989 rv = 0;
65990 }
65991
65992 daemon_reply_destroy(reply);
65993 return rv;
65994}
65995
65996static void print_usage(void)
65997{
65998 printf("lvmlockctl options\n");
65999 printf("Options:\n");
66000 printf("--help | -h\n");
66001 printf(" Show this help information.\n");
66002 printf("--quit | -q\n");
66003 printf(" Tell lvmlockd to quit.\n");
66004 printf("--info | -i\n");
66005 printf(" Print lock state information from lvmlockd.\n");
66006 printf("--dump | -d\n");
66007 printf(" Print log buffer from lvmlockd.\n");
66008 printf("--wait | -w 0|1\n");
66009 printf(" Wait option for other commands.\n");
66010 printf("--force | -f 0|1>\n");
66011 printf(" Force option for other commands.\n");
66012 printf("--kill | -k <vgname>\n");
66013 printf(" Kill access to the VG when sanlock cannot renew lease.\n");
66014 printf("--drop | -r <vgname>\n");
66015 printf(" Clear locks for the VG when it is unused after kill (-k).\n");
66016 printf("--gl-enable | -E <vgname>\n");
66017 printf(" Tell lvmlockd to enable the global lock in a sanlock VG.\n");
66018 printf("--gl-disable | -D <vgname>\n");
66019 printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
66020 printf("--stop-lockspaces | -S\n");
66021 printf(" Stop all lockspaces.\n");
66022}
66023
66024static int read_options(int argc, char *argv[])
66025{
66026 int option_index = 0;
66027 int c;
66028
66029 static struct option long_options[] = {
66030 {"help", no_argument, 0, 'h' },
66031 {"quit", no_argument, 0, 'q' },
66032 {"info", no_argument, 0, 'i' },
66033 {"dump", no_argument, 0, 'd' },
66034 {"wait", required_argument, 0, 'w' },
66035 {"force", required_argument, 0, 'f' },
66036 {"kill", required_argument, 0, 'k' },
66037 {"drop", required_argument, 0, 'r' },
66038 {"gl-enable", required_argument, 0, 'E' },
66039 {"gl-disable", required_argument, 0, 'D' },
66040 {"stop-lockspaces", no_argument, 0, 'S' },
66041 {0, 0, 0, 0 }
66042 };
66043
66044 if (argc == 1) {
66045 print_usage();
66046 exit(0);
66047 }
66048
66049 while (1) {
66050 c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index);
66051 if (c == -1)
66052 break;
66053
66054 switch (c) {
66055 case 'h':
66056 /* --help */
66057 print_usage();
66058 exit(0);
66059 case 'q':
66060 /* --quit */
66061 quit = 1;
66062 break;
66063 case 'i':
66064 /* --info */
66065 info = 1;
66066 break;
66067 case 'd':
66068 /* --dump */
66069 dump = 1;
66070 break;
66071 case 'w':
66072 wait_opt = atoi(optarg);
66073 break;
66074 case 'k':
66075 kill_vg = 1;
66076 arg_vg_name = strdup(optarg);
66077 break;
66078 case 'r':
66079 drop_vg = 1;
66080 arg_vg_name = strdup(optarg);
66081 break;
66082 case 'E':
66083 gl_enable = 1;
66084 arg_vg_name = strdup(optarg);
66085 break;
66086 case 'D':
66087 gl_disable = 1;
66088 arg_vg_name = strdup(optarg);
66089 break;
66090 case 'S':
66091 stop_lockspaces = 1;
66092 break;
66093 default:
66094 print_usage();
66095 exit(1);
66096 }
66097 }
66098
66099
66100 return 0;
66101}
66102
66103int main(int argc, char **argv)
66104{
66105 int rv = 0;
66106
66107 rv = read_options(argc, argv);
66108 if (rv < 0)
66109 return rv;
66110
66111 _lvmlockd = lvmlockd_open(NULL);
66112
66113 if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
66114 log_error("Cannot connect to lvmlockd.");
66115 return -1;
66116 }
66117
66118 if (quit) {
66119 rv = do_quit();
66120 goto out;
66121 }
66122
66123 if (info) {
66124 rv = do_dump("info");
66125 goto out;
66126 }
66127
66128 if (dump) {
66129 rv = do_dump("dump");
66130 goto out;
66131 }
66132
66133 if (kill_vg) {
66134 rv = do_kill();
66135 goto out;
66136 }
66137
66138 if (drop_vg) {
66139 rv = do_drop();
66140 goto out;
66141 }
66142
66143 if (gl_enable) {
66144 syslog(LOG_INFO, "Enabling global lock in VG %s.", arg_vg_name);
66145 rv = do_able("enable_gl");
66146 goto out;
66147 }
66148
66149 if (gl_disable) {
66150 syslog(LOG_INFO, "Disabling global lock in VG %s.", arg_vg_name);
66151 rv = do_able("disable_gl");
66152 goto out;
66153 }
66154
66155 if (stop_lockspaces) {
66156 rv = do_stop_lockspaces();
66157 goto out;
66158 }
66159
66160out:
66161 lvmlockd_close(_lvmlockd);
66162 return rv;
66163}
66164\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockd-client.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002421\013062740170\0023547\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
66165 * Copyright (C) 2014-2015 Red Hat, Inc.
66166 *
66167 * This file is part of LVM2.
66168 *
66169 * This copyrighted material is made available to anyone wishing to use,
66170 * modify, copy, or redistribute it subject to the terms and conditions
66171 * of the GNU Lesser General Public License v.2.1.
66172 */
66173
66174#ifndef _LVM_LVMLOCKD_CLIENT_H
66175#define _LVM_LVMLOCKD_CLIENT_H
66176
66177#include "daemon-client.h"
66178
66179#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
66180
66181/* Wrappers to open/close connection */
66182
66183static inline daemon_handle lvmlockd_open(const char *sock)
66184{
66185 daemon_info lvmlockd_info = {
66186 .path = "lvmlockd",
66187 .socket = sock ?: LVMLOCKD_SOCKET,
66188 .protocol = "lvmlockd",
66189 .protocol_version = 1,
66190 .autostart = 0
66191 };
66192
66193 return daemon_open(lvmlockd_info);
66194}
66195
66196static inline void lvmlockd_close(daemon_handle h)
66197{
66198 return daemon_close(h);
66199}
66200
66201/*
66202 * Errors returned as the lvmlockd result value.
66203 */
66204#define ENOLS 210 /* lockspace not found */
66205#define ESTARTING 211 /* lockspace is starting */
66206#define EARGS 212
66207#define EHOSTID 213
66208#define EMANAGER 214
66209#define EPREPARE 215
66210#define ELOCKD 216
66211#define EVGKILLED 217 /* sanlock lost access to leases and VG is killed. */
66212#define ELOCKIO 218 /* sanlock io errors during lock op, may be transient. */
66213#define EREMOVED 219
66214
66215#endif /* _LVM_LVMLOCKD_CLIENT_H */
66216\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockd-core.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000451451\013062740170\0023227\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
66217 * Copyright (C) 2014-2015 Red Hat, Inc.
66218 *
66219 * This file is part of LVM2.
66220 *
66221 * This copyrighted material is made available to anyone wishing to use,
66222 * modify, copy, or redistribute it subject to the terms and conditions
66223 * of the GNU Lesser General Public License v.2.1.
66224 */
66225
66226#define _XOPEN_SOURCE 500 /* pthread */
66227#define _ISOC99_SOURCE
66228#define _REENTRANT
66229
66230#include "tool.h"
66231
66232#include "daemon-io.h"
66233#include "daemon-server.h"
66234#include "lvm-version.h"
66235#include "lvmetad-client.h"
66236#include "lvmlockd-client.h"
66237
66238/* #include <assert.h> */
66239#include <errno.h>
66240#include <pthread.h>
66241#include <stddef.h>
66242#include <poll.h>
66243#include <signal.h>
66244#include <getopt.h>
66245#include <syslog.h>
66246#include <dirent.h>
66247#include <time.h>
66248#include <sys/types.h>
66249#include <sys/socket.h>
66250#include <sys/utsname.h>
66251#include <sys/un.h>
66252
66253#define EXTERN
66254#include "lvmlockd-internal.h"
66255
66256/*
66257 * Basic operation of lvmlockd
66258 *
66259 * lvmlockd main process runs main_loop() which uses poll().
66260 * poll listens for new connections from lvm commands and for
66261 * messages from existing connected lvm commands.
66262 *
66263 * lvm command starts and connects to lvmlockd.
66264 *
66265 * lvmlockd receives a connection request from command and adds a
66266 * 'struct client' to keep track of the connection to the command.
66267 * The client's fd is added to the set of fd's in poll().
66268 *
66269 * lvm command sends a lock request to lvmlockd. The lock request
66270 * can be for the global lock, a vg lock, or an lv lock.
66271 *
66272 * lvmlockd main_loop/poll sees a message from an existing client.
66273 * It sets client.recv = 1, then wakes up client_thread_main.
66274 *
66275 * client_thread_main iterates through client structs (cl), looking
66276 * for any that need processing, finds the one with cl->recv set,
66277 * and calls client_recv_action(cl).
66278 *
66279 * client_recv_action(cl) reads the message/request from the client,
66280 * allocates a new 'struct action' (act) to represent the request,
66281 * sets the act with what is found in the request, then looks at
66282 * the specific operation in act->op (LD_OP_FOO) to decide what to
66283 * do with the action:
66284 *
66285 * . If the action is to start a lockspace, create a new thread
66286 * to manage that lockspace: add_lockspace(act).
66287 *
66288 * . If the action is a lock request, pass the act to the thread
66289 * that is managing that lockspace: add_lock_action(act).
66290 *
66291 * . Other misc actions are are passed to the worker_thread:
66292 * add_work_action(act).
66293 *
66294 * Onec the client_thread has passed the action off to another
66295 * thread to process, it goes back to waiting for more client
66296 * handling work to do.
66297 *
66298 * The thread that was given the action by the client_thread
66299 * now processes that action according to the operation, act->op.
66300 * This is either a lockspace_thread (for lock ops or ops that
66301 * add/rem a lockspace), or the worker_thread. See below for
66302 * how these ops are processed by these threads. When the
66303 * given thread is done processing the action, the result is
66304 * set in act->result, and the act struct for the completed action
66305 * is passed back to the client_thread (client_results list).
66306 *
66307 * The client_thread takes completed actions (from client_results
66308 * list), and sends the result back to the client that sent the
66309 * request represented by the action. The act struct is then freed.
66310 *
66311 * This completes the cycle of work between lvm commands (clients)
66312 * and lvmlockd. In summary:
66313 *
66314 * - main process polls for new client connections and new requests
66315 * from lvm commands
66316 * - client_thread reads requests from clients
66317 * - client_thread creates an action struct for each request
66318 * - client_thread passes the act to another thread for processing
66319 * - other threads pass completed act structs back to client_thread
66320 * - client_thread sends the act result back to the client and frees the act
66321 *
66322 *
66323 * Lockspace threads:
66324 * Each lockd VG has its own lockspace that contains locks for that VG.
66325 * Each 'struct lockspace' is managed by a separate lockspace_thread.
66326 * When the lockspace_thread is first created, the first thing it does
66327 * is join the lockspace in the lock manager. This can take a long time.
66328 * If the join fails, the thread exits. After the join, the thread
66329 * enters a loop waiting for lock actions to perform in the lockspace.
66330 *
66331 * The request to remove/leave a lockspace causes a flag to be set in
66332 * the lockspace struct. When the lockspace_thread sees this flag
66333 * set, it leaves the lockspace, and exits.
66334 *
66335 * When the client_thread passes a new action to a lockspace_thread,
66336 * i.e. a new lock request, the lockspace_thread identifies which resource
66337 * is being locked (GL, VG, LV), and gets the 'struct resource' (r) for it.
66338 * r->type will be LD_RT_GL, LD_RT_VG, or LD_RT_LV. r->name is the
66339 * resource name, and is fixed for GL and VG resources, but is based on
66340 * the LV name for LV resources. The act is added to the resource's
66341 * list of actions: r->actions, i.e. outstanding lock requests on the
66342 * resource.
66343 *
66344 * The lockspace thread then iterates through each resource in the
66345 * lockspace, processing any outstanding actions on each: res_process(ls, r).
66346 *
66347 * res_process() compares the outstanding actions/requests in r->actions
66348 * against any existing locks on the resource in r->locks. If the
66349 * action is blocked by existing locks, it's left on r->actions. If not,
66350 * the action/request is passed to the lock manager. If the result from
66351 * the lock manager is success, a new 'struct lock' is created for the
66352 * action and saved on r->locks. The result is set in act->result and
66353 * the act is passed back to the client_thread to be returned to the client.
66354 */
66355
66356static const char *lvmlockd_protocol = "lvmlockd";
66357static const int lvmlockd_protocol_version = 1;
66358static int daemon_quit;
66359static int adopt_opt;
66360
66361static daemon_handle lvmetad_handle;
66362static pthread_mutex_t lvmetad_mutex;
66363static int lvmetad_connected;
66364
66365/*
66366 * We use a separate socket for dumping daemon info.
66367 * This will not interfere with normal operations, and allows
66368 * free-form debug data to be dumped instead of the libdaemon
66369 * protocol that wants all data in the cft format.
66370 * 1MB should fit all the info we need to dump.
66371 */
66372#define DUMP_SOCKET_NAME "lvmlockd-dump.sock"
66373#define DUMP_BUF_SIZE (1024 * 1024)
66374static char dump_buf[DUMP_BUF_SIZE];
66375static struct sockaddr_un dump_addr;
66376static socklen_t dump_addrlen;
66377
66378/*
66379 * Main program polls client connections, adds new clients,
66380 * adds work for client thread.
66381 *
66382 * pollfd_mutex is used for adding vs removing entries,
66383 * and for resume vs realloc.
66384 */
66385#define POLL_FD_UNUSED -1 /* slot if free */
66386#define POLL_FD_IGNORE -2 /* slot is used but ignore in poll */
66387#define ADD_POLL_SIZE 16 /* increment slots by this amount */
66388
66389static pthread_mutex_t pollfd_mutex;
66390static struct pollfd *pollfd;
66391static int pollfd_size;
66392static int pollfd_maxi;
66393static int listen_pi;
66394static int listen_fd;
66395static int restart_pi;
66396static int restart_fds[2];
66397
66398/*
66399 * Each lockspace has its own thread to do locking.
66400 * The lockspace thread makes synchronous lock requests to dlm/sanlock.
66401 * Every vg with a lockd type, i.e. "dlm", "sanlock", should be on this list.
66402 */
66403static pthread_mutex_t lockspaces_mutex;
66404static struct list_head lockspaces;
66405
66406/*
66407 * Client thread reads client requests and writes client results.
66408 */
66409static pthread_t client_thread;
66410static pthread_mutex_t client_mutex;
66411static pthread_cond_t client_cond;
66412static struct list_head client_list; /* connected clients */
66413static struct list_head client_results; /* actions to send back to clients */
66414static uint32_t client_ids; /* 0 and INTERNAL_CLIENT_ID are skipped */
66415static int client_stop; /* stop the thread */
66416static int client_work; /* a client on client_list has work to do */
66417
66418#define INTERNAL_CLIENT_ID 0xFFFFFFFF /* special client_id for internal actions */
66419static struct list_head adopt_results; /* special start actions from adopt_locks() */
66420
66421/*
66422 * Worker thread performs misc non-locking actions, e.g. init/free.
66423 */
66424static pthread_t worker_thread;
66425static pthread_mutex_t worker_mutex;
66426static pthread_cond_t worker_cond;
66427static struct list_head worker_list; /* actions for worker_thread */
66428static int worker_stop; /* stop the thread */
66429static int worker_wake; /* wake the thread without adding work */
66430
66431/*
66432 * The content of every log_foo() statement is saved in the
66433 * circular buffer, which can be dumped to a client and printed.
66434 */
66435#define LOG_LINE_SIZE 256
66436#define LOG_DUMP_SIZE DUMP_BUF_SIZE
66437#define LOG_SYSLOG_PRIO LOG_WARNING
66438static char log_dump[LOG_DUMP_SIZE];
66439static unsigned int log_point;
66440static unsigned int log_wrap;
66441static pthread_mutex_t log_mutex;
66442static int syslog_priority = LOG_SYSLOG_PRIO;
66443
66444/*
66445 * Structure pools to avoid repeated malloc/free.
66446 */
66447#define MAX_UNUSED_ACTION 64
66448#define MAX_UNUSED_CLIENT 64
66449#define MAX_UNUSED_RESOURCE 64
66450#define MAX_UNUSED_LOCK 64
66451static pthread_mutex_t unused_struct_mutex;
66452static struct list_head unused_action;
66453static struct list_head unused_client;
66454static struct list_head unused_resource;
66455static struct list_head unused_lock;
66456static int unused_action_count;
66457static int unused_client_count;
66458static int unused_resource_count;
66459static int unused_lock_count;
66460static int resource_lm_data_size; /* max size of lm_data from sanlock|dlm */
66461static int alloc_new_structs; /* used for initializing in setup_structs */
66462
66463#define DO_STOP 1
66464#define NO_STOP 0
66465#define DO_FREE 1
66466#define NO_FREE 0
66467#define DO_FORCE 1
66468#define NO_FORCE 0
66469
66470static int add_lock_action(struct action *act);
66471static int str_to_lm(const char *str);
66472static int setup_dump_socket(void);
66473static void send_dump_buf(int fd, int dump_len);
66474static int dump_info(int *dump_len);
66475static int dump_log(int *dump_len);
66476
66477static int _syslog_name_to_num(const char *name)
66478{
66479 if (!strcmp(name, "emerg"))
66480 return LOG_EMERG;
66481 if (!strcmp(name, "alert"))
66482 return LOG_ALERT;
66483 if (!strcmp(name, "crit"))
66484 return LOG_CRIT;
66485 if (!strcmp(name, "err") || !strcmp(name, "error"))
66486 return LOG_ERR;
66487 if (!strcmp(name, "warning") || !strcmp(name, "warn"))
66488 return LOG_WARNING;
66489 if (!strcmp(name, "notice"))
66490 return LOG_NOTICE;
66491 if (!strcmp(name, "info"))
66492 return LOG_INFO;
66493 if (!strcmp(name, "debug"))
66494 return LOG_DEBUG;
66495 return LOG_WARNING;
66496}
66497
66498static const char *_syslog_num_to_name(int num)
66499{
66500 switch (num) {
66501 case LOG_EMERG:
66502 return "emerg";
66503 case LOG_ALERT:
66504 return "alert";
66505 case LOG_CRIT:
66506 return "crit";
66507 case LOG_ERR:
66508 return "err";
66509 case LOG_WARNING:
66510 return "warning";
66511 case LOG_NOTICE:
66512 return "notice";
66513 case LOG_INFO:
66514 return "info";
66515 case LOG_DEBUG:
66516 return "debug";
66517 }
66518 return "unknown";
66519}
66520
66521static uint64_t monotime(void)
66522{
66523 struct timespec ts;
66524
66525 if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
66526 log_error("clock_gettime failed to get timestamp %s.",
66527 strerror(errno));
66528 ts.tv_sec = 0;
66529 }
66530
66531 return ts.tv_sec;
66532}
66533
66534static void log_save_line(int len, char *line,
66535 char *log_buf, unsigned int *point, unsigned int *wrap)
66536{
66537 unsigned int p = *point;
66538 unsigned int w = *wrap;
66539 int i;
66540
66541 if (len < (int) (LOG_DUMP_SIZE - p)) {
66542 memcpy(log_buf + p, line, len);
66543 p += len;
66544
66545 if (p == LOG_DUMP_SIZE) {
66546 p = 0;
66547 w = 1;
66548 }
66549 goto out;
66550 }
66551
66552 for (i = 0; i < len; i++) {
66553 log_buf[p++] = line[i];
66554
66555 if (p == LOG_DUMP_SIZE) {
66556 p = 0;
66557 w = 1;
66558 }
66559 }
66560 out:
66561 *point = p;
66562 *wrap = w;
66563}
66564
66565void log_level(int level, const char *fmt, ...)
66566{
66567 char line[LOG_LINE_SIZE];
66568 va_list ap;
66569 int len = LOG_LINE_SIZE - 1;
66570 int ret, pos = 0;
66571
66572 memset(line, 0, sizeof(line));
66573
66574 ret = snprintf(line, len, "%llu ", (unsigned long long)time(NULL));
66575 pos += ret;
66576
66577 va_start(ap, fmt);
66578 ret = vsnprintf(line + pos, len - pos, fmt, ap);
66579 va_end(ap);
66580
66581 if (ret >= len - pos)
66582 pos = len - 1;
66583 else
66584 pos += ret;
66585
66586 line[pos++] = '\n';
66587 line[pos++] = '\0';
66588
66589 pthread_mutex_lock(&log_mutex);
66590 log_save_line(pos - 1, line, log_dump, &log_point, &log_wrap);
66591 pthread_mutex_unlock(&log_mutex);
66592
66593 if (level <= syslog_priority)
66594 syslog(level, "%s", line);
66595
66596 if (daemon_debug)
66597 fprintf(stderr, "%s", line);
66598}
66599
66600static int dump_log(int *dump_len)
66601{
66602 int tail_len;
66603
66604 pthread_mutex_lock(&log_mutex);
66605
66606 if (!log_wrap && !log_point) {
66607 *dump_len = 0;
66608 } else if (log_wrap) {
66609 tail_len = LOG_DUMP_SIZE - log_point;
66610 memcpy(dump_buf, log_dump+log_point, tail_len);
66611 if (log_point)
66612 memcpy(dump_buf+tail_len, log_dump, log_point);
66613 *dump_len = LOG_DUMP_SIZE;
66614 } else {
66615 memcpy(dump_buf, log_dump, log_point-1);
66616 *dump_len = log_point-1;
66617 }
66618 pthread_mutex_unlock(&log_mutex);
66619
66620 return 0;
66621}
66622
66623struct lockspace *alloc_lockspace(void)
66624{
66625 struct lockspace *ls;
66626
66627 if (!(ls = malloc(sizeof(struct lockspace)))) {
66628 log_error("out of memory for lockspace");
66629 return NULL;
66630 }
66631
66632 memset(ls, 0, sizeof(struct lockspace));
66633 INIT_LIST_HEAD(&ls->actions);
66634 INIT_LIST_HEAD(&ls->resources);
66635 pthread_mutex_init(&ls->mutex, NULL);
66636 pthread_cond_init(&ls->cond, NULL);
66637 return ls;
66638}
66639
66640static struct action *alloc_action(void)
66641{
66642 struct action *act;
66643
66644 pthread_mutex_lock(&unused_struct_mutex);
66645 if (!unused_action_count || alloc_new_structs) {
66646 act = malloc(sizeof(struct action));
66647 } else {
66648 act = list_first_entry(&unused_action, struct action, list);
66649 list_del(&act->list);
66650 unused_action_count--;
66651 }
66652 pthread_mutex_unlock(&unused_struct_mutex);
66653 if (act)
66654 memset(act, 0, sizeof(struct action));
66655 else
66656 log_error("out of memory for action");
66657 return act;
66658}
66659
66660static struct client *alloc_client(void)
66661{
66662 struct client *cl;
66663
66664 pthread_mutex_lock(&unused_struct_mutex);
66665 if (!unused_client_count || alloc_new_structs) {
66666 cl = malloc(sizeof(struct client));
66667 } else {
66668 cl = list_first_entry(&unused_client, struct client, list);
66669 list_del(&cl->list);
66670 unused_client_count--;
66671 }
66672 pthread_mutex_unlock(&unused_struct_mutex);
66673 if (cl)
66674 memset(cl, 0, sizeof(struct client));
66675 else
66676 log_error("out of memory for client");
66677 return cl;
66678}
66679
66680static struct resource *alloc_resource(void)
66681{
66682 struct resource *r;
66683
66684 pthread_mutex_lock(&unused_struct_mutex);
66685 if (!unused_resource_count || alloc_new_structs) {
66686 r = malloc(sizeof(struct resource) + resource_lm_data_size);
66687 } else {
66688 r = list_first_entry(&unused_resource, struct resource, list);
66689 list_del(&r->list);
66690 unused_resource_count--;
66691 }
66692 pthread_mutex_unlock(&unused_struct_mutex);
66693 if (r) {
66694 memset(r, 0, sizeof(struct resource) + resource_lm_data_size);
66695 INIT_LIST_HEAD(&r->locks);
66696 INIT_LIST_HEAD(&r->actions);
66697 } else {
66698 log_error("out of memory for resource");
66699 }
66700 return r;
66701}
66702
66703static struct lock *alloc_lock(void)
66704{
66705 struct lock *lk;
66706
66707 pthread_mutex_lock(&unused_struct_mutex);
66708 if (!unused_lock_count || alloc_new_structs) {
66709 lk = malloc(sizeof(struct lock));
66710 } else {
66711 lk = list_first_entry(&unused_lock, struct lock, list);
66712 list_del(&lk->list);
66713 unused_lock_count--;
66714 }
66715 pthread_mutex_unlock(&unused_struct_mutex);
66716 if (lk)
66717 memset(lk, 0, sizeof(struct lock));
66718 else
66719 log_error("out of memory for lock");
66720 return lk;
66721}
66722
66723static void free_action(struct action *act)
66724{
66725 pthread_mutex_lock(&unused_struct_mutex);
66726 if (unused_action_count >= MAX_UNUSED_ACTION) {
66727 free(act);
66728 } else {
66729 list_add_tail(&act->list, &unused_action);
66730 unused_action_count++;
66731 }
66732 pthread_mutex_unlock(&unused_struct_mutex);
66733}
66734
66735static void free_client(struct client *cl)
66736{
66737 pthread_mutex_lock(&unused_struct_mutex);
66738 if (unused_client_count >= MAX_UNUSED_CLIENT) {
66739 free(cl);
66740 } else {
66741 list_add_tail(&cl->list, &unused_client);
66742 unused_client_count++;
66743 }
66744 pthread_mutex_unlock(&unused_struct_mutex);
66745}
66746
66747static void free_resource(struct resource *r)
66748{
66749 pthread_mutex_lock(&unused_struct_mutex);
66750 if (unused_resource_count >= MAX_UNUSED_RESOURCE) {
66751 free(r);
66752 } else {
66753 list_add_tail(&r->list, &unused_resource);
66754 unused_resource_count++;
66755 }
66756 pthread_mutex_unlock(&unused_struct_mutex);
66757}
66758
66759static void free_lock(struct lock *lk)
66760{
66761 pthread_mutex_lock(&unused_struct_mutex);
66762 if (unused_lock_count >= MAX_UNUSED_LOCK) {
66763 free(lk);
66764 } else {
66765 list_add_tail(&lk->list, &unused_lock);
66766 unused_lock_count++;
66767 }
66768 pthread_mutex_unlock(&unused_struct_mutex);
66769}
66770
66771static int setup_structs(void)
66772{
66773 struct action *act;
66774 struct client *cl;
66775 struct resource *r;
66776 struct lock *lk;
66777 int data_san = lm_data_size_sanlock();
66778 int data_dlm = lm_data_size_dlm();
66779 int i;
66780
66781 resource_lm_data_size = data_san > data_dlm ? data_san : data_dlm;
66782
66783 pthread_mutex_init(&unused_struct_mutex, NULL);
66784 INIT_LIST_HEAD(&unused_action);
66785 INIT_LIST_HEAD(&unused_client);
66786 INIT_LIST_HEAD(&unused_resource);
66787 INIT_LIST_HEAD(&unused_lock);
66788
66789 /*
66790 * For setup, force the alloc_ functions to alloc new structs instead
66791 * of taking them unused. This allows alloc_struct/free_struct loop to
66792 * populate the unused lists.
66793 */
66794 alloc_new_structs = 1;
66795
66796 for (i = 0; i < MAX_UNUSED_ACTION/2; i++) {
66797 if (!(act = alloc_action()))
66798 goto fail;
66799 free_action(act);
66800 }
66801
66802 for (i = 0; i < MAX_UNUSED_CLIENT/2; i++) {
66803 if (!(cl = alloc_client()))
66804 goto fail;
66805 free_client(cl);
66806 }
66807
66808 for (i = 0; i < MAX_UNUSED_RESOURCE/2; i++) {
66809 if (!(r = alloc_resource()))
66810 goto fail;
66811 free_resource(r);
66812 }
66813
66814 for (i = 0; i < MAX_UNUSED_LOCK/2; i++) {
66815 if (!(lk = alloc_lock()))
66816 goto fail;
66817 free_lock(lk);
66818 }
66819
66820 alloc_new_structs = 0;
66821 return 0;
66822fail:
66823 alloc_new_structs = 0;
66824 return -ENOMEM;
66825}
66826
66827static int add_pollfd(int fd)
66828{
66829 int i, new_size;
66830 struct pollfd *tmp_pollfd;
66831
66832 pthread_mutex_lock(&pollfd_mutex);
66833 for (i = 0; i < pollfd_size; i++) {
66834 if (pollfd[i].fd != POLL_FD_UNUSED)
66835 continue;
66836
66837 pollfd[i].fd = fd;
66838 pollfd[i].events = POLLIN;
66839 pollfd[i].revents = 0;
66840
66841 if (i > pollfd_maxi)
66842 pollfd_maxi = i;
66843
66844 pthread_mutex_unlock(&pollfd_mutex);
66845 return i;
66846 }
66847
66848 new_size = pollfd_size + ADD_POLL_SIZE;
66849
66850 tmp_pollfd = realloc(pollfd, new_size * sizeof(struct pollfd));
66851 if (!tmp_pollfd) {
66852 log_error("can't alloc new size %d for pollfd", new_size);
66853 pthread_mutex_unlock(&pollfd_mutex);
66854 return -ENOMEM;
66855 }
66856 pollfd = tmp_pollfd;
66857
66858 for (i = pollfd_size; i < new_size; i++) {
66859 pollfd[i].fd = POLL_FD_UNUSED;
66860 pollfd[i].events = 0;
66861 pollfd[i].revents = 0;
66862 }
66863
66864 i = pollfd_size;
66865 pollfd[i].fd = fd;
66866 pollfd[i].events = POLLIN;
66867 pollfd[i].revents = 0;
66868 pollfd_maxi = i;
66869
66870 pollfd_size = new_size;
66871
66872 pthread_mutex_unlock(&pollfd_mutex);
66873 return i;
66874}
66875
66876static void rem_pollfd(int pi)
66877{
66878 if (pi < 0) {
66879 log_error("rem_pollfd %d", pi);
66880 return;
66881 }
66882 pthread_mutex_lock(&pollfd_mutex);
66883 pollfd[pi].fd = POLL_FD_UNUSED;
66884 pollfd[pi].events = 0;
66885 pollfd[pi].revents = 0;
66886 pthread_mutex_unlock(&pollfd_mutex);
66887}
66888
66889static const char *lm_str(int x)
66890{
66891 switch (x) {
66892 case LD_LM_NONE:
66893 return "none";
66894 case LD_LM_DLM:
66895 return "dlm";
66896 case LD_LM_SANLOCK:
66897 return "sanlock";
66898 default:
66899 return "lm_unknown";
66900 }
66901}
66902
66903static const char *rt_str(int x)
66904{
66905 switch (x) {
66906 case LD_RT_GL:
66907 return "gl";
66908 case LD_RT_VG:
66909 return "vg";
66910 case LD_RT_LV:
66911 return "lv";
66912 default:
66913 return ".";
66914 };
66915}
66916
66917static const char *op_str(int x)
66918{
66919 switch (x) {
66920 case LD_OP_INIT:
66921 return "init";
66922 case LD_OP_FREE:
66923 return "free";
66924 case LD_OP_START:
66925 return "start";
66926 case LD_OP_STOP:
66927 return "stop";
66928 case LD_OP_LOCK:
66929 return "lock";
66930 case LD_OP_UPDATE:
66931 return "update";
66932 case LD_OP_CLOSE:
66933 return "close";
66934 case LD_OP_ENABLE:
66935 return "enable";
66936 case LD_OP_DISABLE:
66937 return "disable";
66938 case LD_OP_START_WAIT:
66939 return "start_wait";
66940 case LD_OP_STOP_ALL:
66941 return "stop_all";
66942 case LD_OP_RENAME_BEFORE:
66943 return "rename_before";
66944 case LD_OP_RENAME_FINAL:
66945 return "rename_final";
66946 case LD_OP_RUNNING_LM:
66947 return "running_lm";
66948 case LD_OP_FIND_FREE_LOCK:
66949 return "find_free_lock";
66950 case LD_OP_KILL_VG:
66951 return "kill_vg";
66952 case LD_OP_DROP_VG:
66953 return "drop_vg";
66954 case LD_OP_DUMP_LOG:
66955 return "dump_log";
66956 case LD_OP_DUMP_INFO:
66957 return "dump_info";
66958 case LD_OP_BUSY:
66959 return "busy";
66960 default:
66961 return "op_unknown";
66962 };
66963}
66964
66965int last_string_from_args(char *args_in, char *last)
66966{
66967 const char *args = args_in;
66968 const char *colon, *str = NULL;
66969
66970 while (1) {
66971 if (!args || (*args == '\0'))
66972 break;
66973 colon = strstr(args, ":");
66974 if (!colon)
66975 break;
66976 str = colon;
66977 args = colon + 1;
66978 }
66979
66980 if (str) {
66981 snprintf(last, MAX_ARGS, "%s", str + 1);
66982 return 0;
66983 }
66984 return -1;
66985}
66986
66987int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch)
66988{
66989 char version[MAX_ARGS+1];
66990 char *major_str, *minor_str, *patch_str;
66991 char *n, *d1, *d2;
66992
66993 memset(version, 0, sizeof(version));
66994 strncpy(version, args, MAX_ARGS);
66995 version[MAX_ARGS] = '\0';
66996
66997 n = strstr(version, ":");
66998 if (n)
66999 *n = '\0';
67000
67001 d1 = strstr(version, ".");
67002 if (!d1)
67003 return -1;
67004
67005 d2 = strstr(d1 + 1, ".");
67006 if (!d2)
67007 return -1;
67008
67009 major_str = version;
67010 minor_str = d1 + 1;
67011 patch_str = d2 + 1;
67012
67013 *d1 = '\0';
67014 *d2 = '\0';
67015
67016 if (major)
67017 *major = atoi(major_str);
67018 if (minor)
67019 *minor = atoi(minor_str);
67020 if (patch)
67021 *patch = atoi(patch_str);
67022
67023 return 0;
67024}
67025
67026/*
67027 * These are few enough that arrays of function pointers can
67028 * be avoided.
67029 */
67030
67031static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
67032{
67033 int rv;
67034
67035 if (ls->lm_type == LD_LM_DLM)
67036 rv = lm_prepare_lockspace_dlm(ls);
67037 else if (ls->lm_type == LD_LM_SANLOCK)
67038 rv = lm_prepare_lockspace_sanlock(ls);
67039 else
67040 return -1;
67041
67042 if (act)
67043 act->lm_rv = rv;
67044 return rv;
67045}
67046
67047static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt)
67048{
67049 int rv;
67050
67051 if (ls->lm_type == LD_LM_DLM)
67052 rv = lm_add_lockspace_dlm(ls, adopt);
67053 else if (ls->lm_type == LD_LM_SANLOCK)
67054 rv = lm_add_lockspace_sanlock(ls, adopt);
67055 else
67056 return -1;
67057
67058 if (act)
67059 act->lm_rv = rv;
67060 return rv;
67061}
67062
67063static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_vg)
67064{
67065 int rv;
67066
67067 if (ls->lm_type == LD_LM_DLM)
67068 rv = lm_rem_lockspace_dlm(ls, free_vg);
67069 else if (ls->lm_type == LD_LM_SANLOCK)
67070 rv = lm_rem_lockspace_sanlock(ls, free_vg);
67071 else
67072 return -1;
67073
67074 if (act)
67075 act->lm_rv = rv;
67076 return rv;
67077}
67078
67079static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act,
67080 struct val_blk *vb_out, int *retry, int adopt)
67081{
67082 int rv;
67083
67084 if (ls->lm_type == LD_LM_DLM)
67085 rv = lm_lock_dlm(ls, r, mode, vb_out, adopt);
67086 else if (ls->lm_type == LD_LM_SANLOCK)
67087 rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt);
67088 else
67089 return -1;
67090
67091 if (act)
67092 act->lm_rv = rv;
67093 return rv;
67094}
67095
67096static int lm_convert(struct lockspace *ls, struct resource *r,
67097 int mode, struct action *act, uint32_t r_version)
67098{
67099 int rv;
67100
67101 if (ls->lm_type == LD_LM_DLM)
67102 rv = lm_convert_dlm(ls, r, mode, r_version);
67103 else if (ls->lm_type == LD_LM_SANLOCK)
67104 rv = lm_convert_sanlock(ls, r, mode, r_version);
67105 else
67106 return -1;
67107
67108 if (act)
67109 act->lm_rv = rv;
67110 return rv;
67111}
67112
67113static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *act,
67114 uint32_t r_version, uint32_t lmu_flags)
67115{
67116 int rv;
67117
67118 if (ls->lm_type == LD_LM_DLM)
67119 rv = lm_unlock_dlm(ls, r, r_version, lmu_flags);
67120 else if (ls->lm_type == LD_LM_SANLOCK)
67121 rv = lm_unlock_sanlock(ls, r, r_version, lmu_flags);
67122 else
67123 return -1;
67124
67125 if (act)
67126 act->lm_rv = rv;
67127 return rv;
67128}
67129
67130static int lm_hosts(struct lockspace *ls, int notify)
67131{
67132 if (ls->lm_type == LD_LM_DLM)
67133 return lm_hosts_dlm(ls, notify);
67134 else if (ls->lm_type == LD_LM_SANLOCK)
67135 return lm_hosts_sanlock(ls, notify);
67136 return -1;
67137}
67138
67139static void lm_rem_resource(struct lockspace *ls, struct resource *r)
67140{
67141 if (ls->lm_type == LD_LM_DLM)
67142 lm_rem_resource_dlm(ls, r);
67143 else if (ls->lm_type == LD_LM_SANLOCK)
67144 lm_rem_resource_sanlock(ls, r);
67145}
67146
67147static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset)
67148{
67149 if (ls->lm_type == LD_LM_DLM)
67150 return 0;
67151 else if (ls->lm_type == LD_LM_SANLOCK)
67152 return lm_find_free_lock_sanlock(ls, free_offset);
67153 return -1;
67154}
67155
67156/*
67157 * While adopting locks, actions originate from the adopt_locks()
67158 * function, not from a client. So, these actions (flagged ADOPT),
67159 * should be passed back to the adopt_locks() function through the
67160 * adopt_results list, and not be sent back to a client via the
67161 * client_list/client_thread.
67162 */
67163
67164static void add_client_result(struct action *act)
67165{
67166 if (act->flags & LD_AF_NO_CLIENT) {
67167 log_debug("internal action done op %s mode %s result %d vg %s",
67168 op_str(act->op), mode_str(act->mode), act->result, act->vg_name);
67169 free_action(act);
67170 return;
67171 }
67172
67173 pthread_mutex_lock(&client_mutex);
67174 if (act->flags & LD_AF_ADOPT)
67175 list_add_tail(&act->list, &adopt_results);
67176 else
67177 list_add_tail(&act->list, &client_results);
67178 pthread_cond_signal(&client_cond);
67179 pthread_mutex_unlock(&client_mutex);
67180}
67181
67182static struct lock *find_lock_client(struct resource *r, uint32_t client_id)
67183{
67184 struct lock *lk;
67185
67186 list_for_each_entry(lk, &r->locks, list) {
67187 if (lk->client_id == client_id)
67188 return lk;
67189 }
67190 return NULL;
67191}
67192
67193static struct lock *find_lock_persistent(struct resource *r)
67194{
67195 struct lock *lk;
67196
67197 list_for_each_entry(lk, &r->locks, list) {
67198 if (lk->flags & LD_LF_PERSISTENT)
67199 return lk;
67200 }
67201 return NULL;
67202}
67203
67204static struct action *find_action_client(struct resource *r, uint32_t client_id)
67205{
67206 struct action *act;
67207
67208 list_for_each_entry(act, &r->actions, list) {
67209 if (act->client_id != client_id)
67210 continue;
67211 return act;
67212 }
67213 return NULL;
67214}
67215
67216static void add_work_action(struct action *act)
67217{
67218 pthread_mutex_lock(&worker_mutex);
67219 if (!worker_stop) {
67220 list_add_tail(&act->list, &worker_list);
67221 pthread_cond_signal(&worker_cond);
67222 }
67223 pthread_mutex_unlock(&worker_mutex);
67224}
67225
67226static daemon_reply send_lvmetad(const char *id, ...)
67227{
67228 daemon_reply reply;
67229 va_list ap;
67230 int retries = 0;
67231 int err;
67232
67233 va_start(ap, id);
67234
67235 /*
67236 * mutex is used because all threads share a single
67237 * lvmetad connection/handle.
67238 */
67239 pthread_mutex_lock(&lvmetad_mutex);
67240retry:
67241 if (!lvmetad_connected) {
67242 lvmetad_handle = lvmetad_open(NULL);
67243 if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0) {
67244 err = lvmetad_handle.error ?: lvmetad_handle.socket_fd;
67245 pthread_mutex_unlock(&lvmetad_mutex);
67246 log_error("lvmetad_open reconnect error %d", err);
67247 memset(&reply, 0, sizeof(reply));
67248 reply.error = err;
67249 va_end(ap);
67250 return reply;
67251 } else {
67252 log_debug("lvmetad reconnected");
67253 lvmetad_connected = 1;
67254 }
67255 }
67256
67257 reply = daemon_send_simple_v(lvmetad_handle, id, ap);
67258
67259 /* lvmetad may have been restarted */
67260 if ((reply.error == ECONNRESET) && (retries < 2)) {
67261 daemon_close(lvmetad_handle);
67262 lvmetad_connected = 0;
67263 retries++;
67264 goto retry;
67265 }
67266 pthread_mutex_unlock(&lvmetad_mutex);
67267
67268 va_end(ap);
67269 return reply;
67270}
67271
67272static int res_lock(struct lockspace *ls, struct resource *r, struct action *act, int *retry)
67273{
67274 struct lock *lk;
67275 struct val_blk vb;
67276 uint32_t new_version = 0;
67277 int inval_meta;
67278 int rv = 0;
67279
67280 memset(&vb, 0, sizeof(vb));
67281
67282 r->last_client_id = act->client_id;
67283
67284 if (r->type == LD_RT_LV)
67285 log_debug("S %s R %s res_lock cl %u mode %s (%s)", ls->name, r->name, act->client_id, mode_str(act->mode), act->lv_name);
67286 else
67287 log_debug("S %s R %s res_lock cl %u mode %s", ls->name, r->name, act->client_id, mode_str(act->mode));
67288
67289 if (r->mode == LD_LK_SH && act->mode == LD_LK_SH)
67290 goto add_lk;
67291
67292 if (r->type == LD_RT_LV && act->lv_args[0])
67293 memcpy(r->lv_args, act->lv_args, MAX_ARGS);
67294
67295 rv = lm_lock(ls, r, act->mode, act, &vb, retry, act->flags & LD_AF_ADOPT);
67296
67297 if (r->use_vb)
67298 log_debug("S %s R %s res_lock rv %d read vb %x %x %u",
67299 ls->name, r->name, rv, vb.version, vb.flags, vb.r_version);
67300 else
67301 log_debug("S %s R %s res_lock rv %d", ls->name, r->name, rv);
67302
67303 if (rv < 0)
67304 return rv;
67305
67306 if (sanlock_gl_dup && ls->sanlock_gl_enabled)
67307 act->flags |= LD_AF_DUP_GL_LS;
67308
67309 /*
67310 * Check new lvb values to decide if lvmetad cache should
67311 * be invalidated. When we need to invalidate the lvmetad
67312 * cache, but don't have a usable r_version from the lvb,
67313 * send lvmetad new_version 0 which causes it to invalidate
67314 * the VG metdata without comparing against the currently
67315 * cached VG seqno.
67316 */
67317
67318 inval_meta = 0;
67319
67320 if (!r->use_vb) {
67321 /* LV locks don't use an lvb. */
67322
67323 } else if (vb.version && ((vb.version & 0xFF00) > (VAL_BLK_VERSION & 0xFF00))) {
67324 log_error("S %s R %s res_lock invalid val_blk version %x flags %x r_version %u",
67325 ls->name, r->name, vb.version, vb.flags, vb.r_version);
67326 inval_meta = 1;
67327 new_version = 0;
67328 rv = -EINVAL;
67329
67330 } else if (vb.r_version && (vb.r_version == r->version)) {
67331 /*
67332 * Common case when the version hasn't changed.
67333 * Do nothing.
67334 */
67335 } else if (r->version && vb.r_version && (vb.r_version > r->version)) {
67336 /*
67337 * Common case when the version has changed. Another host
67338 * has changed the data protected by the lock since we last
67339 * acquired it, and increased r_version so we know that our
67340 * cache is invalid.
67341 */
67342 log_debug("S %s R %s res_lock got version %u our %u",
67343 ls->name, r->name, vb.r_version, r->version);
67344 r->version = vb.r_version;
67345 new_version = vb.r_version;
67346 r->version_zero_valid = 0;
67347 inval_meta = 1;
67348
67349 } else if (r->version_zero_valid && !vb.r_version) {
67350 /*
67351 * The lvb is in a persistent zero state, which will end
67352 * once someone uses the lock and writes a new lvb value.
67353 * Do nothing.
67354 */
67355 log_debug("S %s R %s res_lock version_zero_valid still zero", ls->name, r->name);
67356
67357 } else if (r->version_zero_valid && vb.r_version) {
67358 /*
67359 * Someone has written to the lvb after it was in a
67360 * persistent zero state. Begin tracking normal
67361 * non-zero changes. We may or may not have known
67362 * about a previous non-zero version (in r->version).
67363 * If we did, it means the lvb content was lost and
67364 * has now been reinitialized.
67365 *
67366 * If the new reinitialized value is less than the
67367 * previous non-zero value in r->version, then something
67368 * unusual has happened. For a VG lock, it probably
67369 * means the VG was removed and recreated. Invalidate
67370 * our cache and begin using the new VG version. For
67371 * a GL lock, another host may have reinitialized a
67372 * lost/zero lvb with a value less than we'd seen
67373 * before. Invalidate the cache, and begin using
67374 * the lower version (or continue using our old
67375 * larger version?)
67376 */
67377 if (r->version && (r->version >= vb.r_version)) {
67378 log_debug("S %s R %s res_lock version_zero_valid got version %u less than our %u",
67379 ls->name, r->name, vb.r_version, r->version);
67380 new_version = 0;
67381 } else {
67382 log_debug("S %s R %s res_lock version_zero_valid got version %u our %u",
67383 ls->name, r->name, vb.r_version, r->version);
67384 new_version = vb.r_version;
67385 }
67386 r->version = vb.r_version;
67387 r->version_zero_valid = 0;
67388 inval_meta = 1;
67389
67390 } else if (!r->version && vb.r_version) {
67391 /*
67392 * The first time we've acquired the lock and seen the lvb.
67393 */
67394 log_debug("S %s R %s res_lock initial version %u", ls->name, r->name, vb.r_version);
67395 r->version = vb.r_version;
67396 inval_meta = 1;
67397 new_version = vb.r_version;
67398 r->version_zero_valid = 0;
67399
67400 } else if (!r->version && !vb.r_version) {
67401 /*
67402 * The lock may have never been used to change something.
67403 * (e.g. a new sanlock GL?)
67404 */
67405 log_debug("S %s R %s res_lock all versions zero", ls->name, r->name);
67406 if (!r->version_zero_valid) {
67407 inval_meta = 1;
67408 new_version = 0;
67409 }
67410 r->version_zero_valid = 1;
67411
67412 } else if (r->version && !vb.r_version) {
67413 /*
67414 * The lvb content has been lost or never been initialized.
67415 * It can be lost during dlm recovery when the master node
67416 * is removed.
67417 *
67418 * If we're the next to write the lvb, reinitialze it to the
67419 * new VG seqno, or a new GL counter larger than was seen by
67420 * any hosts before (how to estimate that?)
67421 *
67422 * If we see non-zero values before we next write to it, use
67423 * those values.
67424 *
67425 * While the lvb values remain zero, the data for the lock
67426 * is unchanged and we don't need to invalidate metadata.
67427 */
67428 if ((ls->lm_type == LD_LM_DLM) && !vb.version && !vb.flags)
67429 log_debug("S %s R %s res_lock all lvb content is blank",
67430 ls->name, r->name);
67431 log_debug("S %s R %s res_lock our version %u got vb %x %x %u",
67432 ls->name, r->name, r->version, vb.version, vb.flags, vb.r_version);
67433 r->version_zero_valid = 1;
67434 inval_meta = 1;
67435 new_version = 0;
67436
67437 } else if (r->version && vb.r_version && (vb.r_version < r->version)) {
67438 /*
67439 * The lvb value has gone backwards, which shouldn't generally happen,
67440 * but could when the dlm lvb is lost and reinitialized, or the VG
67441 * is removed and recreated.
67442 *
67443 * If this is a VG lock, it probably means the VG has been removed
67444 * and recreated while we had the dlm lockspace running.
67445 * FIXME: how does the cache validation and replacement in lvmetad
67446 * work in this case?
67447 */
67448 log_debug("S %s R %s res_lock got version %u less than our version %u",
67449 ls->name, r->name, vb.r_version, r->version);
67450 r->version = vb.r_version;
67451 inval_meta = 1;
67452 new_version = 0;
67453 r->version_zero_valid = 0;
67454 } else {
67455 log_debug("S %s R %s res_lock undefined vb condition vzv %d our version %u vb %x %x %u",
67456 ls->name, r->name, r->version_zero_valid, r->version,
67457 vb.version, vb.flags, vb.r_version);
67458 }
67459
67460 if (vb.version && vb.r_version && (vb.flags & VBF_REMOVED)) {
67461 /* Should we set ls->thread_stop = 1 ? */
67462 log_debug("S %s R %s res_lock vb flag REMOVED",
67463 ls->name, r->name);
67464 rv = -EREMOVED;
67465 }
67466
67467 /*
67468 * r is vglk: tell lvmetad to set the vg invalid
67469 * flag, and provide the new r_version. If lvmetad finds
67470 * that its cached vg has seqno less than the value
67471 * we send here, it will set the vg invalid flag.
67472 * lvm commands that read the vg from lvmetad, will
67473 * see the invalid flag returned, will reread the
67474 * vg from disk, update the lvmetad copy, and go on.
67475 *
67476 * r is global: tell lvmetad to set the global invalid
67477 * flag. When commands see this flag returned from lvmetad,
67478 * they will reread metadata from disk, update the lvmetad
67479 * caches, and tell lvmetad to set global invalid to 0.
67480 */
67481
67482 if (inval_meta && (r->type == LD_RT_VG)) {
67483 daemon_reply reply;
67484 char *uuid;
67485
67486 log_debug("S %s R %s res_lock set lvmetad vg version %u",
67487 ls->name, r->name, new_version);
67488
67489 if (!ls->vg_uuid[0] || !strcmp(ls->vg_uuid, "none"))
67490 uuid = (char *)"none";
67491 else
67492 uuid = ls->vg_uuid;
67493
67494 reply = send_lvmetad("set_vg_info",
67495 "token = %s", "skip",
67496 "uuid = %s", uuid,
67497 "name = %s", ls->vg_name,
67498 "version = " FMTd64, (int64_t)new_version,
67499 NULL);
67500
67501 if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK"))
67502 log_error("set_vg_info in lvmetad failed %d", reply.error);
67503 daemon_reply_destroy(reply);
67504 }
67505
67506 if (inval_meta && (r->type == LD_RT_GL)) {
67507 daemon_reply reply;
67508
67509 log_debug("S %s R %s res_lock set lvmetad global invalid",
67510 ls->name, r->name);
67511
67512 reply = send_lvmetad("set_global_info",
67513 "token = %s", "skip",
67514 "global_invalid = " FMTd64, INT64_C(1),
67515 NULL);
67516
67517 if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK"))
67518 log_error("set_global_info in lvmetad failed %d", reply.error);
67519 daemon_reply_destroy(reply);
67520 }
67521
67522 /*
67523 * Record the new lock state.
67524 */
67525
67526 r->mode = act->mode;
67527
67528add_lk:
67529 if (r->mode == LD_LK_SH)
67530 r->sh_count++;
67531
67532 if (!(lk = alloc_lock()))
67533 return -ENOMEM;
67534
67535 lk->client_id = act->client_id;
67536 lk->mode = act->mode;
67537
67538 if (act->flags & LD_AF_PERSISTENT) {
67539 lk->flags |= LD_LF_PERSISTENT;
67540 lk->client_id = 0;
67541 }
67542
67543 /*
67544 * LV_LOCK means the action acquired the lv lock in the lock manager
67545 * (as opposed to finding that the lv lock was already held). If
67546 * the client for this LV_LOCK action fails before we send the result,
67547 * then we automatically unlock the lv since the lv wasn't activated.
67548 * (There will always be an odd chance the lv lock is held while the
67549 * lv is not active, but this helps.) The most common case where this
67550 * is helpful is when the lv lock operation is slow/delayed and the
67551 * command is canceled by the user.
67552 *
67553 * LV_UNLOCK means the lv unlock action was generated by lvmlockd when
67554 * it tried to send the reply for an lv lock action (with LV_LOCK set),
67555 * and failed to send the reply to the client/command. The
67556 * last_client_id saved on the resource is compared to this LV_UNLOCK
67557 * action before the auto unlock is done in case another action locked
67558 * the lv between the failed client lock action and the auto unlock.
67559 */
67560 if (r->type == LD_RT_LV)
67561 act->flags |= LD_AF_LV_LOCK;
67562
67563 list_add_tail(&lk->list, &r->locks);
67564
67565 return rv;
67566}
67567
67568static int res_convert(struct lockspace *ls, struct resource *r,
67569 struct lock *lk, struct action *act)
67570{
67571 uint32_t r_version;
67572 int rv;
67573
67574 r->last_client_id = act->client_id;
67575
67576 log_debug("S %s R %s res_convert cl %u mode %s", ls->name, r->name, act->client_id, mode_str(act->mode));
67577
67578 if (act->mode == LD_LK_EX && lk->mode == LD_LK_SH && r->sh_count > 1)
67579 return -EAGAIN;
67580
67581 /*
67582 * lm_convert() writes new version (from ex)
67583 * Same as lm_unlock()
67584 */
67585
67586 if ((r->type == LD_RT_GL) && (r->mode == LD_LK_EX)) {
67587 r->version++;
67588 lk->version = r->version;
67589 r_version = r->version;
67590 r->version_zero_valid = 0;
67591
67592 log_debug("S %s R %s res_convert r_version inc %u",
67593 ls->name, r->name, r_version);
67594
67595 } else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk->version > r->version)) {
67596 r->version = lk->version;
67597 r_version = r->version;
67598 r->version_zero_valid = 0;
67599
67600 log_debug("S %s R %s res_convert r_version new %u", ls->name, r->name, r_version);
67601 } else {
67602 r_version = 0;
67603 }
67604
67605 rv = lm_convert(ls, r, act->mode, act, r_version);
67606 if (rv < 0) {
67607 log_error("S %s R %s res_convert lm error %d", ls->name, r->name, rv);
67608 return rv;
67609 }
67610
67611 log_debug("S %s R %s res_convert lm done", ls->name, r->name);
67612
67613 if (lk->mode == LD_LK_EX && act->mode == LD_LK_SH) {
67614 r->sh_count = 1;
67615 } else if (lk->mode == LD_LK_SH && act->mode == LD_LK_EX) {
67616 r->sh_count = 0;
67617 } else {
67618 /* should not be possible */
67619 log_error("S %s R %s res_convert invalid modes %d %d",
67620 ls->name, r->name, lk->mode, act->mode);
67621 return -1;
67622 }
67623
67624 r->mode = act->mode;
67625 lk->mode = act->mode;
67626
67627 return 0;
67628}
67629
67630static int res_cancel(struct lockspace *ls, struct resource *r,
67631 struct action *act)
67632{
67633 struct action *cact;
67634
67635 /*
67636 * a client can cancel its own non-persistent lock requests,
67637 * when could this happen?
67638 *
67639 * a client can cancel other client's persistent lock requests,
67640 * when could this happen?
67641 */
67642
67643 if (act->flags & LD_AF_PERSISTENT) {
67644 list_for_each_entry(cact, &r->actions, list) {
67645 if (!(cact->flags & LD_AF_PERSISTENT))
67646 continue;
67647 goto do_cancel;
67648 }
67649 } else {
67650 cact = find_action_client(r, act->client_id);
67651 if (cact)
67652 goto do_cancel;
67653 }
67654
67655 return -ENOENT;
67656
67657do_cancel:
67658 log_debug("S %s R %s res_cancel cl %u", ls->name, r->name, cact->client_id);
67659 cact->result = -ECANCELED;
67660 list_del(&cact->list);
67661 add_client_result(cact);
67662
67663 return -ECANCELED;
67664}
67665
67666/*
67667 * lm_unlock() writes new a r_version (from ex)
67668 *
67669 * The r_version of the vg resource is incremented if
67670 * an "update" was received for the vg lock. The update
67671 * contains the new vg seqno from the vg metadata which is
67672 * used as the r_version.
67673 *
67674 * The r_version of the global resource is automatically
67675 * incremented when it is unlocked from ex mode.
67676 *
67677 * r_version is incremented every time a command releases
67678 * the global lock from ex.
67679 */
67680
67681/*
67682 * persistent locks will not be unlocked for OP_CLOSE/act_close
67683 * because act_close->flags does not have the PERSISTENT flag
67684 * set, and a persistent lk->client_id is zero, which will not
67685 * match the client in act_close->client_id.
67686 */
67687
67688static int res_unlock(struct lockspace *ls, struct resource *r,
67689 struct action *act)
67690{
67691 struct lock *lk;
67692 uint32_t r_version;
67693 int rv;
67694
67695 if (act->flags & LD_AF_PERSISTENT) {
67696 lk = find_lock_persistent(r);
67697 if (lk)
67698 goto do_unlock;
67699 } else {
67700 lk = find_lock_client(r, act->client_id);
67701 if (lk)
67702 goto do_unlock;
67703 }
67704
67705 if (act->op != LD_OP_CLOSE)
67706 log_debug("S %s R %s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
67707 return -ENOENT;
67708
67709do_unlock:
67710 if ((act->flags & LD_AF_LV_UNLOCK) && (r->last_client_id != act->client_id)) {
67711 log_debug("S %s R %s res_unlock cl %u for failed client ignored, last client %u",
67712 ls->name, r->name, act->client_id, r->last_client_id);
67713 return -ENOENT;
67714 }
67715
67716 r->last_client_id = act->client_id;
67717
67718 if (act->op == LD_OP_CLOSE)
67719 log_debug("S %s R %s res_unlock cl %u from close", ls->name, r->name, act->client_id);
67720 else if (r->type == LD_RT_LV)
67721 log_debug("S %s R %s res_unlock cl %u (%s)", ls->name, r->name, act->client_id, act->lv_name);
67722 else
67723 log_debug("S %s R %s res_unlock cl %u", ls->name, r->name, act->client_id);
67724
67725 /* send unlock to lm when last sh lock is unlocked */
67726 if (lk->mode == LD_LK_SH) {
67727 r->sh_count--;
67728 if (r->sh_count > 0) {
67729 log_debug("S %s R %s res_unlock sh_count %u", ls->name, r->name, r->sh_count);
67730 goto rem_lk;
67731 }
67732 }
67733
67734 if ((r->type == LD_RT_GL) && (r->mode == LD_LK_EX)) {
67735 r->version++;
67736 lk->version = r->version;
67737 r_version = r->version;
67738 r->version_zero_valid = 0;
67739
67740 log_debug("S %s R %s res_unlock r_version inc %u", ls->name, r->name, r_version);
67741
67742 } else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk->version > r->version)) {
67743 r->version = lk->version;
67744 r_version = r->version;
67745 r->version_zero_valid = 0;
67746
67747 log_debug("S %s R %s res_unlock r_version new %u",
67748 ls->name, r->name, r_version);
67749 } else {
67750 r_version = 0;
67751 }
67752
67753 rv = lm_unlock(ls, r, act, r_version, 0);
67754 if (rv < 0) {
67755 /* should never happen, retry? */
67756 log_error("S %s R %s res_unlock lm error %d", ls->name, r->name, rv);
67757 return rv;
67758 }
67759
67760 log_debug("S %s R %s res_unlock lm done", ls->name, r->name);
67761
67762rem_lk:
67763 list_del(&lk->list);
67764 free_lock(lk);
67765
67766 if (list_empty(&r->locks))
67767 r->mode = LD_LK_UN;
67768
67769 return 0;
67770}
67771
67772static int res_update(struct lockspace *ls, struct resource *r,
67773 struct action *act)
67774{
67775 struct lock *lk;
67776
67777 lk = find_lock_client(r, act->client_id);
67778 if (!lk) {
67779 log_error("S %s R %s res_update cl %u lock not found",
67780 ls->name, r->name, act->client_id);
67781 return -ENOENT;
67782 }
67783
67784 if (r->mode != LD_LK_EX) {
67785 log_error("S %s R %s res_update cl %u version on non-ex lock",
67786 ls->name, r->name, act->client_id);
67787 return -EINVAL;
67788 }
67789
67790 /* lk version will be written to lm by unlock */
67791
67792 if (act->flags & LD_AF_NEXT_VERSION)
67793 lk->version = r->version + 1;
67794 else {
67795 if (r->version >= act->version) {
67796 /*
67797 * This update is done from vg_write. If the metadata with
67798 * this seqno is not committed by vg_commit, then next
67799 * vg_write can use the same seqno, causing us to see no
67800 * increase in seqno here as expected.
67801 * FIXME: In this case, do something like setting the lvb
67802 * version to 0 to instead of the same seqno which will
67803 * force an invalidation on other hosts. The next change
67804 * will return to using the seqno again.
67805 */
67806 log_error("S %s R %s res_update cl %u old version %u new version %u too small",
67807 ls->name, r->name, act->client_id, r->version, act->version);
67808 }
67809 lk->version = act->version;
67810 }
67811
67812 log_debug("S %s R %s res_update cl %u lk version to %u", ls->name, r->name, act->client_id, lk->version);
67813
67814 return 0;
67815}
67816
67817/*
67818 * There is nothing to deallocate when freeing a dlm LV, the LV
67819 * will simply be unlocked by rem_resource.
67820 */
67821
67822static int free_lv(struct lockspace *ls, struct resource *r)
67823{
67824 if (ls->lm_type == LD_LM_SANLOCK)
67825 return lm_free_lv_sanlock(ls, r);
67826 else if (ls->lm_type == LD_LM_DLM)
67827 return 0;
67828 else
67829 return -EINVAL;
67830}
67831
67832/*
67833 * NB. we can't do this if sanlock is holding any locks on
67834 * the resource; we'd be rewriting the resource from under
67835 * sanlock and would confuse or break it badly. We don't
67836 * know what another host is doing, so these must be used
67837 * very carefully.
67838 */
67839
67840static int res_able(struct lockspace *ls, struct resource *r,
67841 struct action *act)
67842{
67843 int rv;
67844
67845 if (ls->lm_type != LD_LM_SANLOCK) {
67846 log_error("enable/disable only applies to sanlock");
67847 return -EINVAL;
67848 }
67849
67850 if (r->type != LD_RT_GL) {
67851 log_error("enable/disable only applies to global lock");
67852 return -EINVAL;
67853 }
67854
67855 if (r->mode != LD_LK_UN) {
67856 log_error("enable/disable only allowed on unlocked resource");
67857 return -EINVAL;
67858 }
67859
67860 if (act->op == LD_OP_ENABLE && gl_lsname_sanlock[0]) {
67861 log_error("disable global lock in %s before enable in %s",
67862 gl_lsname_sanlock, ls->name);
67863 return -EINVAL;
67864 }
67865
67866 if ((act->op == LD_OP_DISABLE) && (act->flags & LD_AF_EX_DISABLE)) {
67867 rv = lm_ex_disable_gl_sanlock(ls);
67868 goto out;
67869 }
67870
67871 rv = lm_able_gl_sanlock(ls, act->op == LD_OP_ENABLE);
67872
67873 if (!rv && (act->op == LD_OP_ENABLE))
67874 gl_vg_removed = 0;
67875out:
67876 return rv;
67877}
67878
67879/*
67880 * Go through queued actions, and make lock/unlock calls on the resource
67881 * based on the actions and the existing lock state.
67882 *
67883 * All lock operations sent to the lock manager are non-blocking.
67884 * This is because sanlock does not support lock queueing.
67885 * Eventually we could enhance this to take advantage of lock
67886 * queueing when available (i.e. for the dlm).
67887 *
67888 * act_close_list: list of CLOSE actions, identifying clients that have
67889 * closed/terminated their lvmlockd connection, and whose locks should
67890 * be released. Do not remove these actions from act_close_list.
67891 *
67892 * retry_out: set to 1 if the lock manager said we should retry,
67893 * meaning we should call res_process() again in a short while to retry.
67894 */
67895
67896static void res_process(struct lockspace *ls, struct resource *r,
67897 struct list_head *act_close_list, int *retry_out)
67898{
67899 struct action *act, *safe, *act_close;
67900 struct lock *lk;
67901 int lm_retry;
67902 int rv;
67903
67904 /*
67905 * handle version updates for ex locks
67906 * (new version will be written by unlock)
67907 */
67908
67909 list_for_each_entry_safe(act, safe, &r->actions, list) {
67910 if (act->op == LD_OP_UPDATE) {
67911 rv = res_update(ls, r, act);
67912 act->result = rv;
67913 list_del(&act->list);
67914 add_client_result(act);
67915 }
67916 }
67917
67918 /*
67919 * handle explicit unlock actions
67920 */
67921
67922 list_for_each_entry_safe(act, safe, &r->actions, list) {
67923 if ((act->op == LD_OP_LOCK) &&
67924 (act->mode == LD_LK_IV || act->mode == LD_LK_NL)) {
67925 act->result = -EINVAL;
67926 list_del(&act->list);
67927 add_client_result(act);
67928 }
67929
67930 if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
67931 rv = res_unlock(ls, r, act);
67932
67933 if (rv == -ENOENT && (act->flags & LD_AF_UNLOCK_CANCEL))
67934 rv = res_cancel(ls, r, act);
67935
67936 /*
67937 * possible unlock results:
67938 * 0: unlock succeeded
67939 * -ECANCELED: cancel succeeded
67940 * -ENOENT: nothing to unlock or cancel
67941 */
67942
67943 act->result = rv;
67944 list_del(&act->list);
67945 add_client_result(act);
67946 }
67947 }
67948
67949 /*
67950 * handle implicit unlocks due to client exit,
67951 * also clear any outstanding actions for the client
67952 */
67953
67954 list_for_each_entry(act_close, act_close_list, list) {
67955 res_unlock(ls, r, act_close);
67956 res_cancel(ls, r, act_close);
67957 }
67958
67959 /*
67960 * handle freeing a lock for an lv that has been removed
67961 */
67962
67963 list_for_each_entry_safe(act, safe, &r->actions, list) {
67964 if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
67965 log_debug("S %s R %s free_lv", ls->name, r->name);
67966 rv = free_lv(ls, r);
67967 act->result = rv;
67968 list_del(&act->list);
67969 add_client_result(act);
67970 goto r_free;
67971
67972 }
67973 }
67974
67975 /*
67976 * handle enable/disable
67977 */
67978
67979 list_for_each_entry_safe(act, safe, &r->actions, list) {
67980 if (act->op == LD_OP_ENABLE || act->op == LD_OP_DISABLE) {
67981 rv = res_able(ls, r, act);
67982 act->result = rv;
67983 list_del(&act->list);
67984 add_client_result(act);
67985
67986 if (!rv && act->op == LD_OP_DISABLE) {
67987 log_debug("S %s R %s free disabled", ls->name, r->name);
67988 goto r_free;
67989 }
67990 }
67991 }
67992
67993 /*
67994 * transient requests on existing transient locks
67995 */
67996
67997 list_for_each_entry_safe(act, safe, &r->actions, list) {
67998 if (act->flags & LD_AF_PERSISTENT)
67999 continue;
68000
68001 lk = find_lock_client(r, act->client_id);
68002 if (!lk)
68003 continue;
68004
68005 if (lk->mode != act->mode) {
68006 /* convert below */
68007 /*
68008 act->result = -EEXIST;
68009 list_del(&act->list);
68010 add_client_result(act);
68011 */
68012 continue;
68013 } else {
68014 /* success */
68015 r->last_client_id = act->client_id;
68016 act->result = -EALREADY;
68017 list_del(&act->list);
68018 add_client_result(act);
68019 }
68020 }
68021
68022 /*
68023 * persistent requests on existing persistent locks
68024 *
68025 * persistent locks are not owned by a client, so any
68026 * existing with matching mode satisfies a request.
68027 * only one persistent lock is kept on a resource.
68028 * a single "unowned" persistent lock satisfies
68029 * any/multiple client requests for a persistent lock.
68030 */
68031
68032 list_for_each_entry_safe(act, safe, &r->actions, list) {
68033 if (!(act->flags & LD_AF_PERSISTENT))
68034 continue;
68035
68036 lk = find_lock_persistent(r);
68037 if (!lk)
68038 continue;
68039
68040 if (lk->mode != act->mode) {
68041 /* convert below */
68042 /*
68043 act->result = -EEXIST;
68044 list_del(&act->list);
68045 add_client_result(act);
68046 */
68047 continue;
68048 } else {
68049 /* success */
68050 r->last_client_id = act->client_id;
68051 act->result = -EALREADY;
68052 list_del(&act->list);
68053 add_client_result(act);
68054 }
68055 }
68056
68057 /*
68058 * transient requests with existing persistent locks
68059 *
68060 * Just grant the transient request and do not
68061 * keep a record of it. Assume that the persistent
68062 * lock will not go away while the transient lock
68063 * is needed.
68064 *
68065 * This would be used when an ex, persistent lv lock
68066 * exists from activation, and then something like
68067 * lvextend asks for a transient ex lock to change
68068 * the lv. The lv could not be unlocked by deactivation
68069 * while the lvextend was running.
68070 *
68071 * The logic here for mixing T/P locks is not general
68072 * support; there are a number of cases where it will
68073 * not work: updating version number (lv locks have
68074 * none), ex locks from multiple clients will not
68075 * conflict, explicit un of the transient lock will fail.
68076 */
68077
68078 list_for_each_entry_safe(act, safe, &r->actions, list) {
68079 if (act->flags & LD_AF_PERSISTENT)
68080 continue;
68081
68082 lk = find_lock_persistent(r);
68083 if (!lk)
68084 continue;
68085
68086 if ((lk->mode == LD_LK_EX) ||
68087 (lk->mode == LD_LK_SH && act->mode == LD_LK_SH)) {
68088 r->last_client_id = act->client_id;
68089 act->result = 0;
68090 list_del(&act->list);
68091 add_client_result(act);
68092 } else {
68093 /* persistent lock is sh, transient request is ex */
68094 /* FIXME: can we remove this case? do a convert here? */
68095 log_debug("res_process %s existing persistent lock new transient", r->name);
68096 r->last_client_id = act->client_id;
68097 act->result = -EEXIST;
68098 list_del(&act->list);
68099 add_client_result(act);
68100 }
68101 }
68102
68103 /*
68104 * persistent requests with existing transient locks
68105 *
68106 * If a client requests a P (persistent) lock for a T (transient)
68107 * lock it already holds, we can just change T to P. Fail if the
68108 * same happens for locks from different clients. Changing
68109 * another client's lock from T to P may cause problems
68110 * if that client tries to unlock or update version.
68111 *
68112 * I don't think this P/T combination will be used.
68113 * It might be used if a command was able to take a P
68114 * vg lock, in which case the T vg lock would already
68115 * be held for reading. If the T lock was sh, it would
68116 * be converted to P ex. If the T/P modes matched, the
68117 * lock could just be changed from T to P.
68118 */
68119
68120 list_for_each_entry_safe(act, safe, &r->actions, list) {
68121 if (!(act->flags & LD_AF_PERSISTENT))
68122 continue;
68123
68124 lk = find_lock_client(r, act->client_id);
68125 if (!lk)
68126 continue;
68127
68128 if (lk->mode != act->mode) {
68129 /* FIXME: convert and change to persistent? */
68130 log_debug("res_process %s existing transient lock new persistent", r->name);
68131 r->last_client_id = act->client_id;
68132 act->result = -EEXIST;
68133 list_del(&act->list);
68134 add_client_result(act);
68135 } else {
68136 r->last_client_id = act->client_id;
68137 lk->flags |= LD_LF_PERSISTENT;
68138 lk->client_id = 0;
68139 act->result = 0;
68140 list_del(&act->list);
68141 add_client_result(act);
68142 }
68143 }
68144
68145 /*
68146 * convert mode of existing locks
68147 */
68148
68149 list_for_each_entry_safe(act, safe, &r->actions, list) {
68150 if (act->flags & LD_AF_PERSISTENT)
68151 lk = find_lock_persistent(r);
68152 else
68153 lk = find_lock_client(r, act->client_id);
68154 if (!lk)
68155 continue;
68156
68157 if (lk->mode == act->mode) {
68158 /* should never happen, should be found above */
68159 log_error("convert same mode");
68160 continue;
68161 }
68162
68163 /* convert fails immediately, no EAGAIN retry */
68164 rv = res_convert(ls, r, lk, act);
68165 act->result = rv;
68166 list_del(&act->list);
68167 add_client_result(act);
68168 }
68169
68170 /*
68171 * Cases above are all requests addressed by existing locks.
68172 * Below handles the rest. Transient and persistent are
68173 * handled the same, except
68174 * - if mode of existing lock is incompat with requested,
68175 * leave the act on r->actions
68176 * - if r mode is EX, any lock action is blocked, just quit
68177 *
68178 * Retry a lock request that fails due to a lock conflict (-EAGAIN):
68179 * if we have not exceeded max retries and lm sets lm_retry (sanlock
68180 * transient conflicts from shared lock implementation), or r type
68181 * is gl or vg (transient real conflicts we want to hide from command).
68182 * lv lock conflicts won't be transient so don't retry them.
68183 */
68184
68185 if (r->mode == LD_LK_EX)
68186 return;
68187
68188 /*
68189 * r mode is SH or UN, pass lock-sh actions to lm
68190 */
68191
68192 list_for_each_entry_safe(act, safe, &r->actions, list) {
68193 /* grant in order, so break here */
68194 if (act->op == LD_OP_LOCK && act->mode == LD_LK_EX)
68195 break;
68196
68197 if (act->op == LD_OP_LOCK && act->mode == LD_LK_SH) {
68198 lm_retry = 0;
68199
68200 rv = res_lock(ls, r, act, &lm_retry);
68201 if ((rv == -EAGAIN) &&
68202 (act->retries <= act->max_retries) &&
68203 (lm_retry || (r->type != LD_RT_LV))) {
68204 /* leave act on list */
68205 log_debug("S %s R %s res_lock EAGAIN retry", ls->name, r->name);
68206 act->retries++;
68207 *retry_out = 1;
68208 } else {
68209 act->result = rv;
68210 list_del(&act->list);
68211 add_client_result(act);
68212 }
68213 if (rv == -EUNATCH)
68214 goto r_free;
68215 }
68216 }
68217
68218 /*
68219 * r mode is SH, any ex lock action is blocked, just quit
68220 */
68221
68222 if (r->mode == LD_LK_SH)
68223 return;
68224
68225 /*
68226 * r mode is UN, pass lock-ex action to lm
68227 */
68228
68229 list_for_each_entry_safe(act, safe, &r->actions, list) {
68230 if (act->op == LD_OP_LOCK && act->mode == LD_LK_EX) {
68231 lm_retry = 0;
68232
68233 rv = res_lock(ls, r, act, &lm_retry);
68234 if ((rv == -EAGAIN) &&
68235 (act->retries <= act->max_retries) &&
68236 (lm_retry || (r->type != LD_RT_LV))) {
68237 /* leave act on list */
68238 log_debug("S %s R %s res_lock EAGAIN retry", ls->name, r->name);
68239 act->retries++;
68240 *retry_out = 1;
68241 } else {
68242 act->result = rv;
68243 list_del(&act->list);
68244 add_client_result(act);
68245 }
68246 if (rv == -EUNATCH)
68247 goto r_free;
68248 break;
68249 }
68250 }
68251
68252 return;
68253
68254r_free:
68255 /* For the EUNATCH case it may be possible there are queued actions? */
68256 list_for_each_entry_safe(act, safe, &r->actions, list) {
68257 log_error("S %s R %s res_process r_free cancel %s client %d",
68258 ls->name, r->name, op_str(act->op), act->client_id);
68259 act->result = -ECANCELED;
68260 list_del(&act->list);
68261 add_client_result(act);
68262 }
68263 log_debug("S %s R %s res_process free", ls->name, r->name);
68264 lm_rem_resource(ls, r);
68265 list_del(&r->list);
68266 free_resource(r);
68267}
68268
68269#define LOCKS_EXIST_ANY 1
68270#define LOCKS_EXIST_GL 2
68271#define LOCKS_EXIST_VG 3
68272#define LOCKS_EXIST_LV 4
68273
68274static int for_each_lock(struct lockspace *ls, int locks_do)
68275{
68276 struct resource *r;
68277 struct lock *lk;
68278
68279 list_for_each_entry(r, &ls->resources, list) {
68280 list_for_each_entry(lk, &r->locks, list) {
68281 if (locks_do == LOCKS_EXIST_ANY)
68282 return 1;
68283
68284 if (locks_do == LOCKS_EXIST_GL && r->type == LD_RT_GL)
68285 return 1;
68286
68287 if (locks_do == LOCKS_EXIST_VG && r->type == LD_RT_VG)
68288 return 1;
68289
68290 if (locks_do == LOCKS_EXIST_LV && r->type == LD_RT_LV)
68291 return 1;
68292 }
68293 }
68294
68295 return 0;
68296}
68297
68298static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
68299{
68300 struct resource *r, *r_safe;
68301 struct lock *lk, *lk_safe;
68302 struct action *act, *act_safe;
68303 uint32_t lk_version;
68304 uint32_t r_version;
68305 int lk_count = 0;
68306 int rv;
68307
68308 list_for_each_entry_safe(r, r_safe, &ls->resources, list) {
68309 lk_version = 0;
68310
68311 list_for_each_entry_safe(lk, lk_safe, &r->locks, list) {
68312 lk_count++;
68313
68314 /*
68315 * Stopping a lockspace shouldn't happen with LV locks
68316 * still held, but it will be stopped with GL and VG
68317 * locks held. The drop_vg case may see LV locks.
68318 */
68319
68320 if (lk->flags & LD_LF_PERSISTENT && !drop_vg)
68321 log_error("S %s R %s clear lock persistent", ls->name, r->name);
68322 else
68323 log_debug("S %s R %s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
68324
68325 if (lk->version > lk_version)
68326 lk_version = lk->version;
68327
68328 list_del(&lk->list);
68329 free_lock(lk);
68330 }
68331
68332 if (r->mode == LD_LK_UN)
68333 goto r_free;
68334
68335 if ((r->type == LD_RT_GL) && (r->mode == LD_LK_EX)) {
68336 r->version++;
68337 r_version = r->version;
68338 log_debug("S %s R %s clear_locks r_version inc %u",
68339 ls->name, r->name, r_version);
68340
68341 } else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk_version > r->version)) {
68342 r->version = lk_version;
68343 r_version = r->version;
68344 log_debug("S %s R %s clear_locks r_version new %u",
68345 ls->name, r->name, r_version);
68346
68347 } else {
68348 r_version = 0;
68349 }
68350
68351 rv = lm_unlock(ls, r, NULL, r_version, free_vg ? LMUF_FREE_VG : 0);
68352 if (rv < 0) {
68353 /* should never happen */
68354 log_error("S %s R %s clear_locks free %d drop %d lm unlock error %d",
68355 ls->name, r->name, free_vg, drop_vg, rv);
68356 }
68357
68358 list_for_each_entry_safe(act, act_safe, &r->actions, list) {
68359 log_error("S %s R %s clear_locks cancel %s client %d",
68360 ls->name, r->name, op_str(act->op), act->client_id);
68361 act->result = -ECANCELED;
68362 list_del(&act->list);
68363 add_client_result(act);
68364 }
68365 r_free:
68366 log_debug("S %s R %s free", ls->name, r->name);
68367 lm_rem_resource(ls, r);
68368 list_del(&r->list);
68369 free_resource(r);
68370 }
68371
68372 return lk_count;
68373}
68374
68375/*
68376 * find and return the resource that is referenced by the action
68377 * - there is a single gl resource per lockspace
68378 * - there is a single vg resource per lockspace
68379 * - there can be many lv resources per lockspace, compare names
68380 */
68381
68382static struct resource *find_resource_act(struct lockspace *ls,
68383 struct action *act,
68384 int nocreate)
68385{
68386 struct resource *r;
68387
68388 list_for_each_entry(r, &ls->resources, list) {
68389 if (r->type != act->rt)
68390 continue;
68391
68392 if (r->type == LD_RT_GL && act->rt == LD_RT_GL)
68393 return r;
68394
68395 if (r->type == LD_RT_VG && act->rt == LD_RT_VG)
68396 return r;
68397
68398 if (r->type == LD_RT_LV && act->rt == LD_RT_LV &&
68399 !strcmp(r->name, act->lv_uuid))
68400 return r;
68401 }
68402
68403 if (nocreate)
68404 return NULL;
68405
68406 if (!(r = alloc_resource()))
68407 return NULL;
68408
68409 r->type = act->rt;
68410 r->mode = LD_LK_UN;
68411
68412 if (r->type == LD_RT_GL) {
68413 strncpy(r->name, R_NAME_GL, MAX_NAME);
68414 r->use_vb = 1;
68415 } else if (r->type == LD_RT_VG) {
68416 strncpy(r->name, R_NAME_VG, MAX_NAME);
68417 r->use_vb = 1;
68418 } else if (r->type == LD_RT_LV) {
68419 strncpy(r->name, act->lv_uuid, MAX_NAME);
68420 r->use_vb = 0;
68421 }
68422
68423 list_add_tail(&r->list, &ls->resources);
68424
68425 return r;
68426}
68427
68428static void free_ls_resources(struct lockspace *ls)
68429{
68430 struct resource *r, *r_safe;
68431
68432 list_for_each_entry_safe(r, r_safe, &ls->resources, list) {
68433 lm_rem_resource(ls, r);
68434 list_del(&r->list);
68435 free_resource(r);
68436 }
68437}
68438
68439/*
68440 * ls is the vg being removed that holds the global lock.
68441 * check if any other vgs will be left without a global lock.
68442 */
68443
68444static int other_sanlock_vgs_exist(struct lockspace *ls_rem)
68445{
68446 struct lockspace *ls;
68447
68448 list_for_each_entry(ls, &lockspaces, list) {
68449 if (ls->lm_type != LD_LM_SANLOCK)
68450 continue;
68451 if (!strcmp(ls->name, ls_rem->name))
68452 continue;
68453 log_debug("other sanlock vg exists %s", ls->name);
68454 return 1;
68455 }
68456
68457 return 0;
68458}
68459
68460/*
68461 * LOCK is the main thing we're interested in; the others are unlikely.
68462 */
68463
68464static int process_op_during_kill(struct action *act)
68465{
68466 if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN)
68467 return 1;
68468
68469 switch (act->op) {
68470 case LD_OP_LOCK:
68471 case LD_OP_ENABLE:
68472 case LD_OP_DISABLE:
68473 case LD_OP_UPDATE:
68474 case LD_OP_RENAME_BEFORE:
68475 case LD_OP_RENAME_FINAL:
68476 case LD_OP_FIND_FREE_LOCK:
68477 return 0;
68478 };
68479 return 1;
68480}
68481
68482/*
68483 * Process actions queued for this lockspace by
68484 * client_recv_action / add_lock_action.
68485 *
68486 * The lockspace_thread can touch its own ls struct without holding
68487 * lockspaces_mutex until it sets ls->thread_done, after which it
68488 * cannot touch ls without holding lockspaces_mutex.
68489 */
68490
68491#define LOCK_RETRY_MS 1000 /* milliseconds to delay between retry */
68492
68493static void *lockspace_thread_main(void *arg_in)
68494{
68495 struct lockspace *ls = arg_in;
68496 struct resource *r, *r2;
68497 struct action *add_act, *act, *safe;
68498 struct action *act_op_free = NULL;
68499 struct list_head tmp_act;
68500 struct list_head act_close;
68501 char tmp_name[MAX_NAME+1];
68502 int free_vg = 0;
68503 int drop_vg = 0;
68504 int error = 0;
68505 int adopt_flag = 0;
68506 int wait_flag = 0;
68507 int retry;
68508 int rv;
68509
68510 INIT_LIST_HEAD(&act_close);
68511
68512 /* first action may be client add */
68513 pthread_mutex_lock(&ls->mutex);
68514 act = NULL;
68515 add_act = NULL;
68516 if (!list_empty(&ls->actions)) {
68517 act = list_first_entry(&ls->actions, struct action, list);
68518 if (act->op == LD_OP_START) {
68519 add_act = act;
68520 list_del(&add_act->list);
68521
68522 if (add_act->flags & LD_AF_WAIT)
68523 wait_flag = 1;
68524 if (add_act->flags & LD_AF_ADOPT)
68525 adopt_flag = 1;
68526 }
68527 }
68528 pthread_mutex_unlock(&ls->mutex);
68529
68530 log_debug("S %s lm_add_lockspace %s wait %d adopt %d",
68531 ls->name, lm_str(ls->lm_type), wait_flag, adopt_flag);
68532
68533 /*
68534 * The prepare step does not wait for anything and is quick;
68535 * it tells us if the parameters are valid and the lm is running.
68536 */
68537 error = lm_prepare_lockspace(ls, add_act);
68538
68539 if (add_act && (!wait_flag || error)) {
68540 /* send initial join result back to client */
68541 add_act->result = error;
68542 add_client_result(add_act);
68543 add_act = NULL;
68544 }
68545
68546 /*
68547 * The actual lockspace join can take a while.
68548 */
68549 if (!error) {
68550 error = lm_add_lockspace(ls, add_act, adopt_flag);
68551
68552 log_debug("S %s lm_add_lockspace done %d", ls->name, error);
68553
68554 if (ls->sanlock_gl_enabled && gl_lsname_sanlock[0] &&
68555 strcmp(ls->name, gl_lsname_sanlock))
68556 sanlock_gl_dup = 1;
68557
68558 if (add_act) {
68559 /* send final join result back to client */
68560 add_act->result = error;
68561 add_client_result(add_act);
68562 }
68563 }
68564
68565 pthread_mutex_lock(&ls->mutex);
68566 if (error) {
68567 ls->thread_stop = 1;
68568 ls->create_fail = 1;
68569 } else {
68570 ls->create_done = 1;
68571 }
68572 pthread_mutex_unlock(&ls->mutex);
68573
68574 if (error)
68575 goto out_act;
68576
68577 while (1) {
68578 pthread_mutex_lock(&ls->mutex);
68579 while (!ls->thread_work) {
68580 if (ls->thread_stop) {
68581 pthread_mutex_unlock(&ls->mutex);
68582 goto out_rem;
68583 }
68584 pthread_cond_wait(&ls->cond, &ls->mutex);
68585 }
68586
68587 /*
68588 * Process all the actions queued for this lockspace.
68589 * The client thread queues actions on ls->actions.
68590 *
68591 * Here, take all the actions off of ls->actions, and:
68592 *
68593 * - For lock operations, move the act to r->actions.
68594 * These lock actions/operations processed by res_process().
68595 *
68596 * - For non-lock operations, e.g. related to managing
68597 * the lockspace, process them in this loop.
68598 */
68599
68600 while (1) {
68601 if (list_empty(&ls->actions)) {
68602 ls->thread_work = 0;
68603 break;
68604 }
68605
68606 act = list_first_entry(&ls->actions, struct action, list);
68607
68608 if (act->op == LD_OP_KILL_VG && act->rt == LD_RT_VG) {
68609 /* Continue processing until DROP_VG arrives. */
68610 log_debug("S %s kill_vg", ls->name);
68611 ls->kill_vg = 1;
68612 list_del(&act->list);
68613 act->result = 0;
68614 add_client_result(act);
68615 continue;
68616 }
68617
68618 if (ls->kill_vg && !process_op_during_kill(act)) {
68619 log_debug("S %s disallow op %s after kill_vg", ls->name, op_str(act->op));
68620 list_del(&act->list);
68621 act->result = -EVGKILLED;
68622 add_client_result(act);
68623 continue;
68624 }
68625
68626 if (act->op == LD_OP_DROP_VG && act->rt == LD_RT_VG) {
68627 /*
68628 * If leases are released after i/o errors begin
68629 * but before lvmlockctl --kill, then the VG is not
68630 * killed, but drop is still needed to clean up the
68631 * VG, so in that case there would be a drop op without
68632 * a preceding kill op.
68633 */
68634 if (!ls->kill_vg)
68635 log_debug("S %s received drop without kill", ls->name);
68636 log_debug("S %s drop_vg", ls->name);
68637 ls->thread_work = 0;
68638 ls->thread_stop = 1;
68639 drop_vg = 1;
68640 break;
68641 }
68642
68643 if (act->op == LD_OP_STOP) {
68644 /* thread_stop is already set */
68645 ls->thread_work = 0;
68646 break;
68647 }
68648
68649 if (act->op == LD_OP_FREE && act->rt == LD_RT_VG) {
68650 /* vgremove */
68651 log_debug("S %s checking for lockspace hosts", ls->name);
68652 rv = lm_hosts(ls, 1);
68653 if (rv) {
68654 /*
68655 * Checking for hosts here in addition to after the
68656 * main loop allows vgremove to fail and be rerun
68657 * after the ls is stopped on other hosts.
68658 */
68659 log_error("S %s lockspace hosts %d", ls->name, rv);
68660 list_del(&act->list);
68661 act->result = -EBUSY;
68662 add_client_result(act);
68663 continue;
68664 }
68665 ls->thread_work = 0;
68666 ls->thread_stop = 1;
68667 free_vg = 1;
68668 break;
68669 }
68670
68671 if (act->op == LD_OP_BUSY && act->rt == LD_RT_VG) {
68672 log_debug("S %s checking if lockspace is busy", ls->name);
68673 rv = lm_hosts(ls, 0);
68674 if (rv)
68675 act->result = -EBUSY;
68676 else
68677 act->result = 0;
68678 list_del(&act->list);
68679 add_client_result(act);
68680 continue;
68681 }
68682
68683 if (act->op == LD_OP_RENAME_BEFORE && act->rt == LD_RT_VG) {
68684 /* vgrename */
68685 log_debug("S %s checking for lockspace hosts", ls->name);
68686 rv = lm_hosts(ls, 1);
68687 if (rv) {
68688 log_error("S %s lockspace hosts %d", ls->name, rv);
68689 list_del(&act->list);
68690 act->result = -EBUSY;
68691 add_client_result(act);
68692 continue;
68693 }
68694 ls->thread_work = 0;
68695 ls->thread_stop = 1;
68696 /* Do we want to check hosts again below like vgremove? */
68697 break;
68698 }
68699
68700 if (act->op == LD_OP_FIND_FREE_LOCK && act->rt == LD_RT_VG) {
68701 uint64_t free_offset = 0;
68702 log_debug("S %s find free lock", ls->name);
68703 rv = lm_find_free_lock(ls, &free_offset);
68704 log_debug("S %s find free lock %d offset %llu",
68705 ls->name, rv, (unsigned long long)free_offset);
68706 ls->free_lock_offset = free_offset;
68707 list_del(&act->list);
68708 act->result = rv;
68709 add_client_result(act);
68710 continue;
68711 }
68712
68713 list_del(&act->list);
68714
68715 /* applies to all resources */
68716 if (act->op == LD_OP_CLOSE) {
68717 list_add(&act->list, &act_close);
68718 continue;
68719 }
68720
68721 /*
68722 * All the other op's are for locking.
68723 * Find the specific resource that the lock op is for,
68724 * and add the act to the resource's list of lock ops.
68725 *
68726 * (This creates a new resource if the one named in
68727 * the act is not found.)
68728 */
68729
68730 r = find_resource_act(ls, act, (act->op == LD_OP_FREE) ? 1 : 0);
68731 if (!r) {
68732 act->result = (act->op == LD_OP_FREE) ? -ENOENT : -ENOMEM;
68733 add_client_result(act);
68734 continue;
68735 }
68736
68737 list_add_tail(&act->list, &r->actions);
68738
68739 log_debug("S %s R %s action %s %s", ls->name, r->name,
68740 op_str(act->op), mode_str(act->mode));
68741 }
68742 pthread_mutex_unlock(&ls->mutex);
68743
68744 /*
68745 * Process the lock operations that have been queued for each
68746 * resource.
68747 */
68748
68749 retry = 0;
68750
68751 list_for_each_entry_safe(r, r2, &ls->resources, list)
68752 res_process(ls, r, &act_close, &retry);
68753
68754 list_for_each_entry_safe(act, safe, &act_close, list) {
68755 list_del(&act->list);
68756 free_action(act);
68757 }
68758
68759 if (retry) {
68760 ls->thread_work = 1;
68761 usleep(LOCK_RETRY_MS * 1000);
68762 }
68763 }
68764
68765out_rem:
68766 log_debug("S %s stopping", ls->name);
68767
68768 /*
68769 * For sanlock, we need to unlock any existing locks
68770 * before removing the lockspace, otherwise the sanlock
68771 * daemon will kill us when the lockspace goes away.
68772 * For dlm, we leave with force, so all locks will
68773 * automatically be dropped when we leave the lockspace,
68774 * so unlocking all before leaving could be skipped.
68775 *
68776 * Blindly dropping all existing locks must only be
68777 * allowed in emergency/force situations, otherwise it's
68778 * obviously dangerous, since the lock holders are still
68779 * operating under the assumption that they hold the lock.
68780 * drop_vg drops all existing locks, but should only
68781 * happen when the VG access has been forcibly and
68782 * succesfully terminated.
68783 *
68784 * For vgremove of a sanlock vg, the vg lock will be held,
68785 * and possibly the gl lock if this vg holds the gl.
68786 * sanlock vgremove wants to unlock-rename these locks.
68787 */
68788
68789 log_debug("S %s clearing locks", ls->name);
68790
68791 rv = clear_locks(ls, free_vg, drop_vg);
68792
68793 /*
68794 * Tell any other hosts in the lockspace to leave it
68795 * before we remove it (for vgremove). We do this
68796 * before leaving the lockspace ourself because we
68797 * need to be in the lockspace to see others.
68798 */
68799
68800 if (free_vg) {
68801 log_debug("S %s checking for lockspace hosts", ls->name);
68802 rv = lm_hosts(ls, 1);
68803 if (rv)
68804 log_error("S %s other lockspace hosts %d", ls->name, rv);
68805 }
68806
68807 /*
68808 * Leave the lockspace.
68809 */
68810
68811 rv = lm_rem_lockspace(ls, NULL, free_vg);
68812
68813 log_debug("S %s rem_lockspace done %d", ls->name, rv);
68814
68815out_act:
68816 /*
68817 * Move remaining actions to results; this will usually (always?)
68818 * be only the stop action.
68819 */
68820 INIT_LIST_HEAD(&tmp_act);
68821
68822 pthread_mutex_lock(&ls->mutex);
68823 list_for_each_entry_safe(act, safe, &ls->actions, list) {
68824 if (act->op == LD_OP_FREE) {
68825 act_op_free = act;
68826 act->result = 0;
68827 } else if (act->op == LD_OP_STOP)
68828 act->result = 0;
68829 else if (act->op == LD_OP_DROP_VG)
68830 act->result = 0;
68831 else if (act->op == LD_OP_RENAME_BEFORE)
68832 act->result = 0;
68833 else
68834 act->result = -ENOLS;
68835 list_del(&act->list);
68836 list_add_tail(&act->list, &tmp_act);
68837 }
68838 pthread_mutex_unlock(&ls->mutex);
68839
68840 /*
68841 * If this freed a sanlock vg that had gl enabled, and other sanlock
68842 * vgs exist, return a flag so the command can warn that the gl has
68843 * been removed and may need to be enabled in another sanlock vg.
68844 */
68845
68846 if (free_vg && ls->sanlock_gl_enabled && act_op_free) {
68847 pthread_mutex_lock(&lockspaces_mutex);
68848 if (other_sanlock_vgs_exist(ls)) {
68849 act_op_free->flags |= LD_AF_WARN_GL_REMOVED;
68850 gl_vg_removed = 1;
68851 }
68852 pthread_mutex_unlock(&lockspaces_mutex);
68853 }
68854
68855 pthread_mutex_lock(&client_mutex);
68856 list_for_each_entry_safe(act, safe, &tmp_act, list) {
68857 list_del(&act->list);
68858 list_add_tail(&act->list, &client_results);
68859 }
68860 pthread_cond_signal(&client_cond);
68861 pthread_mutex_unlock(&client_mutex);
68862
68863 pthread_mutex_lock(&lockspaces_mutex);
68864 ls->thread_done = 1;
68865 ls->free_vg = free_vg;
68866 ls->drop_vg = drop_vg;
68867 if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
68868 global_dlm_lockspace_exists = 0;
68869 /* Avoid a name collision of the same lockspace is added again before this thread is cleaned up. */
68870 memset(tmp_name, 0, sizeof(tmp_name));
68871 snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
68872 memcpy(ls->name, tmp_name, MAX_NAME);
68873 pthread_mutex_unlock(&lockspaces_mutex);
68874
68875 /* worker_thread will join this thread, and free the ls */
68876 pthread_mutex_lock(&worker_mutex);
68877 worker_wake = 1;
68878 pthread_cond_signal(&worker_cond);
68879 pthread_mutex_unlock(&worker_mutex);
68880
68881 return NULL;
68882}
68883
68884int lockspaces_empty(void)
68885{
68886 int rv;
68887 pthread_mutex_lock(&lockspaces_mutex);
68888 rv = list_empty(&lockspaces);
68889 pthread_mutex_unlock(&lockspaces_mutex);
68890 return rv;
68891}
68892
68893/*
68894 * lockspaces_mutex is locked
68895 *
68896 * When duplicate sanlock global locks have been seen,
68897 * this function has a secondary job of counting the
68898 * number of lockspaces that exist with the gl enabled,
68899 * with the side effect of setting sanlock_gl_dup back to
68900 * zero when the duplicates have been removed/disabled.
68901 */
68902
68903static struct lockspace *find_lockspace_name(char *ls_name)
68904{
68905 struct lockspace *ls_found = NULL;
68906 struct lockspace *ls;
68907 int gl_count = 0;
68908
68909 list_for_each_entry(ls, &lockspaces, list) {
68910 if (!strcmp(ls->name, ls_name))
68911 ls_found = ls;
68912
68913 if (!sanlock_gl_dup && ls_found)
68914 return ls_found;
68915
68916 if (sanlock_gl_dup && ls->sanlock_gl_enabled)
68917 gl_count++;
68918 }
68919
68920 /* this is the side effect we want from this function */
68921 if (sanlock_gl_dup && gl_count < 2)
68922 sanlock_gl_dup = 0;
68923
68924 return ls_found;
68925}
68926
68927/*
68928 * If lvm_<vg_name> is longer than max lockspace name (64) we just ignore the
68929 * extra characters. For sanlock vgs, the name is shortened further to 48 in
68930 * the sanlock code.
68931 */
68932
68933static int vg_ls_name(const char *vg_name, char *ls_name)
68934{
68935 if (strlen(vg_name) + 4 > MAX_NAME) {
68936 log_error("vg name too long %s", vg_name);
68937 return -1;
68938 }
68939
68940 snprintf(ls_name, MAX_NAME, "%s%s", LVM_LS_PREFIX, vg_name);
68941 return 0;
68942}
68943
68944/* FIXME: add mutex for gl_lsname_ ? */
68945
68946static void gl_ls_name(char *ls_name)
68947{
68948 if (gl_use_dlm)
68949 memcpy(ls_name, gl_lsname_dlm, MAX_NAME);
68950 else if (gl_use_sanlock)
68951 memcpy(ls_name, gl_lsname_sanlock, MAX_NAME);
68952 else
68953 memset(ls_name, 0, MAX_NAME);
68954}
68955
68956/*
68957 * When this function returns an error, the caller needs to deal
68958 * with act (in the cases where act exists).
68959 */
68960
68961static int add_lockspace_thread(const char *ls_name,
68962 const char *vg_name,
68963 const char *vg_uuid,
68964 int lm_type, const char *vg_args,
68965 struct action *act)
68966{
68967 struct lockspace *ls, *ls2;
68968 struct resource *r;
68969 int rv;
68970
68971 log_debug("add_lockspace_thread %s %s version %u",
68972 lm_str(lm_type), ls_name, act ? act->version : 0);
68973
68974 if (!(ls = alloc_lockspace()))
68975 return -ENOMEM;
68976
68977 strncpy(ls->name, ls_name, MAX_NAME);
68978 ls->lm_type = lm_type;
68979
68980 if (act)
68981 ls->start_client_id = act->client_id;
68982
68983 if (vg_uuid)
68984 strncpy(ls->vg_uuid, vg_uuid, 64);
68985
68986 if (vg_name)
68987 strncpy(ls->vg_name, vg_name, MAX_NAME);
68988
68989 if (vg_args)
68990 strncpy(ls->vg_args, vg_args, MAX_ARGS);
68991
68992 if (act)
68993 ls->host_id = act->host_id;
68994
68995 if (!(r = alloc_resource())) {
68996 free(ls);
68997 return -ENOMEM;
68998 }
68999
69000 r->type = LD_RT_VG;
69001 r->mode = LD_LK_UN;
69002 r->use_vb = 1;
69003 strncpy(r->name, R_NAME_VG, MAX_NAME);
69004 list_add_tail(&r->list, &ls->resources);
69005
69006 pthread_mutex_lock(&lockspaces_mutex);
69007 ls2 = find_lockspace_name(ls->name);
69008 if (ls2) {
69009 if (ls2->thread_stop) {
69010 log_debug("add_lockspace_thread %s exists and stopping", ls->name);
69011 rv = -EAGAIN;
69012 } else {
69013 log_debug("add_lockspace_thread %s exists", ls->name);
69014 rv = -EEXIST;
69015 }
69016 pthread_mutex_unlock(&lockspaces_mutex);
69017 free_resource(r);
69018 free(ls);
69019 return rv;
69020 }
69021
69022 /*
69023 * act will be null when this lockspace is added automatically/internally
69024 * and not by an explicit client action that wants a result.
69025 */
69026 if (act)
69027 list_add(&act->list, &ls->actions);
69028
69029 if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
69030 global_dlm_lockspace_exists = 1;
69031 list_add_tail(&ls->list, &lockspaces);
69032 pthread_mutex_unlock(&lockspaces_mutex);
69033
69034 rv = pthread_create(&ls->thread, NULL, lockspace_thread_main, ls);
69035 if (rv < 0) {
69036 log_error("add_lockspace_thread %s pthread error %d %d", ls->name, rv, errno);
69037 pthread_mutex_lock(&lockspaces_mutex);
69038 list_del(&ls->list);
69039 pthread_mutex_unlock(&lockspaces_mutex);
69040 free_resource(r);
69041 free(ls);
69042 return rv;
69043 }
69044
69045 return 0;
69046}
69047
69048/*
69049 * There is no add_sanlock_global_lockspace or
69050 * rem_sanlock_global_lockspace because with sanlock,
69051 * the global lockspace is one of the vg lockspaces.
69052 */
69053
69054static int add_dlm_global_lockspace(struct action *act)
69055{
69056 int rv;
69057
69058 if (global_dlm_lockspace_exists)
69059 return 0;
69060
69061 /*
69062 * FIXME: if the dlm global lockspace is started without a global
69063 * lock request, insert an internal gl sh lock request?
69064 */
69065
69066 rv = add_lockspace_thread(gl_lsname_dlm, NULL, NULL, LD_LM_DLM, NULL, act);
69067 if (rv < 0)
69068 log_debug("add_dlm_global_lockspace add_lockspace_thread %d", rv);
69069
69070 /*
69071 * EAGAIN may be returned for a short period because
69072 * global_dlm_lockspace_exists is set to 0 before the
69073 * ls is removed from the lockspaces list by the
69074 * worker_thread.
69075 */
69076
69077 return rv;
69078}
69079
69080/*
69081 * If dlm gl lockspace is the only one left, then stop it.
69082 * This is not used for an explicit rem_lockspace action from
69083 * the client, only for auto remove.
69084 */
69085
69086static int rem_dlm_global_lockspace(void)
69087{
69088 struct lockspace *ls, *ls_gl = NULL;
69089 int others = 0;
69090 int rv = 0;
69091
69092 pthread_mutex_lock(&lockspaces_mutex);
69093 list_for_each_entry(ls, &lockspaces, list) {
69094 if (!strcmp(ls->name, gl_lsname_dlm)) {
69095 ls_gl = ls;
69096 continue;
69097 }
69098 if (ls->thread_stop)
69099 continue;
69100 others++;
69101 break;
69102 }
69103
69104 if (others) {
69105 rv = -EAGAIN;
69106 goto out;
69107 }
69108
69109 if (!ls_gl) {
69110 rv = -ENOENT;
69111 goto out;
69112 }
69113
69114 ls = ls_gl;
69115 pthread_mutex_lock(&ls->mutex);
69116 ls->thread_stop = 1;
69117 ls->thread_work = 1;
69118 pthread_cond_signal(&ls->cond);
69119 pthread_mutex_unlock(&ls->mutex);
69120 rv = 0;
69121out:
69122 pthread_mutex_unlock(&lockspaces_mutex);
69123 return rv;
69124}
69125
69126/*
69127 * When the first dlm lockspace is added for a vg, automatically add a separate
69128 * dlm lockspace for the global lock.
69129 *
69130 * For sanlock, a separate lockspace is not used for the global lock, but the
69131 * gl lock lives in a vg lockspace, (although it's recommended to create a
69132 * special vg dedicated to holding the gl).
69133 */
69134
69135static int add_lockspace(struct action *act)
69136{
69137 char ls_name[MAX_NAME+1];
69138 int rv;
69139
69140 memset(ls_name, 0, sizeof(ls_name));
69141
69142 /*
69143 * FIXME: I don't think this is used any more.
69144 * Remove it, or add the ability to start the global
69145 * dlm lockspace using lvmlockctl?
69146 */
69147 if (act->rt == LD_RT_GL) {
69148 if (gl_use_dlm) {
69149 rv = add_dlm_global_lockspace(act);
69150 return rv;
69151 } else {
69152 return -EINVAL;
69153 }
69154 }
69155
69156 if (act->rt == LD_RT_VG) {
69157 if (gl_use_dlm)
69158 add_dlm_global_lockspace(NULL);
69159
69160 vg_ls_name(act->vg_name, ls_name);
69161
69162 rv = add_lockspace_thread(ls_name, act->vg_name, act->vg_uuid,
69163 act->lm_type, act->vg_args,
69164 act);
69165 if (rv)
69166 log_debug("add_lockspace %s add_lockspace_thread %d", ls_name, rv);
69167 return rv;
69168 }
69169
69170 log_error("add_lockspace bad type %d", act->rt);
69171 return -1;
69172}
69173
69174/*
69175 * vgchange --lock-stop vgname will lock the vg ex, then send a stop,
69176 * so we exect to find the ex vg lock held here, and will automatically
69177 * unlock it when stopping.
69178 *
69179 * Should we attempt to stop the lockspace containing the gl last?
69180 */
69181
69182static int rem_lockspace(struct action *act)
69183{
69184 struct lockspace *ls;
69185 char ls_name[MAX_NAME+1];
69186 int force = act->flags & LD_AF_FORCE;
69187 int rt = act->rt;
69188
69189 if (act->rt == LD_RT_GL && act->lm_type != LD_LM_DLM)
69190 return -EINVAL;
69191
69192 memset(ls_name, 0, sizeof(ls_name));
69193
69194 if (act->rt == LD_RT_GL)
69195 gl_ls_name(ls_name);
69196 else
69197 vg_ls_name(act->vg_name, ls_name);
69198
69199 pthread_mutex_lock(&lockspaces_mutex);
69200 ls = find_lockspace_name(ls_name);
69201 if (!ls) {
69202 pthread_mutex_unlock(&lockspaces_mutex);
69203 return -ENOLS;
69204 }
69205
69206 pthread_mutex_lock(&ls->mutex);
69207 if (ls->thread_stop) {
69208 pthread_mutex_unlock(&ls->mutex);
69209 pthread_mutex_unlock(&lockspaces_mutex);
69210 return -ESTALE;
69211 }
69212
69213 if (!force && for_each_lock(ls, LOCKS_EXIST_LV)) {
69214 pthread_mutex_unlock(&ls->mutex);
69215 pthread_mutex_unlock(&lockspaces_mutex);
69216 return -EBUSY;
69217 }
69218 ls->thread_work = 1;
69219 ls->thread_stop = 1;
69220 list_add_tail(&act->list, &ls->actions);
69221 pthread_cond_signal(&ls->cond);
69222 pthread_mutex_unlock(&ls->mutex);
69223 pthread_mutex_unlock(&lockspaces_mutex);
69224
69225 /*
69226 * The dlm global lockspace was automatically added when
69227 * the first dlm vg lockspace was added, now reverse that
69228 * by automatically removing the dlm global lockspace when
69229 * the last dlm vg lockspace is removed.
69230 */
69231
69232 if (rt == LD_RT_VG && gl_use_dlm)
69233 rem_dlm_global_lockspace();
69234
69235 return 0;
69236}
69237
69238/*
69239 * count how many lockspaces started by this client are still starting;
69240 * the client will use this to wait for all its start operations to finish
69241 * (START_WAIT).
69242 */
69243
69244static int count_lockspace_starting(uint32_t client_id)
69245{
69246 struct lockspace *ls;
69247 int count = 0;
69248 int done = 0;
69249 int fail = 0;
69250
69251 pthread_mutex_lock(&lockspaces_mutex);
69252 list_for_each_entry(ls, &lockspaces, list) {
69253 if (ls->start_client_id != client_id)
69254 continue;
69255
69256 if (!ls->create_done && !ls->create_fail) {
69257 count++;
69258 continue;
69259 }
69260
69261 if (ls->create_done)
69262 done++;
69263 if (ls->create_fail)
69264 fail++;
69265 }
69266 pthread_mutex_unlock(&lockspaces_mutex);
69267
69268 log_debug("count_lockspace_starting client %u count %d done %d fail %d",
69269 client_id, count, done, fail);
69270
69271 return count;
69272}
69273
69274/*
69275 * Loop through all lockspaces, and:
69276 * - if do_stop is set, stop any that are not stopped
69277 * - if do_free is set, join any that are done stopping (and free ls)
69278 *
69279 * do_stop will not stop an ls with lv locks unless force is set.
69280 *
69281 * This function does not block or wait for anything.
69282 *
69283 * do_stop (no do_free):
69284 * returns count of lockspaces that need stop (have locks and no force)
69285 *
69286 * do_free (no do_stop):
69287 * returns count of lockspaces that are stopped and need freeing
69288 *
69289 * do_stop and do_free:
69290 * returns sum of the previous two
69291 */
69292
69293static int for_each_lockspace(int do_stop, int do_free, int do_force)
69294{
69295 struct lockspace *ls, *safe;
69296 int need_stop = 0;
69297 int need_free = 0;
69298 int stop_count = 0;
69299 int free_count = 0;
69300 int done;
69301 int stop;
69302 int perrno;
69303
69304 pthread_mutex_lock(&lockspaces_mutex);
69305
69306 if (do_stop) {
69307 list_for_each_entry(ls, &lockspaces, list) {
69308
69309 pthread_mutex_lock(&ls->mutex);
69310 if (ls->thread_stop) {
69311 pthread_mutex_unlock(&ls->mutex);
69312 continue;
69313 }
69314
69315 if (!do_force && for_each_lock(ls, LOCKS_EXIST_ANY)) {
69316 need_stop++;
69317 } else {
69318 ls->thread_work = 1;
69319 ls->thread_stop = 1;
69320 pthread_cond_signal(&ls->cond);
69321 stop_count++;
69322 }
69323 pthread_mutex_unlock(&ls->mutex);
69324 }
69325 }
69326
69327 if (do_free) {
69328 list_for_each_entry_safe(ls, safe, &lockspaces, list) {
69329
69330 pthread_mutex_lock(&ls->mutex);
69331 done = ls->thread_done;
69332 stop = ls->thread_stop;
69333 pthread_mutex_unlock(&ls->mutex);
69334
69335 /* This ls has locks and force is not set. */
69336 if (!stop)
69337 continue;
69338
69339 /*
69340 * Once thread_done is set, we know that the lockspace_thread
69341 * will not be using/touching the ls struct. Any other
69342 * thread touches the ls struct under lockspaces_mutex.
69343 */
69344 if (done) {
69345 if ((perrno = pthread_join(ls->thread, NULL)))
69346 log_error("pthread_join error %d", perrno);
69347
69348 list_del(&ls->list);
69349
69350 /* FIXME: will free_vg ever not be set? */
69351
69352 log_debug("free ls %s", ls->name);
69353
69354 if (ls->free_vg) {
69355 /* In future we may need to free ls->actions here */
69356 free_ls_resources(ls);
69357 free(ls);
69358 free_count++;
69359 }
69360 } else {
69361 need_free++;
69362 }
69363 }
69364 }
69365
69366 if (list_empty(&lockspaces)) {
69367 if (!gl_type_static) {
69368 gl_use_dlm = 0;
69369 gl_use_sanlock = 0;
69370 }
69371 }
69372 pthread_mutex_unlock(&lockspaces_mutex);
69373
69374 if (stop_count || free_count || need_stop || need_free) {
69375 log_debug("for_each_lockspace do_stop %d do_free %d "
69376 "stop_count %d free_count %d need_stop %d need_free %d",
69377 do_stop, do_free, stop_count, free_count, need_stop, need_free);
69378 }
69379
69380 return need_stop + need_free;
69381}
69382
69383/*
69384 * This is only called when the daemon is exiting so the sleep/retry
69385 * loop doesn't have any adverse impact.
69386 */
69387
69388static void for_each_lockspace_retry(int do_stop, int do_free, int do_force)
69389{
69390 int count;
69391
69392 while (1) {
69393 count = for_each_lockspace(do_stop, do_free, do_force);
69394 if (!count)
69395 break;
69396
69397 log_debug("for_each_lockspace_retry remaining %d", count);
69398 sleep(1);
69399 }
69400}
69401
69402static int work_init_vg(struct action *act)
69403{
69404 struct lockspace *ls;
69405 char ls_name[MAX_NAME+1];
69406 int rv = 0;
69407
69408 memset(ls_name, 0, sizeof(ls_name));
69409
69410 vg_ls_name(act->vg_name, ls_name);
69411
69412 /*
69413 * The max dlm ls name is 64 and the max sanlock ls name is 48. So,
69414 * after the "lvm_" prefix, only the first 60/44 characters of the VG
69415 * name are used for the lockspace name. This will cause a collision
69416 * in the lock manager if two different VG names have the first 60/44
69417 * chars in common. At the time of vgcreate (here), check if any other
69418 * VG's are known that would collide. If the collision is not detected
69419 * at vgcreate time, it will be detected at start time and add_lockspace
69420 * will fail for the second of the two matching ls names.
69421 */
69422 pthread_mutex_lock(&lockspaces_mutex);
69423 list_for_each_entry(ls, &lockspaces, list) {
69424 if ((ls->lm_type == LD_LM_SANLOCK) && !strncmp(ls->name, ls_name, 48)) {
69425 rv = -EEXIST;
69426 break;
69427 }
69428 if ((ls->lm_type == LD_LM_DLM) && !strcmp(ls->name, ls_name)) {
69429 rv = -EEXIST;
69430 break;
69431 }
69432 }
69433 pthread_mutex_unlock(&lockspaces_mutex);
69434
69435 if (rv == -EEXIST) {
69436 log_error("Existing lockspace name %s matches new %s VG names %s %s",
69437 ls->name, ls_name, ls->vg_name, act->vg_name);
69438 return rv;
69439 }
69440
69441 if (act->lm_type == LD_LM_SANLOCK)
69442 rv = lm_init_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
69443 else if (act->lm_type == LD_LM_DLM)
69444 rv = lm_init_vg_dlm(ls_name, act->vg_name, act->flags, act->vg_args);
69445 else
69446 rv = -EINVAL;
69447
69448 return rv;
69449}
69450
69451static int work_rename_vg(struct action *act)
69452{
69453 char ls_name[MAX_NAME+1];
69454 int rv = 0;
69455
69456 memset(ls_name, 0, sizeof(ls_name));
69457
69458 vg_ls_name(act->vg_name, ls_name);
69459
69460 if (act->lm_type == LD_LM_SANLOCK)
69461 rv = lm_rename_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
69462 else if (act->lm_type == LD_LM_DLM)
69463 return 0;
69464 else
69465 rv = -EINVAL;
69466
69467 return rv;
69468}
69469
69470static void work_test_gl(void)
69471{
69472 struct lockspace *ls;
69473 int is_enabled = 0;
69474
69475 pthread_mutex_lock(&lockspaces_mutex);
69476 list_for_each_entry(ls, &lockspaces, list) {
69477 if (ls->lm_type != LD_LM_SANLOCK)
69478 continue;
69479
69480 pthread_mutex_lock(&ls->mutex);
69481 if (ls->create_done && !ls->thread_stop) {
69482 is_enabled = lm_gl_is_enabled(ls);
69483 if (is_enabled) {
69484 log_debug("S %s worker found gl_is_enabled", ls->name);
69485 strncpy(gl_lsname_sanlock, ls->name, MAX_NAME);
69486 }
69487 }
69488 pthread_mutex_unlock(&ls->mutex);
69489
69490 if (is_enabled)
69491 break;
69492 }
69493
69494 if (!is_enabled)
69495 log_debug("worker found no gl_is_enabled");
69496 pthread_mutex_unlock(&lockspaces_mutex);
69497}
69498
69499static int work_init_lv(struct action *act)
69500{
69501 struct lockspace *ls;
69502 char ls_name[MAX_NAME+1];
69503 char vg_args[MAX_ARGS+1];
69504 char lv_args[MAX_ARGS+1];
69505 uint64_t free_offset = 0;
69506 int lm_type = 0;
69507 int rv = 0;
69508
69509 memset(ls_name, 0, sizeof(ls_name));
69510 memset(vg_args, 0, sizeof(vg_args));
69511 memset(lv_args, 0, sizeof(lv_args));
69512
69513 vg_ls_name(act->vg_name, ls_name);
69514
69515 pthread_mutex_lock(&lockspaces_mutex);
69516 ls = find_lockspace_name(ls_name);
69517 if (ls) {
69518 lm_type = ls->lm_type;
69519 memcpy(vg_args, ls->vg_args, MAX_ARGS);
69520 free_offset = ls->free_lock_offset;
69521 ls->free_lock_offset = 0;
69522 }
69523 pthread_mutex_unlock(&lockspaces_mutex);
69524
69525 if (!ls) {
69526 lm_type = act->lm_type;
69527 memcpy(vg_args, act->vg_args, MAX_ARGS);
69528 }
69529
69530 if (act->lm_type != lm_type) {
69531 log_error("init_lv ls_name %s wrong lm_type %d %d",
69532 ls_name, act->lm_type, lm_type);
69533 return -EINVAL;
69534 }
69535
69536 if (lm_type == LD_LM_SANLOCK) {
69537 rv = lm_init_lv_sanlock(ls_name, act->vg_name, act->lv_uuid,
69538 vg_args, lv_args, free_offset);
69539
69540 memcpy(act->lv_args, lv_args, MAX_ARGS);
69541 return rv;
69542
69543 } else if (act->lm_type == LD_LM_DLM) {
69544 return 0;
69545 } else {
69546 log_error("init_lv ls_name %s bad lm_type %d", ls_name, act->lm_type);
69547 return -EINVAL;
69548 }
69549}
69550
69551/*
69552 * When an action is queued for the worker_thread, it is processed right away.
69553 * After processing, some actions need to be retried again in a short while.
69554 * These actions are put on the delayed_list, and the worker_thread will
69555 * process these delayed actions again in SHORT_DELAY_PERIOD.
69556 */
69557
69558#define SHORT_DELAY_PERIOD 2
69559#define LONG_DELAY_PERIOD 60
69560
69561static void *worker_thread_main(void *arg_in)
69562{
69563 struct list_head delayed_list;
69564 struct timespec ts;
69565 struct action *act, *safe;
69566 uint64_t last_delayed_time = 0;
69567 int delay_sec = LONG_DELAY_PERIOD;
69568 int rv;
69569
69570 INIT_LIST_HEAD(&delayed_list);
69571
69572 while (1) {
69573 pthread_mutex_lock(&worker_mutex);
69574 if (clock_gettime(CLOCK_REALTIME, &ts)) {
69575 log_error("clock_gettime failed.");
69576 ts.tv_sec = ts.tv_nsec = 0;
69577 }
69578 ts.tv_sec += delay_sec;
69579 rv = 0;
69580 act = NULL;
69581
69582 while (list_empty(&worker_list) && !worker_stop && !worker_wake && !rv) {
69583 rv = pthread_cond_timedwait(&worker_cond, &worker_mutex, &ts);
69584 }
69585 worker_wake = 0;
69586
69587 if (worker_stop) {
69588 pthread_mutex_unlock(&worker_mutex);
69589 goto out;
69590 }
69591
69592 if (!list_empty(&worker_list)) {
69593 act = list_first_entry(&worker_list, struct action, list);
69594 list_del(&act->list);
69595 }
69596 pthread_mutex_unlock(&worker_mutex);
69597
69598 /*
69599 * Do new work actions before processing delayed work actions.
69600 */
69601
69602 if (!act)
69603 goto delayed_work;
69604
69605 if (act->op == LD_OP_RUNNING_LM) {
69606 int run_sanlock = lm_is_running_sanlock();
69607 int run_dlm = lm_is_running_dlm();
69608
69609 if (daemon_test) {
69610 run_sanlock = gl_use_sanlock;
69611 run_dlm = gl_use_dlm;
69612 }
69613
69614 if (run_sanlock && run_dlm)
69615 act->result = -EXFULL;
69616 else if (!run_sanlock && !run_dlm)
69617 act->result = -ENOLCK;
69618 else if (run_sanlock)
69619 act->result = LD_LM_SANLOCK;
69620 else if (run_dlm)
69621 act->result = LD_LM_DLM;
69622 add_client_result(act);
69623
69624 } else if ((act->op == LD_OP_LOCK) && (act->flags & LD_AF_SEARCH_LS)) {
69625 /*
69626 * worker_thread used as a helper to search existing
69627 * sanlock vgs for an enabled gl.
69628 */
69629 log_debug("work search for gl");
69630 work_test_gl();
69631
69632 /* try again to find a gl lockspace for this act */
69633 rv = add_lock_action(act);
69634 if (rv < 0) {
69635 act->result = rv;
69636 add_client_result(act);
69637 }
69638
69639 } else if ((act->op == LD_OP_INIT) && (act->rt == LD_RT_VG)) {
69640 log_debug("work init_vg %s", act->vg_name);
69641 act->result = work_init_vg(act);
69642 add_client_result(act);
69643
69644 } else if ((act->op == LD_OP_INIT) && (act->rt == LD_RT_LV)) {
69645 log_debug("work init_lv %s/%s uuid %s", act->vg_name, act->lv_name, act->lv_uuid);
69646 act->result = work_init_lv(act);
69647 add_client_result(act);
69648
69649 } else if ((act->op == LD_OP_RENAME_FINAL) && (act->rt == LD_RT_VG)) {
69650 log_debug("work rename_vg %s", act->vg_name);
69651 act->result = work_rename_vg(act);
69652 add_client_result(act);
69653
69654 } else if (act->op == LD_OP_START_WAIT) {
69655 act->result = count_lockspace_starting(act->client_id);
69656 if (!act->result)
69657 add_client_result(act);
69658 else
69659 list_add(&act->list, &delayed_list);
69660
69661 } else if (act->op == LD_OP_STOP_ALL) {
69662 act->result = for_each_lockspace(DO_STOP, DO_FREE, (act->flags & LD_AF_FORCE) ? DO_FORCE : NO_FORCE);
69663 if (!act->result || !(act->flags & LD_AF_WAIT))
69664 add_client_result(act);
69665 else
69666 list_add(&act->list, &delayed_list);
69667
69668 } else {
69669 log_error("work unknown op %d", act->op);
69670 act->result = -EINVAL;
69671 add_client_result(act);
69672 }
69673
69674 delayed_work:
69675 /*
69676 * We may want to track retry times per action so that
69677 * we can delay different actions by different amounts.
69678 */
69679
69680 if (monotime() - last_delayed_time < SHORT_DELAY_PERIOD) {
69681 delay_sec = 1;
69682 continue;
69683 }
69684 last_delayed_time = monotime();
69685
69686 list_for_each_entry_safe(act, safe, &delayed_list, list) {
69687 if (act->op == LD_OP_START_WAIT) {
69688 log_debug("work delayed start_wait for client %u", act->client_id);
69689 act->result = count_lockspace_starting(act->client_id);
69690 if (!act->result) {
69691 list_del(&act->list);
69692 add_client_result(act);
69693 }
69694
69695 } else if (act->op == LD_OP_STOP_ALL) {
69696 log_debug("work delayed stop_all");
69697 act->result = for_each_lockspace(DO_STOP, DO_FREE, (act->flags & LD_AF_FORCE) ? DO_FORCE : NO_FORCE);
69698 if (!act->result) {
69699 list_del(&act->list);
69700 act->result = 0;
69701 add_client_result(act);
69702 }
69703 }
69704 }
69705
69706 /*
69707 * This is not explicitly queued work, and not delayed work,
69708 * but lockspace thread cleanup that's needed when a
69709 * lockspace has been stopped/removed or failed to start.
69710 */
69711
69712 for_each_lockspace(NO_STOP, DO_FREE, NO_FORCE);
69713
69714 if (list_empty(&delayed_list))
69715 delay_sec = LONG_DELAY_PERIOD;
69716 else
69717 delay_sec = 1;
69718 }
69719out:
69720 list_for_each_entry_safe(act, safe, &delayed_list, list) {
69721 list_del(&act->list);
69722 free_action(act);
69723 }
69724
69725 pthread_mutex_lock(&worker_mutex);
69726 list_for_each_entry_safe(act, safe, &worker_list, list) {
69727 list_del(&act->list);
69728 free_action(act);
69729 }
69730 pthread_mutex_unlock(&worker_mutex);
69731 return NULL;
69732}
69733
69734static int setup_worker_thread(void)
69735{
69736 int rv;
69737
69738 INIT_LIST_HEAD(&worker_list);
69739
69740 pthread_mutex_init(&worker_mutex, NULL);
69741 pthread_cond_init(&worker_cond, NULL);
69742
69743 rv = pthread_create(&worker_thread, NULL, worker_thread_main, NULL);
69744 if (rv)
69745 return -1;
69746 return 0;
69747}
69748
69749static void close_worker_thread(void)
69750{
69751 pthread_mutex_lock(&worker_mutex);
69752 worker_stop = 1;
69753 pthread_cond_signal(&worker_cond);
69754 pthread_mutex_unlock(&worker_mutex);
69755 pthread_join(worker_thread, NULL);
69756}
69757
69758/* client_mutex is locked */
69759static struct client *find_client_work(void)
69760{
69761 struct client *cl;
69762
69763 list_for_each_entry(cl, &client_list, list) {
69764 if (cl->recv || cl->dead)
69765 return cl;
69766 }
69767 return NULL;
69768}
69769
69770/* client_mutex is locked */
69771static struct client *find_client_id(uint32_t id)
69772{
69773 struct client *cl;
69774
69775 list_for_each_entry(cl, &client_list, list) {
69776 if (cl->id == id)
69777 return cl;
69778 }
69779 return NULL;
69780}
69781
69782/* client_mutex is locked */
69783static struct client *find_client_pi(int pi)
69784{
69785 struct client *cl;
69786
69787 list_for_each_entry(cl, &client_list, list) {
69788 if (cl->pi == pi)
69789 return cl;
69790 }
69791 return NULL;
69792}
69793
69794/*
69795 * wake up poll() because we have added an fd
69796 * back into pollfd and poll() needs to be restarted
69797 * to recognize it.
69798 */
69799static void restart_poll(void)
69800{
69801 int rv;
69802 rv = write(restart_fds[1], "w", 1);
69803 if (!rv || rv < 0)
69804 log_debug("restart_poll write %d", errno);
69805}
69806
69807/* poll will take requests from client again, cl->mutex must be held */
69808static void client_resume(struct client *cl)
69809{
69810 if (cl->dead)
69811 return;
69812
69813 if (!cl->poll_ignore || cl->fd == -1 || cl->pi == -1) {
69814 /* shouldn't happen */
69815 log_error("client_resume %u bad state ig %d fd %d pi %d",
69816 cl->id, cl->poll_ignore, cl->fd, cl->pi);
69817 return;
69818 }
69819
69820 pthread_mutex_lock(&pollfd_mutex);
69821 if (pollfd[cl->pi].fd != POLL_FD_IGNORE) {
69822 log_error("client_resume %u pi %d fd %d not IGNORE",
69823 cl->id, cl->pi, cl->fd);
69824 }
69825 pollfd[cl->pi].fd = cl->fd;
69826 pollfd[cl->pi].events = POLLIN;
69827 pthread_mutex_unlock(&pollfd_mutex);
69828
69829 restart_poll();
69830}
69831
69832/* called from client_thread, cl->mutex is held */
69833static int client_send_result(struct client *cl, struct action *act)
69834{
69835 response res;
69836 char result_flags[128];
69837 int dump_len = 0;
69838 int dump_fd = -1;
69839 int rv = 0;
69840
69841 if (cl->dead) {
69842 log_debug("send cl %u skip dead", cl->id);
69843 return -1;
69844 }
69845
69846 memset(result_flags, 0, sizeof(result_flags));
69847
69848 buffer_init(&res.buffer);
69849
69850 /*
69851 * EUNATCH is returned when the global lock existed,
69852 * but had been disabled when we tried to lock it,
69853 * so we removed it, and no longer have a gl to lock.
69854 */
69855
69856 if (act->result == -EUNATCH)
69857 act->result = -ENOLS;
69858
69859 /*
69860 * init_vg with dlm|sanlock returns vg_args
69861 * init_lv with sanlock returns lv_args
69862 */
69863
69864 if (act->result == -ENOLS) {
69865 /*
69866 * The lockspace could not be found, in which case
69867 * the caller may want to know if any lockspaces exist
69868 * or if lockspaces exist, but not one with the global lock.
69869 * Given this detail, it may be able to procede without
69870 * the lock.
69871 */
69872 pthread_mutex_lock(&lockspaces_mutex);
69873 if (list_empty(&lockspaces))
69874 strcat(result_flags, "NO_LOCKSPACES,");
69875 pthread_mutex_unlock(&lockspaces_mutex);
69876
69877 if (gl_use_sanlock) {
69878 if (!gl_lsname_sanlock[0])
69879 strcat(result_flags, "NO_GL_LS,");
69880 } else if (gl_use_dlm) {
69881 if (!gl_lsname_dlm[0])
69882 strcat(result_flags, "NO_GL_LS,");
69883 } else {
69884 strcat(result_flags, "NO_GL_LS,");
69885 }
69886 }
69887
69888 if (act->flags & LD_AF_DUP_GL_LS)
69889 strcat(result_flags, "DUP_GL_LS,");
69890
69891 if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
69892 strcat(result_flags, "WARN_GL_REMOVED,");
69893
69894 if (act->op == LD_OP_INIT) {
69895 /*
69896 * init is a special case where lock args need
69897 * to be passed back to the client.
69898 */
69899 const char *vg_args = "none";
69900 const char *lv_args = "none";
69901
69902 if (act->vg_args[0])
69903 vg_args = act->vg_args;
69904
69905 if (act->lv_args[0])
69906 lv_args = act->lv_args;
69907
69908 log_debug("send %s[%d] cl %u %s %s rv %d vg_args %s lv_args %s",
69909 cl->name[0] ? cl->name : "client", cl->pid, cl->id,
69910 op_str(act->op), rt_str(act->rt),
69911 act->result, vg_args ? vg_args : "", lv_args ? lv_args : "");
69912
69913 res = daemon_reply_simple("OK",
69914 "op = " FMTd64, (int64_t)act->op,
69915 "op_result = " FMTd64, (int64_t) act->result,
69916 "lm_result = " FMTd64, (int64_t) act->lm_rv,
69917 "vg_lock_args = %s", vg_args,
69918 "lv_lock_args = %s", lv_args,
69919 "result_flags = %s", result_flags[0] ? result_flags : "none",
69920 NULL);
69921
69922 } else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
69923 /*
69924 * lvmlockctl creates the unix socket then asks us to write to it.
69925 * FIXME: move processing this to a new dedicated query thread to
69926 * avoid having a large data dump interfere with normal operation
69927 * of the client thread?
69928 */
69929
69930 dump_fd = setup_dump_socket();
69931 if (dump_fd < 0)
69932 act->result = dump_fd;
69933 else if (act->op == LD_OP_DUMP_LOG)
69934 act->result = dump_log(&dump_len);
69935 else if (act->op == LD_OP_DUMP_INFO)
69936 act->result = dump_info(&dump_len);
69937 else
69938 act->result = -EINVAL;
69939
69940 log_debug("send %s[%d] cl %u dump result %d dump_len %d",
69941 cl->name[0] ? cl->name : "client", cl->pid, cl->id,
69942 act->result, dump_len);
69943
69944 res = daemon_reply_simple("OK",
69945 "result = " FMTd64, (int64_t) act->result,
69946 "dump_len = " FMTd64, (int64_t) dump_len,
69947 NULL);
69948 } else {
69949 /*
69950 * A normal reply.
69951 */
69952
69953 log_debug("send %s[%d] cl %u %s %s rv %d %s %s",
69954 cl->name[0] ? cl->name : "client", cl->pid, cl->id,
69955 op_str(act->op), rt_str(act->rt),
69956 act->result, (act->result == -ENOLS) ? "ENOLS" : "", result_flags);
69957
69958 res = daemon_reply_simple("OK",
69959 "op = " FMTd64, (int64_t) act->op,
69960 "lock_type = %s", lm_str(act->lm_type),
69961 "op_result = " FMTd64, (int64_t) act->result,
69962 "lm_result = " FMTd64, (int64_t) act->lm_rv,
69963 "result_flags = %s", result_flags[0] ? result_flags : "none",
69964 NULL);
69965 }
69966
69967 if (!buffer_write(cl->fd, &res.buffer)) {
69968 rv = -errno;
69969 if (rv >= 0)
69970 rv = -1;
69971 log_debug("send cl %u fd %d error %d", cl->id, cl->fd, rv);
69972 }
69973
69974 buffer_destroy(&res.buffer);
69975
69976 client_resume(cl);
69977
69978 if (dump_fd >= 0) {
69979 /* To avoid deadlock, send data here after the reply. */
69980 send_dump_buf(dump_fd, dump_len);
69981 close(dump_fd);
69982 }
69983
69984 return rv;
69985}
69986
69987/* called from client_thread */
69988static void client_purge(struct client *cl)
69989{
69990 struct lockspace *ls;
69991 struct action *act;
69992
69993 /*
69994 * If the client made no lock requests, there can be
69995 * no locks to release for it.
69996 */
69997 if (!cl->lock_ops)
69998 return;
69999
70000 pthread_mutex_lock(&lockspaces_mutex);
70001 list_for_each_entry(ls, &lockspaces, list) {
70002 if (!(act = alloc_action()))
70003 continue;
70004
70005 act->op = LD_OP_CLOSE;
70006 act->client_id = cl->id;
70007
70008 pthread_mutex_lock(&ls->mutex);
70009 if (!ls->thread_stop) {
70010 list_add_tail(&act->list, &ls->actions);
70011 ls->thread_work = 1;
70012 pthread_cond_signal(&ls->cond);
70013 } else {
70014 free_action(act);
70015 }
70016 pthread_mutex_unlock(&ls->mutex);
70017 }
70018 pthread_mutex_unlock(&lockspaces_mutex);
70019}
70020
70021static int add_lock_action(struct action *act)
70022{
70023 struct lockspace *ls = NULL;
70024 char ls_name[MAX_NAME+1];
70025
70026 memset(ls_name, 0, sizeof(ls_name));
70027
70028 /*
70029 * Determine which lockspace this action is for, and set ls_name.
70030 */
70031
70032 if (act->rt == LD_RT_GL) {
70033 /* Global lock is requested */
70034 if (gl_use_sanlock && (act->op == LD_OP_ENABLE || act->op == LD_OP_DISABLE)) {
70035 vg_ls_name(act->vg_name, ls_name);
70036 } else {
70037 if (!gl_use_dlm && !gl_use_sanlock) {
70038 if (lm_is_running_dlm())
70039 gl_use_dlm = 1;
70040 else if (lm_is_running_sanlock())
70041 gl_use_sanlock = 1;
70042 }
70043 gl_ls_name(ls_name);
70044 }
70045 } else {
70046 /* VG lock is requested */
70047 vg_ls_name(act->vg_name, ls_name);
70048 }
70049
70050 retry:
70051 pthread_mutex_lock(&lockspaces_mutex);
70052 if (ls_name[0])
70053 ls = find_lockspace_name(ls_name);
70054 pthread_mutex_unlock(&lockspaces_mutex);
70055 if (!ls) {
70056 if (act->op == LD_OP_UPDATE && act->rt == LD_RT_VG) {
70057 log_debug("lockspace \"%s\" not found ignored for vg update", ls_name);
70058 return -ENOLS;
70059
70060 } else if (act->flags & LD_AF_SEARCH_LS) {
70061 /*
70062 * Fail if we've already tried searching for the lockspace.
70063 */
70064 log_debug("lockspace \"%s\" not found after search", ls_name);
70065 return -ENOLS;
70066
70067 } else if (act->op == LD_OP_LOCK && act->rt == LD_RT_GL && gl_use_sanlock) {
70068 /*
70069 * The sanlock global lock may have been enabled in an existing VG,
70070 * so search existing VGs for an enabled global lock.
70071 */
70072 log_debug("lockspace \"%s\" not found for sanlock gl, searching...", ls_name);
70073 act->flags |= LD_AF_SEARCH_LS;
70074 add_work_action(act);
70075 return 0;
70076
70077 } else if (act->op == LD_OP_LOCK && act->rt == LD_RT_GL && act->mode != LD_LK_UN && gl_use_dlm) {
70078 /*
70079 * Automatically start the dlm global lockspace when
70080 * a command tries to acquire the global lock.
70081 */
70082 log_debug("lockspace \"%s\" not found for dlm gl, adding...", ls_name);
70083 act->flags |= LD_AF_SEARCH_LS;
70084 act->flags |= LD_AF_WAIT_STARTING;
70085 add_dlm_global_lockspace(NULL);
70086 goto retry;
70087
70088 } else if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
70089 log_debug("lockspace \"%s\" not found for unlock ignored", ls_name);
70090 return -ENOLS;
70091
70092 } else {
70093 log_debug("lockspace \"%s\" not found", ls_name);
70094 return -ENOLS;
70095 }
70096 }
70097
70098 if (act->lm_type == LD_LM_NONE) {
70099 /* return to the command the type we are using */
70100 act->lm_type = ls->lm_type;
70101 } else if (act->lm_type != ls->lm_type) {
70102 /* should not happen */
70103 log_error("S %s add_lock_action bad lm_type %d ls %d",
70104 ls_name, act->lm_type, ls->lm_type);
70105 pthread_mutex_unlock(&lockspaces_mutex);
70106 return -EINVAL;
70107 }
70108
70109 pthread_mutex_lock(&ls->mutex);
70110 if (ls->thread_stop) {
70111 pthread_mutex_unlock(&ls->mutex);
70112 pthread_mutex_unlock(&lockspaces_mutex);
70113 log_error("lockspace is stopping %s", ls_name);
70114 return -ESTALE;
70115 }
70116
70117 if (!ls->create_fail && !ls->create_done && !(act->flags & LD_AF_WAIT_STARTING)) {
70118 pthread_mutex_unlock(&ls->mutex);
70119 pthread_mutex_unlock(&lockspaces_mutex);
70120 log_debug("lockspace is starting %s", ls_name);
70121 return -ESTARTING;
70122 }
70123
70124 list_add_tail(&act->list, &ls->actions);
70125 ls->thread_work = 1;
70126 pthread_cond_signal(&ls->cond);
70127 pthread_mutex_unlock(&ls->mutex);
70128 pthread_mutex_unlock(&lockspaces_mutex);
70129
70130 /* lockspace_thread_main / res_process take it from here */
70131
70132 return 0;
70133}
70134
70135static int str_to_op_rt(const char *req_name, int *op, int *rt)
70136{
70137 if (!req_name)
70138 goto out;
70139
70140 if (!strcmp(req_name, "hello")) {
70141 *op = LD_OP_HELLO;
70142 *rt = 0;
70143 return 0;
70144 }
70145 if (!strcmp(req_name, "quit")) {
70146 *op = LD_OP_QUIT;
70147 *rt = 0;
70148 return 0;
70149 }
70150 if (!strcmp(req_name, "info")) {
70151 *op = LD_OP_DUMP_INFO;
70152 *rt = 0;
70153 return 0;
70154 }
70155 if (!strcmp(req_name, "dump")) {
70156 *op = LD_OP_DUMP_LOG;
70157 *rt = 0;
70158 return 0;
70159 }
70160 if (!strcmp(req_name, "init_vg")) {
70161 *op = LD_OP_INIT;
70162 *rt = LD_RT_VG;
70163 return 0;
70164 }
70165 if (!strcmp(req_name, "init_lv")) {
70166 *op = LD_OP_INIT;
70167 *rt = LD_RT_LV;
70168 return 0;
70169 }
70170 if (!strcmp(req_name, "free_vg")) {
70171 *op = LD_OP_FREE;
70172 *rt = LD_RT_VG;
70173 return 0;
70174 }
70175 if (!strcmp(req_name, "busy_vg")) {
70176 *op = LD_OP_BUSY;
70177 *rt = LD_RT_VG;
70178 return 0;
70179 }
70180 if (!strcmp(req_name, "free_lv")) {
70181 *op = LD_OP_FREE;
70182 *rt = LD_RT_LV;
70183 return 0;
70184 }
70185 if (!strcmp(req_name, "start_vg")) {
70186 *op = LD_OP_START;
70187 *rt = LD_RT_VG;
70188 return 0;
70189 }
70190 if (!strcmp(req_name, "stop_vg")) {
70191 *op = LD_OP_STOP;
70192 *rt = LD_RT_VG;
70193 return 0;
70194 }
70195 if (!strcmp(req_name, "start_wait")) {
70196 *op = LD_OP_START_WAIT;
70197 *rt = 0;
70198 return 0;
70199 }
70200 if (!strcmp(req_name, "stop_all")) {
70201 *op = LD_OP_STOP_ALL;
70202 *rt = 0;
70203 return 0;
70204 }
70205 if (!strcmp(req_name, "lock_gl")) {
70206 *op = LD_OP_LOCK;
70207 *rt = LD_RT_GL;
70208 return 0;
70209 }
70210 if (!strcmp(req_name, "lock_vg")) {
70211 *op = LD_OP_LOCK;
70212 *rt = LD_RT_VG;
70213 return 0;
70214 }
70215 if (!strcmp(req_name, "lock_lv")) {
70216 *op = LD_OP_LOCK;
70217 *rt = LD_RT_LV;
70218 return 0;
70219 }
70220 if (!strcmp(req_name, "vg_update")) {
70221 *op = LD_OP_UPDATE;
70222 *rt = LD_RT_VG;
70223 return 0;
70224 }
70225 if (!strcmp(req_name, "enable_gl")) {
70226 *op = LD_OP_ENABLE;
70227 *rt = LD_RT_GL;
70228 return 0;
70229 }
70230 if (!strcmp(req_name, "disable_gl")) {
70231 *op = LD_OP_DISABLE;
70232 *rt = LD_RT_GL;
70233 return 0;
70234 }
70235 if (!strcmp(req_name, "rename_vg_before")) {
70236 *op = LD_OP_RENAME_BEFORE;
70237 *rt = LD_RT_VG;
70238 return 0;
70239 }
70240 if (!strcmp(req_name, "rename_vg_final")) {
70241 *op = LD_OP_RENAME_FINAL;
70242 *rt = LD_RT_VG;
70243 return 0;
70244 }
70245 if (!strcmp(req_name, "running_lm")) {
70246 *op = LD_OP_RUNNING_LM;
70247 *rt = 0;
70248 return 0;
70249 }
70250 if (!strcmp(req_name, "find_free_lock")) {
70251 *op = LD_OP_FIND_FREE_LOCK;
70252 *rt = LD_RT_VG;
70253 return 0;
70254 }
70255 if (!strcmp(req_name, "kill_vg")) {
70256 *op = LD_OP_KILL_VG;
70257 *rt = LD_RT_VG;
70258 return 0;
70259 }
70260 if (!strcmp(req_name, "drop_vg")) {
70261 *op = LD_OP_DROP_VG;
70262 *rt = LD_RT_VG;
70263 return 0;
70264 }
70265out:
70266 return -1;
70267}
70268
70269static int str_to_mode(const char *str)
70270{
70271 if (!str)
70272 goto out;
70273 if (!strcmp(str, "un"))
70274 return LD_LK_UN;
70275 if (!strcmp(str, "nl"))
70276 return LD_LK_NL;
70277 if (!strcmp(str, "sh"))
70278 return LD_LK_SH;
70279 if (!strcmp(str, "ex"))
70280 return LD_LK_EX;
70281out:
70282 return LD_LK_IV;
70283}
70284
70285static int str_to_lm(const char *str)
70286{
70287 if (!str || !strcmp(str, "none"))
70288 return LD_LM_NONE;
70289 if (!strcmp(str, "sanlock"))
70290 return LD_LM_SANLOCK;
70291 if (!strcmp(str, "dlm"))
70292 return LD_LM_DLM;
70293 return -2;
70294}
70295
70296static uint32_t str_to_opts(const char *str)
70297{
70298 uint32_t flags = 0;
70299
70300 if (!str)
70301 goto out;
70302 if (strstr(str, "persistent"))
70303 flags |= LD_AF_PERSISTENT;
70304 if (strstr(str, "unlock_cancel"))
70305 flags |= LD_AF_UNLOCK_CANCEL;
70306 if (strstr(str, "next_version"))
70307 flags |= LD_AF_NEXT_VERSION;
70308 if (strstr(str, "wait"))
70309 flags |= LD_AF_WAIT;
70310 if (strstr(str, "force"))
70311 flags |= LD_AF_FORCE;
70312 if (strstr(str, "ex_disable"))
70313 flags |= LD_AF_EX_DISABLE;
70314 if (strstr(str, "enable"))
70315 flags |= LD_AF_ENABLE;
70316 if (strstr(str, "disable"))
70317 flags |= LD_AF_DISABLE;
70318out:
70319 return flags;
70320}
70321
70322/*
70323 * dump info
70324 * client_list: each client struct
70325 * lockspaces: each lockspace struct
70326 * lockspace actions: each action struct
70327 * lockspace resources: each resource struct
70328 * lockspace resource actions: each action struct
70329 * lockspace resource locks: each lock struct
70330 */
70331
70332static int setup_dump_socket(void)
70333{
70334 int s;
70335
70336 s = socket(AF_LOCAL, SOCK_DGRAM, 0);
70337 if (s < 0)
70338 return s;
70339
70340 memset(&dump_addr, 0, sizeof(dump_addr));
70341 dump_addr.sun_family = AF_LOCAL;
70342 strcpy(&dump_addr.sun_path[1], DUMP_SOCKET_NAME);
70343 dump_addrlen = sizeof(sa_family_t) + strlen(dump_addr.sun_path+1) + 1;
70344
70345 return s;
70346}
70347
70348#define MAX_SEND_LEN 65536
70349#define RESEND_DELAY_US 1000
70350#define RESEND_DELAY_US_MAX 500000
70351
70352static void send_dump_buf(int fd, int dump_len)
70353{
70354 int pos = 0;
70355 int ret;
70356 int send_len;
70357 int delay = 0;
70358
70359 if (!dump_len)
70360 return;
70361repeat:
70362 if (dump_len - pos < MAX_SEND_LEN)
70363 send_len = dump_len - pos;
70364 else
70365 send_len = MAX_SEND_LEN;
70366
70367 ret = sendto(fd, dump_buf + pos, send_len, MSG_NOSIGNAL | MSG_DONTWAIT,
70368 (struct sockaddr *)&dump_addr, dump_addrlen);
70369 if (ret < 0) {
70370 if ((errno == EAGAIN || errno == EINTR) && (delay < RESEND_DELAY_US_MAX)) {
70371 usleep(RESEND_DELAY_US);
70372 delay += RESEND_DELAY_US;
70373 goto repeat;
70374 }
70375 log_error("send_dump_buf delay %d errno %d", delay, errno);
70376 return;
70377 }
70378
70379 pos += ret;
70380
70381 if (pos < dump_len)
70382 goto repeat;
70383
70384 log_debug("send_dump_buf delay %d total %d", delay, pos);
70385}
70386
70387static int print_structs(const char *prefix, int pos, int len)
70388{
70389 return snprintf(dump_buf + pos, len - pos,
70390 "info=%s "
70391 "unused_action_count=%d "
70392 "unused_client_count=%d "
70393 "unused_resource_count=%d "
70394 "unused_lock_count=%d\n",
70395 prefix,
70396 unused_action_count,
70397 unused_client_count,
70398 unused_resource_count,
70399 unused_lock_count);
70400}
70401
70402static int print_client(struct client *cl, const char *prefix, int pos, int len)
70403{
70404 return snprintf(dump_buf + pos, len - pos,
70405 "info=%s "
70406 "pid=%d "
70407 "fd=%d "
70408 "pi=%d "
70409 "id=%u "
70410 "name=%s\n",
70411 prefix,
70412 cl->pid,
70413 cl->fd,
70414 cl->pi,
70415 cl->id,
70416 cl->name[0] ? cl->name : ".");
70417}
70418
70419static int print_lockspace(struct lockspace *ls, const char *prefix, int pos, int len)
70420{
70421 return snprintf(dump_buf + pos, len - pos,
70422 "info=%s "
70423 "ls_name=%s "
70424 "vg_name=%s "
70425 "vg_uuid=%s "
70426 "vg_sysid=%s "
70427 "vg_args=%s "
70428 "lm_type=%s "
70429 "host_id=%llu "
70430 "create_fail=%d "
70431 "create_done=%d "
70432 "thread_work=%d "
70433 "thread_stop=%d "
70434 "thread_done=%d "
70435 "kill_vg=%d "
70436 "drop_vg=%d "
70437 "sanlock_gl_enabled=%d\n",
70438 prefix,
70439 ls->name,
70440 ls->vg_name,
70441 ls->vg_uuid,
70442 ls->vg_sysid[0] ? ls->vg_sysid : ".",
70443 ls->vg_args,
70444 lm_str(ls->lm_type),
70445 (unsigned long long)ls->host_id,
70446 ls->create_fail ? 1 : 0,
70447 ls->create_done ? 1 : 0,
70448 ls->thread_work ? 1 : 0,
70449 ls->thread_stop ? 1 : 0,
70450 ls->thread_done ? 1 : 0,
70451 ls->kill_vg,
70452 ls->drop_vg,
70453 ls->sanlock_gl_enabled ? 1 : 0);
70454}
70455
70456static int print_action(struct action *act, const char *prefix, int pos, int len)
70457{
70458 return snprintf(dump_buf + pos, len - pos,
70459 "info=%s "
70460 "client_id=%u "
70461 "flags=0x%x "
70462 "version=%u "
70463 "op=%s "
70464 "rt=%s "
70465 "mode=%s "
70466 "lm_type=%s "
70467 "result=%d "
70468 "lm_rv=%d\n",
70469 prefix,
70470 act->client_id,
70471 act->flags,
70472 act->version,
70473 op_str(act->op),
70474 rt_str(act->rt),
70475 mode_str(act->mode),
70476 lm_str(act->lm_type),
70477 act->result,
70478 act->lm_rv);
70479}
70480
70481static int print_resource(struct resource *r, const char *prefix, int pos, int len)
70482{
70483 return snprintf(dump_buf + pos, len - pos,
70484 "info=%s "
70485 "name=%s "
70486 "type=%s "
70487 "mode=%s "
70488 "sh_count=%d "
70489 "version=%u\n",
70490 prefix,
70491 r->name,
70492 rt_str(r->type),
70493 mode_str(r->mode),
70494 r->sh_count,
70495 r->version);
70496}
70497
70498static int print_lock(struct lock *lk, const char *prefix, int pos, int len)
70499{
70500 return snprintf(dump_buf + pos, len - pos,
70501 "info=%s "
70502 "mode=%s "
70503 "version=%u "
70504 "flags=0x%x "
70505 "client_id=%u\n",
70506 prefix,
70507 mode_str(lk->mode),
70508 lk->version,
70509 lk->flags,
70510 lk->client_id);
70511}
70512
70513static int dump_info(int *dump_len)
70514{
70515 struct client *cl;
70516 struct lockspace *ls;
70517 struct resource *r;
70518 struct lock *lk;
70519 struct action *act;
70520 int len, pos, ret;
70521 int rv = 0;
70522
70523 memset(dump_buf, 0, sizeof(dump_buf));
70524 len = sizeof(dump_buf);
70525 pos = 0;
70526
70527 /*
70528 * memory
70529 */
70530
70531 pthread_mutex_lock(&unused_struct_mutex);
70532 ret = print_structs("structs", pos, len);
70533 if (ret >= len - pos) {
70534 pthread_mutex_unlock(&unused_struct_mutex);
70535 return -ENOSPC;
70536 }
70537 pos += ret;
70538 pthread_mutex_unlock(&unused_struct_mutex);
70539
70540 /*
70541 * clients
70542 */
70543
70544 pthread_mutex_lock(&client_mutex);
70545 list_for_each_entry(cl, &client_list, list) {
70546 ret = print_client(cl, "client", pos, len);
70547 if (ret >= len - pos) {
70548 rv = -ENOSPC;
70549 break;
70550 }
70551 pos += ret;
70552 }
70553 pthread_mutex_unlock(&client_mutex);
70554
70555 if (rv < 0)
70556 return rv;
70557
70558 /*
70559 * lockspaces with their action/resource/lock info
70560 */
70561
70562 pthread_mutex_lock(&lockspaces_mutex);
70563 list_for_each_entry(ls, &lockspaces, list) {
70564
70565 ret = print_lockspace(ls, "ls", pos, len);
70566 if (ret >= len - pos) {
70567 rv = -ENOSPC;
70568 goto out;
70569 }
70570 pos += ret;
70571
70572 list_for_each_entry(act, &ls->actions, list) {
70573 ret = print_action(act, "ls_action", pos, len);
70574 if (ret >= len - pos) {
70575 rv = -ENOSPC;
70576 goto out;
70577 }
70578 pos += ret;
70579 }
70580
70581 list_for_each_entry(r, &ls->resources, list) {
70582 ret = print_resource(r, "r", pos, len);
70583 if (ret >= len - pos) {
70584 rv = -ENOSPC;
70585 goto out;
70586 }
70587 pos += ret;
70588
70589 list_for_each_entry(lk, &r->locks, list) {
70590 ret = print_lock(lk, "lk", pos, len);
70591 if (ret >= len - pos) {
70592 rv = -ENOSPC;
70593 goto out;
70594 }
70595 pos += ret;
70596 }
70597
70598 list_for_each_entry(act, &r->actions, list) {
70599 ret = print_action(act, "r_action", pos, len);
70600 if (ret >= len - pos) {
70601 rv = -ENOSPC;
70602 goto out;
70603 }
70604 pos += ret;
70605 }
70606 }
70607 }
70608out:
70609 pthread_mutex_unlock(&lockspaces_mutex);
70610
70611 *dump_len = pos;
70612
70613 return rv;
70614}
70615
70616/* called from client_thread, cl->mutex is held */
70617static void client_recv_action(struct client *cl)
70618{
70619 request req;
70620 response res;
70621 struct action *act;
70622 const char *cl_name;
70623 const char *vg_name;
70624 const char *vg_uuid;
70625 const char *vg_sysid;
70626 const char *str;
70627 int64_t val;
70628 uint32_t opts = 0;
70629 int result = 0;
70630 int cl_pid;
70631 int op, rt, lm, mode;
70632 int rv;
70633
70634 buffer_init(&req.buffer);
70635
70636 rv = buffer_read(cl->fd, &req.buffer);
70637 if (!rv) {
70638 if (errno == ECONNRESET) {
70639 log_debug("client recv %u ECONNRESET", cl->id);
70640 cl->dead = 1;
70641 } else {
70642 log_error("client recv %u buffer_read error %d", cl->id, errno);
70643 }
70644 buffer_destroy(&req.buffer);
70645 client_resume(cl);
70646 return;
70647 }
70648
70649 req.cft = config_tree_from_string_without_dup_node_check(req.buffer.mem);
70650 if (!req.cft) {
70651 log_error("client recv %u config_from_string error", cl->id);
70652 buffer_destroy(&req.buffer);
70653 client_resume(cl);
70654 return;
70655 }
70656
70657 str = daemon_request_str(req, "request", NULL);
70658 rv = str_to_op_rt(str, &op, &rt);
70659 if (rv < 0) {
70660 log_error("client recv %u bad request name \"%s\"", cl->id, str ? str : "");
70661 dm_config_destroy(req.cft);
70662 buffer_destroy(&req.buffer);
70663 client_resume(cl);
70664 return;
70665 }
70666
70667 if (op == LD_OP_HELLO || op == LD_OP_QUIT) {
70668
70669 /*
70670 * FIXME: add the client command name to the hello messages
70671 * so it can be saved in cl->name here.
70672 */
70673
70674 result = 0;
70675
70676 if (op == LD_OP_QUIT) {
70677 log_debug("op quit");
70678 pthread_mutex_lock(&lockspaces_mutex);
70679 if (list_empty(&lockspaces))
70680 daemon_quit = 1;
70681 else
70682 result = -EBUSY;
70683 pthread_mutex_unlock(&lockspaces_mutex);
70684 }
70685
70686 buffer_init(&res.buffer);
70687
70688 res = daemon_reply_simple("OK",
70689 "result = " FMTd64, (int64_t) result,
70690 "protocol = %s", lvmlockd_protocol,
70691 "version = " FMTd64, (int64_t) lvmlockd_protocol_version,
70692 NULL);
70693 buffer_write(cl->fd, &res.buffer);
70694 buffer_destroy(&res.buffer);
70695 dm_config_destroy(req.cft);
70696 buffer_destroy(&req.buffer);
70697 client_resume(cl);
70698 return;
70699 }
70700
70701 cl_name = daemon_request_str(req, "cmd", NULL);
70702 cl_pid = daemon_request_int(req, "pid", 0);
70703 vg_name = daemon_request_str(req, "vg_name", NULL);
70704 vg_uuid = daemon_request_str(req, "vg_uuid", NULL);
70705 vg_sysid = daemon_request_str(req, "vg_sysid", NULL);
70706 str = daemon_request_str(req, "mode", NULL);
70707 mode = str_to_mode(str);
70708 str = daemon_request_str(req, "opts", NULL);
70709 opts = str_to_opts(str);
70710 str = daemon_request_str(req, "vg_lock_type", NULL);
70711 lm = str_to_lm(str);
70712
70713 if (cl_pid && cl_pid != cl->pid)
70714 log_error("client recv bad message pid %d client %d", cl_pid, cl->pid);
70715
70716 /* FIXME: do this in hello message instead */
70717 if (!cl->name[0] && cl_name)
70718 strncpy(cl->name, cl_name, MAX_NAME);
70719
70720 if (!gl_use_dlm && !gl_use_sanlock && (lm > 0)) {
70721 if (lm == LD_LM_DLM && lm_support_dlm())
70722 gl_use_dlm = 1;
70723 else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
70724 gl_use_sanlock = 1;
70725
70726 log_debug("set gl_use_%s", lm_str(lm));
70727 }
70728
70729 if (!(act = alloc_action())) {
70730 log_error("No memory for action");
70731 dm_config_destroy(req.cft);
70732 buffer_destroy(&req.buffer);
70733 client_resume(cl);
70734 return;
70735 }
70736
70737 act->client_id = cl->id;
70738 act->op = op;
70739 act->rt = rt;
70740 act->mode = mode;
70741 act->flags = opts;
70742 act->lm_type = lm;
70743
70744 if (vg_name && strcmp(vg_name, "none"))
70745 strncpy(act->vg_name, vg_name, MAX_NAME);
70746
70747 if (vg_uuid && strcmp(vg_uuid, "none"))
70748 strncpy(act->vg_uuid, vg_uuid, 64);
70749
70750 if (vg_sysid && strcmp(vg_sysid, "none"))
70751 strncpy(act->vg_sysid, vg_sysid, MAX_NAME);
70752
70753 str = daemon_request_str(req, "lv_name", NULL);
70754 if (str && strcmp(str, "none"))
70755 strncpy(act->lv_name, str, MAX_NAME);
70756
70757 str = daemon_request_str(req, "lv_uuid", NULL);
70758 if (str && strcmp(str, "none"))
70759 strncpy(act->lv_uuid, str, MAX_NAME);
70760
70761 val = daemon_request_int(req, "version", 0);
70762 if (val)
70763 act->version = (uint32_t)val;
70764
70765 str = daemon_request_str(req, "vg_lock_args", NULL);
70766 if (str && strcmp(str, "none"))
70767 strncpy(act->vg_args, str, MAX_ARGS);
70768
70769 str = daemon_request_str(req, "lv_lock_args", NULL);
70770 if (str && strcmp(str, "none"))
70771 strncpy(act->lv_args, str, MAX_ARGS);
70772
70773 /* start_vg will include lvmlocal.conf local/host_id here */
70774 val = daemon_request_int(req, "host_id", 0);
70775 if (val)
70776 act->host_id = val;
70777
70778 act->max_retries = daemon_request_int(req, "max_retries", DEFAULT_MAX_RETRIES);
70779
70780 dm_config_destroy(req.cft);
70781 buffer_destroy(&req.buffer);
70782
70783 log_debug("recv %s[%d] cl %u %s %s \"%s\" mode %s flags %x",
70784 cl->name[0] ? cl->name : "client", cl->pid, cl->id,
70785 op_str(act->op), rt_str(act->rt), act->vg_name, mode_str(act->mode), opts);
70786
70787 if (lm == LD_LM_DLM && !lm_support_dlm()) {
70788 log_debug("dlm not supported");
70789 rv = -EPROTONOSUPPORT;
70790 goto out;
70791 }
70792
70793 if (lm == LD_LM_SANLOCK && !lm_support_sanlock()) {
70794 log_debug("sanlock not supported");
70795 rv = -EPROTONOSUPPORT;
70796 goto out;
70797 }
70798
70799 if (act->op == LD_OP_LOCK && act->mode != LD_LK_UN)
70800 cl->lock_ops = 1;
70801
70802 switch (act->op) {
70803 case LD_OP_START:
70804 rv = add_lockspace(act);
70805 break;
70806 case LD_OP_STOP:
70807 rv = rem_lockspace(act);
70808 break;
70809 case LD_OP_DUMP_LOG:
70810 case LD_OP_DUMP_INFO:
70811 /* The client thread reply will copy and send the dump. */
70812 add_client_result(act);
70813 rv = 0;
70814 break;
70815 case LD_OP_INIT:
70816 case LD_OP_START_WAIT:
70817 case LD_OP_STOP_ALL:
70818 case LD_OP_RENAME_FINAL:
70819 case LD_OP_RUNNING_LM:
70820 add_work_action(act);
70821 rv = 0;
70822 break;
70823 case LD_OP_LOCK:
70824 case LD_OP_UPDATE:
70825 case LD_OP_ENABLE:
70826 case LD_OP_DISABLE:
70827 case LD_OP_FREE:
70828 case LD_OP_RENAME_BEFORE:
70829 case LD_OP_FIND_FREE_LOCK:
70830 case LD_OP_KILL_VG:
70831 case LD_OP_DROP_VG:
70832 case LD_OP_BUSY:
70833 rv = add_lock_action(act);
70834 break;
70835 default:
70836 rv = -EINVAL;
70837 };
70838
70839out:
70840 if (rv < 0) {
70841 act->result = rv;
70842 add_client_result(act);
70843 }
70844}
70845
70846static void *client_thread_main(void *arg_in)
70847{
70848 struct client *cl;
70849 struct action *act;
70850 struct action *act_un;
70851 int rv;
70852
70853 while (1) {
70854 pthread_mutex_lock(&client_mutex);
70855 while (!client_work && list_empty(&client_results)) {
70856 if (client_stop) {
70857 pthread_mutex_unlock(&client_mutex);
70858 goto out;
70859 }
70860 pthread_cond_wait(&client_cond, &client_mutex);
70861 }
70862
70863 /*
70864 * Send outgoing results back to clients
70865 */
70866
70867 if (!list_empty(&client_results)) {
70868 act = list_first_entry(&client_results, struct action, list);
70869 list_del(&act->list);
70870 cl = find_client_id(act->client_id);
70871 pthread_mutex_unlock(&client_mutex);
70872
70873 if (cl) {
70874 pthread_mutex_lock(&cl->mutex);
70875 rv = client_send_result(cl, act);
70876 pthread_mutex_unlock(&cl->mutex);
70877 } else {
70878 log_debug("no client %u for result", act->client_id);
70879 rv = -1;
70880 }
70881
70882 /*
70883 * The client failed after we acquired an LV lock for
70884 * it, but before getting this reply saying it's done.
70885 * So the lv will not be active and we should release
70886 * the lv lock it requested.
70887 */
70888 if ((rv < 0) && (act->flags & LD_AF_LV_LOCK)) {
70889 log_debug("auto unlock lv for failed client %u", act->client_id);
70890 if ((act_un = alloc_action())) {
70891 memcpy(act_un, act, sizeof(struct action));
70892 act_un->mode = LD_LK_UN;
70893 act_un->flags |= LD_AF_LV_UNLOCK;
70894 act_un->flags &= ~LD_AF_LV_LOCK;
70895 add_lock_action(act_un);
70896 }
70897 }
70898
70899 free_action(act);
70900 continue;
70901 }
70902
70903 /*
70904 * Queue incoming actions for lockspace threads
70905 */
70906
70907 if (client_work) {
70908 cl = find_client_work();
70909 if (!cl)
70910 client_work = 0;
70911 pthread_mutex_unlock(&client_mutex);
70912
70913 if (!cl)
70914 continue;
70915
70916 pthread_mutex_lock(&cl->mutex);
70917
70918 if (cl->recv) {
70919 cl->recv = 0;
70920 client_recv_action(cl);
70921 }
70922
70923 if (cl->dead) {
70924 /*
70925 log_debug("client rem %d pi %d fd %d ig %d",
70926 cl->id, cl->pi, cl->fd, cl->poll_ignore);
70927 */
70928
70929 /*
70930 * If cl->dead was set in main_loop, then the
70931 * fd has already been closed and the pollfd
70932 * entry is already unused.
70933 * main_loop set dead=1, ignore=0, pi=-1, fd=-1
70934 *
70935 * if cl->dead was not set in main_loop, but
70936 * set in client_recv_action, then the main_loop
70937 * should be ignoring this client fd.
70938 * main_loop set ignore=1
70939 */
70940
70941 if (cl->poll_ignore) {
70942 log_debug("client close %d pi %d fd %d",
70943 cl->id, cl->pi, cl->fd);
70944 /* assert cl->pi != -1 */
70945 /* assert pollfd[pi].fd == FD_IGNORE */
70946 if (close(cl->fd))
70947 log_error("client close %d pi %d fd %d failed",
70948 cl->id, cl->pi, cl->fd);
70949 rem_pollfd(cl->pi);
70950 cl->pi = -1;
70951 cl->fd = -1;
70952 cl->poll_ignore = 0;
70953 } else {
70954 /* main thread should have closed */
70955 if (cl->pi != -1 || cl->fd != -1) {
70956 log_error("client %d bad state pi %d fd %d",
70957 cl->id, cl->pi, cl->fd);
70958 }
70959 }
70960 pthread_mutex_unlock(&cl->mutex);
70961
70962 pthread_mutex_lock(&client_mutex);
70963 list_del(&cl->list);
70964 pthread_mutex_unlock(&client_mutex);
70965
70966 client_purge(cl);
70967
70968 free_client(cl);
70969 } else {
70970 pthread_mutex_unlock(&cl->mutex);
70971 }
70972 }
70973 pthread_mutex_unlock(&client_mutex);
70974 }
70975out:
70976 return NULL;
70977}
70978
70979static int setup_client_thread(void)
70980{
70981 int rv;
70982
70983 INIT_LIST_HEAD(&client_list);
70984 INIT_LIST_HEAD(&client_results);
70985
70986 pthread_mutex_init(&client_mutex, NULL);
70987 pthread_cond_init(&client_cond, NULL);
70988
70989 rv = pthread_create(&client_thread, NULL, client_thread_main, NULL);
70990 if (rv)
70991 return -1;
70992 return 0;
70993}
70994
70995static void close_client_thread(void)
70996{
70997 pthread_mutex_lock(&client_mutex);
70998 client_stop = 1;
70999 pthread_cond_signal(&client_cond);
71000 pthread_mutex_unlock(&client_mutex);
71001 pthread_join(client_thread, NULL);
71002}
71003
71004/*
71005 * Get a list of all VGs with a lockd type (sanlock|dlm) from lvmetad.
71006 * We'll match this list against a list of existing lockspaces that are
71007 * found in the lock manager.
71008 *
71009 * For each of these VGs, also create a struct resource on ls->resources to
71010 * represent each LV in the VG that uses a lock. For each of these LVs
71011 * that are active, we'll attempt to adopt a lock.
71012 */
71013
71014static int get_lockd_vgs(struct list_head *vg_lockd)
71015{
71016 struct list_head update_vgs;
71017 daemon_reply reply;
71018 struct dm_config_node *cn;
71019 struct dm_config_node *metadata;
71020 struct dm_config_node *md_cn;
71021 struct dm_config_node *lv_cn;
71022 struct lockspace *ls, *safe;
71023 struct resource *r;
71024 const char *vg_name;
71025 const char *vg_uuid;
71026 const char *lv_uuid;
71027 const char *lock_type;
71028 const char *lock_args;
71029 char find_str_path[PATH_MAX];
71030 int rv = 0;
71031
71032 INIT_LIST_HEAD(&update_vgs);
71033
71034 reply = send_lvmetad("vg_list", "token = %s", "skip", NULL);
71035
71036 if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
71037 log_error("vg_list from lvmetad failed %d", reply.error);
71038 rv = -EINVAL;
71039 goto destroy;
71040 }
71041
71042 if (!(cn = dm_config_find_node(reply.cft->root, "volume_groups"))) {
71043 log_error("get_lockd_vgs no vgs");
71044 rv = -EINVAL;
71045 goto destroy;
71046 }
71047
71048 /* create an update_vgs list of all vg uuids */
71049
71050 for (cn = cn->child; cn; cn = cn->sib) {
71051 vg_uuid = cn->key;
71052
71053 if (!(ls = alloc_lockspace())) {
71054 rv = -ENOMEM;
71055 break;
71056 }
71057
71058 strncpy(ls->vg_uuid, vg_uuid, 64);
71059 list_add_tail(&ls->list, &update_vgs);
71060 log_debug("get_lockd_vgs %s", vg_uuid);
71061 }
71062 destroy:
71063 daemon_reply_destroy(reply);
71064
71065 if (rv < 0)
71066 goto out;
71067
71068 /* get vg_name and lock_type for each vg uuid entry in update_vgs */
71069
71070 list_for_each_entry(ls, &update_vgs, list) {
71071 reply = send_lvmetad("vg_lookup",
71072 "token = %s", "skip",
71073 "uuid = %s", ls->vg_uuid,
71074 NULL);
71075
71076 if (reply.error || strcmp(daemon_reply_str(reply, "response", ""), "OK")) {
71077 log_error("vg_lookup from lvmetad failed %d", reply.error);
71078 rv = -EINVAL;
71079 goto next;
71080 }
71081
71082 vg_name = daemon_reply_str(reply, "name", NULL);
71083 if (!vg_name) {
71084 log_error("get_lockd_vgs %s no name", ls->vg_uuid);
71085 rv = -EINVAL;
71086 goto next;
71087 }
71088
71089 strncpy(ls->vg_name, vg_name, MAX_NAME);
71090
71091 metadata = dm_config_find_node(reply.cft->root, "metadata");
71092 if (!metadata) {
71093 log_error("get_lockd_vgs %s name %s no metadata",
71094 ls->vg_uuid, ls->vg_name);
71095 rv = -EINVAL;
71096 goto next;
71097 }
71098
71099 lock_type = dm_config_find_str(metadata, "metadata/lock_type", NULL);
71100 ls->lm_type = str_to_lm(lock_type);
71101
71102 if ((ls->lm_type != LD_LM_SANLOCK) && (ls->lm_type != LD_LM_DLM)) {
71103 log_debug("get_lockd_vgs %s not lockd type", ls->vg_name);
71104 continue;
71105 }
71106
71107 lock_args = dm_config_find_str(metadata, "metadata/lock_args", NULL);
71108 if (lock_args)
71109 strncpy(ls->vg_args, lock_args, MAX_ARGS);
71110
71111 log_debug("get_lockd_vgs %s lock_type %s lock_args %s",
71112 ls->vg_name, lock_type, lock_args ?: "none");
71113
71114 /*
71115 * Make a record (struct resource) of each lv that uses a lock.
71116 * For any lv that uses a lock, we'll check if the lv is active
71117 * and if so try to adopt a lock for it.
71118 */
71119
71120 for (md_cn = metadata->child; md_cn; md_cn = md_cn->sib) {
71121 if (strcmp(md_cn->key, "logical_volumes"))
71122 continue;
71123
71124 for (lv_cn = md_cn->child; lv_cn; lv_cn = lv_cn->sib) {
71125 snprintf(find_str_path, PATH_MAX, "%s/lock_type", lv_cn->key);
71126 lock_type = dm_config_find_str(lv_cn, find_str_path, NULL);
71127
71128 if (!lock_type)
71129 continue;
71130
71131 snprintf(find_str_path, PATH_MAX, "%s/lock_args", lv_cn->key);
71132 lock_args = dm_config_find_str(lv_cn, find_str_path, NULL);
71133
71134 snprintf(find_str_path, PATH_MAX, "%s/id", lv_cn->key);
71135 lv_uuid = dm_config_find_str(lv_cn, find_str_path, NULL);
71136
71137 if (!lv_uuid) {
71138 log_error("get_lock_vgs no lv id for name %s", lv_cn->key);
71139 continue;
71140 }
71141
71142 if (!(r = alloc_resource())) {
71143 rv = -ENOMEM;
71144 goto next;
71145 }
71146
71147 r->use_vb = 0;
71148 r->type = LD_RT_LV;
71149 strncpy(r->name, lv_uuid, MAX_NAME);
71150 if (lock_args)
71151 strncpy(r->lv_args, lock_args, MAX_ARGS);
71152 list_add_tail(&r->list, &ls->resources);
71153 log_debug("get_lockd_vgs %s lv %s %s (name %s)",
71154 ls->vg_name, r->name, lock_args ? lock_args : "", lv_cn->key);
71155 }
71156 }
71157 next:
71158 daemon_reply_destroy(reply);
71159
71160 if (rv < 0)
71161 break;
71162 }
71163out:
71164 /* Return lockd VG's on the vg_lockd list. */
71165
71166 list_for_each_entry_safe(ls, safe, &update_vgs, list) {
71167 list_del(&ls->list);
71168
71169 if ((ls->lm_type == LD_LM_SANLOCK) || (ls->lm_type == LD_LM_DLM))
71170 list_add_tail(&ls->list, vg_lockd);
71171 else
71172 free(ls);
71173 }
71174
71175 return rv;
71176}
71177
71178static char _dm_uuid[64];
71179
71180static char *get_dm_uuid(char *dm_name)
71181{
71182 struct dm_info info;
71183 struct dm_task *dmt;
71184 const char *uuid;
71185
71186 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
71187 goto fail_out;
71188
71189 if (!dm_task_set_name(dmt, dm_name))
71190 goto fail;
71191
71192 if (!dm_task_run(dmt))
71193 goto fail;
71194
71195 if (!dm_task_get_info(dmt, &info))
71196 goto fail;
71197
71198 if (!info.exists)
71199 goto fail;
71200
71201 uuid = dm_task_get_uuid(dmt);
71202 if (!uuid) {
71203 log_error("Failed to get uuid for device %s", dm_name);
71204 goto fail;
71205 }
71206
71207 if (strncmp(uuid, "LVM", 3)) {
71208 log_debug("dm device %s is not from LVM", dm_name);
71209 goto fail;
71210 }
71211
71212 memset(_dm_uuid, 0, sizeof(_dm_uuid));
71213 strncpy(_dm_uuid, uuid, sizeof(_dm_uuid)-1);
71214 dm_task_destroy(dmt);
71215 return _dm_uuid;
71216
71217fail:
71218 dm_task_destroy(dmt);
71219fail_out:
71220 return NULL;
71221}
71222
71223/*
71224 * dm reports the LV uuid as:
71225 * LVM-ydpRIdDWBDX25upmj2k0D4deat6oxH8er03T0f4xM8rPIV8XqIhwv3h8Y7xRWjMr
71226 *
71227 * the lock name for the LV is:
71228 * r03T0f-4xM8-rPIV-8XqI-hwv3-h8Y7-xRWjMr
71229 *
71230 * This function formats both as:
71231 * r03T0f4xM8rPIV8XqIhwv3h8Y7xRWjMr
71232 *
71233 * and returns 1 if they match.
71234 */
71235
71236static int match_dm_uuid(char *dm_uuid, char *lv_lock_uuid)
71237{
71238 char buf1[64];
71239 char buf2[64];
71240 int i, j;
71241
71242 memset(buf1, 0, sizeof(buf1));
71243 memset(buf2, 0, sizeof(buf2));
71244
71245 for (i = 0, j = 0; i < strlen(lv_lock_uuid); i++) {
71246 if (lv_lock_uuid[i] == '-')
71247 continue;
71248 buf1[j] = lv_lock_uuid[i];
71249 j++;
71250 }
71251
71252 for (i = 36, j = 0; i < 69; i++) {
71253 buf2[j] = dm_uuid[i];
71254 j++;
71255 }
71256
71257 if (!strcmp(buf1, buf2))
71258 return 1;
71259 return 0;
71260}
71261
71262/*
71263 * All LVs with a lock_type are on ls->resources.
71264 * Remove any that are not active. The remaining
71265 * will have locks adopted.
71266 */
71267
71268static int remove_inactive_lvs(struct list_head *vg_lockd)
71269{
71270 struct lockspace *ls;
71271 struct resource *r, *rsafe;
71272 struct dm_names *names;
71273 struct dm_task *dmt;
71274 char *dm_uuid;
71275 char *vgname, *lvname, *layer;
71276 char namebuf[MAX_NAME+1];
71277 unsigned next = 0;
71278 int rv = 0;
71279
71280 if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
71281 return -1;
71282
71283 if (!dm_task_run(dmt)) {
71284 log_error("Failed to get dm devices");
71285 rv = -1;
71286 goto ret;
71287 }
71288
71289 if (!(names = dm_task_get_names(dmt))) {
71290 log_error("Failed to get dm names");
71291 rv = -1;
71292 goto ret;
71293 }
71294
71295 if (!names->dev) {
71296 log_debug("dm names none found");
71297 goto out;
71298 }
71299
71300 /*
71301 * For each dm name, compare it to each lv in each lockd vg.
71302 */
71303
71304 do {
71305 names = (struct dm_names *)((char *) names + next);
71306
71307 dm_uuid = get_dm_uuid(names->name);
71308 if (!dm_uuid)
71309 goto next_dmname;
71310
71311 vgname = NULL;
71312 lvname = NULL;
71313 layer = NULL;
71314
71315 memset(namebuf, 0, sizeof(namebuf));
71316 strncpy(namebuf, names->name, MAX_NAME);
71317 vgname = namebuf;
71318
71319 if (!dm_split_lvm_name(NULL, namebuf, &vgname, &lvname, &layer)) {
71320 log_error("failed to split dm name %s", namebuf);
71321 goto next_dmname;
71322 }
71323
71324 log_debug("adopt remove_inactive dm name %s dm uuid %s vgname %s lvname %s",
71325 names->name, dm_uuid, vgname, lvname);
71326
71327 if (!vgname || !lvname) {
71328 log_debug("dm name %s invalid split vg %s lv %s layer %s",
71329 names->name, vgname ? vgname : "", lvname ? lvname : "", layer ? layer : "");
71330 goto next_dmname;
71331 }
71332
71333 list_for_each_entry(ls, vg_lockd, list) {
71334 if (strcmp(vgname, ls->vg_name))
71335 continue;
71336
71337 if (!strcmp(lvname, "lvmlock"))
71338 continue;
71339
71340 list_for_each_entry(r, &ls->resources, list) {
71341 if (!match_dm_uuid(dm_uuid, r->name))
71342 continue;
71343
71344 /* Found an active LV in a lockd VG. */
71345 log_debug("dm device %s adopt in vg %s lv %s",
71346 names->name, ls->vg_name, r->name);
71347 r->adopt = 1;
71348 goto next_dmname;
71349 }
71350 }
71351next_dmname:
71352 next = names->next;
71353 } while (next);
71354
71355out:
71356 /* Remove any struct resources that do not need locks adopted. */
71357 list_for_each_entry(ls, vg_lockd, list) {
71358 list_for_each_entry_safe(r, rsafe, &ls->resources, list) {
71359 if (r->adopt) {
71360 r->adopt = 0;
71361 } else {
71362 log_debug("lockd vg %s remove inactive lv %s", ls->vg_name, r->name);
71363 list_del(&r->list);
71364 free_resource(r);
71365 }
71366 }
71367 }
71368ret:
71369 dm_task_destroy(dmt);
71370 return rv;
71371}
71372
71373static void adopt_locks(void)
71374{
71375 struct list_head ls_found;
71376 struct list_head vg_lockd;
71377 struct list_head to_unlock;
71378 struct lockspace *ls, *lsafe;
71379 struct lockspace *ls1, *l1safe;
71380 struct lockspace *ls2, *l2safe;
71381 struct resource *r, *rsafe;
71382 struct action *act, *asafe;
71383 int count_start = 0, count_start_done = 0, count_start_fail = 0;
71384 int count_adopt = 0, count_adopt_done = 0, count_adopt_fail = 0;
71385 int found, rv;
71386
71387 INIT_LIST_HEAD(&adopt_results);
71388
71389 INIT_LIST_HEAD(&ls_found);
71390 INIT_LIST_HEAD(&vg_lockd);
71391 INIT_LIST_HEAD(&to_unlock);
71392
71393 /*
71394 * Get list of lockspaces from lock managers.
71395 * Get list of VGs from lvmetad with a lockd type.
71396 * Get list of active lockd type LVs from /dev.
71397 *
71398 * ECONNREFUSED means the lock manager is not running.
71399 * This is expected for at least one of them.
71400 */
71401
71402 if (lm_support_dlm()) {
71403 rv = lm_get_lockspaces_dlm(&ls_found);
71404 if ((rv < 0) && (rv != -ECONNREFUSED))
71405 goto fail;
71406 }
71407
71408 if (lm_support_sanlock()) {
71409 rv = lm_get_lockspaces_sanlock(&ls_found);
71410 if ((rv < 0) && (rv != -ECONNREFUSED))
71411 goto fail;
71412 }
71413
71414 if (list_empty(&ls_found)) {
71415 log_debug("No lockspaces found to adopt");
71416 return;
71417 }
71418
71419 /*
71420 * Adds a struct lockspace to vg_lockd for each lockd VG.
71421 * Adds a struct resource to ls->resources for each LV.
71422 */
71423 rv = get_lockd_vgs(&vg_lockd);
71424 if (rv < 0) {
71425 log_error("adopt_locks get_lockd_vgs failed");
71426 goto fail;
71427 }
71428
71429 /*
71430 * For each resource on each lockspace, check if the
71431 * corresponding LV is active. If so, leave the
71432 * resource struct, if not free the resource struct.
71433 * The remain entries need to have locks adopted.
71434 */
71435 rv = remove_inactive_lvs(&vg_lockd);
71436 if (rv < 0) {
71437 log_error("adopt_locks remove_inactive_lvs failed");
71438 goto fail;
71439 }
71440
71441 list_for_each_entry(ls, &ls_found, list) {
71442 if (ls->lm_type == LD_LM_DLM)
71443 gl_use_dlm = 1;
71444
71445 log_debug("adopt %s lockspace %s vg %s",
71446 lm_str(ls->lm_type), ls->name, ls->vg_name);
71447 }
71448
71449 if (!gl_use_dlm)
71450 gl_use_sanlock = 1;
71451
71452 list_for_each_entry(ls, &vg_lockd, list) {
71453 log_debug("adopt lvmetad vg %s lock_type %s lock_args %s",
71454 ls->vg_name, lm_str(ls->lm_type), ls->vg_args);
71455
71456 list_for_each_entry(r, &ls->resources, list)
71457 log_debug("adopt lv %s %s", ls->vg_name, r->name);
71458 }
71459
71460 /*
71461 * Compare and merge the list of lockspaces in ls_found
71462 * and the list of lockd VGs in vg_lockd.
71463 *
71464 * An ls from ls_found may not have had any active lvs when
71465 * previous lvmlockd died, but the ls should still be joined,
71466 * and checked for GL/VG locks.
71467 *
71468 * An ls from vg_lockd with active lvs should be in ls_found.
71469 * If it's not then we might want to join the ls and acquire locks
71470 * for the active lvs (as opposed to adopting orphans for them.)
71471 * The orphan lock in the ls should have prevented the ls in
71472 * the lock manager from going away.
71473 *
71474 * If an ls in vg_lockd has no active lvs and does not have
71475 * a matching entry in ls_found, then skip it.
71476 *
71477 * An ls in ls_found should always have a matching ls in
71478 * vg_lockd. If it doesn't, then maybe the vg has been
71479 * removed even though the lockspace for the vg is still
71480 * in the lock manager. Just leave the ls in the lm
71481 * alone, and skip the ls_found entry.
71482 */
71483
71484 list_for_each_entry_safe(ls1, l1safe, &ls_found, list) {
71485
71486 /* The dlm global lockspace is special and doesn't match a VG. */
71487 if (!strcmp(ls1->name, gl_lsname_dlm)) {
71488 list_del(&ls1->list);
71489 free(ls1);
71490 continue;
71491 }
71492
71493 found = 0;
71494
71495 list_for_each_entry_safe(ls2, l2safe, &vg_lockd, list) {
71496 if (strcmp(ls1->vg_name, ls2->vg_name))
71497 continue;
71498
71499 /*
71500 * LS in both ls_found and vg_lockd.
71501 */
71502 log_debug("ls %s matches vg %s", ls1->name, ls2->vg_name);
71503 memcpy(ls1->vg_uuid, ls2->vg_uuid, 64);
71504 memcpy(ls1->vg_args, ls2->vg_args, MAX_ARGS);
71505 list_for_each_entry_safe(r, rsafe, &ls2->resources, list) {
71506 list_del(&r->list);
71507 list_add(&r->list, &ls1->resources);
71508 }
71509 list_del(&ls2->list);
71510 free(ls2);
71511 found = 1;
71512 break;
71513 }
71514
71515 /*
71516 * LS in ls_found, not in vg_lockd.
71517 * An lvm lockspace found in the lock manager has no
71518 * corresponding VG in lvmetad. This shouldn't usually
71519 * happen, but it's possible the VG could have been removed
71520 * while the orphaned lockspace from it was still around.
71521 * Report an error and leave the ls in the lm alone.
71522 */
71523 if (!found) {
71524 log_error("No VG %s found for lockspace %s %s",
71525 ls1->vg_name, ls1->name, lm_str(ls1->lm_type));
71526 list_del(&ls1->list);
71527 free(ls1);
71528 }
71529 }
71530
71531 /*
71532 * LS in vg_lockd, not in ls_found.
71533 * lockd vgs from lvmetad that do not have an existing lockspace.
71534 * This wouldn't be unusual; we just skip the vg.
71535 * But, if the vg has active lvs, then it should have had locks
71536 * and a lockspace. Should we attempt to join the lockspace and
71537 * acquire (not adopt) locks for these LVs?
71538 */
71539
71540 list_for_each_entry_safe(ls, lsafe, &vg_lockd, list) {
71541 if (!list_empty(&ls->resources)) {
71542 /* We should have found a lockspace. */
71543 /* add this ls and acquire locks for ls->resources? */
71544 log_error("No lockspace %s %s found for VG %s with active LVs",
71545 ls->name, lm_str(ls->lm_type), ls->vg_name);
71546 } else {
71547 /* The VG wasn't started in the previous lvmlockd. */
71548 log_debug("No ls found for vg %s", ls->vg_name);
71549 }
71550
71551 list_del(&ls->list);
71552 free(ls);
71553 }
71554
71555 /*
71556 * Create and queue start actions to add lockspaces.
71557 */
71558
71559 if (gl_use_dlm) {
71560 if (!(act = alloc_action()))
71561 goto fail;
71562 log_debug("adopt add dlm global lockspace");
71563 act->op = LD_OP_START;
71564 act->flags = (LD_AF_ADOPT | LD_AF_WAIT);
71565 act->rt = LD_RT_GL;
71566 act->lm_type = LD_LM_DLM;
71567 act->client_id = INTERNAL_CLIENT_ID;
71568 add_dlm_global_lockspace(act);
71569 count_start++;
71570 }
71571
71572 list_for_each_entry_safe(ls, lsafe, &ls_found, list) {
71573 if (!(act = alloc_action()))
71574 goto fail;
71575 act->op = LD_OP_START;
71576 act->flags = (LD_AF_ADOPT | LD_AF_WAIT);
71577 act->rt = LD_RT_VG;
71578 act->lm_type = ls->lm_type;
71579 act->client_id = INTERNAL_CLIENT_ID;
71580 strncpy(act->vg_name, ls->vg_name, MAX_NAME);
71581 memcpy(act->vg_uuid, ls->vg_uuid, 64);
71582 memcpy(act->vg_args, ls->vg_args, MAX_ARGS);
71583 act->host_id = ls->host_id;
71584
71585 /* set act->version from lvmetad data? */
71586
71587 log_debug("adopt add %s vg lockspace %s", lm_str(act->lm_type), act->vg_name);
71588
71589 rv = add_lockspace_thread(ls->name, act->vg_name, act->vg_uuid,
71590 act->lm_type, act->vg_args, act);
71591 if (rv < 0) {
71592 log_error("Failed to create lockspace thread for VG %s", ls->vg_name);
71593 list_del(&ls->list);
71594 free(ls);
71595 free_action(act);
71596 count_start_fail++;
71597 continue;
71598 }
71599
71600 /*
71601 * When the lockspace_thread is done with the start act,
71602 * it will see the act ADOPT flag and move the act onto
71603 * the adopt_results list for us to collect below.
71604 */
71605 count_start++;
71606 }
71607
71608 log_debug("adopt starting %d lockspaces", count_start);
71609
71610 /*
71611 * Wait for all start/rejoin actions to complete. Each start action
71612 * queued above will appear on the adopt_results list when finished.
71613 */
71614
71615 while (count_start_done < count_start) {
71616 sleep(1);
71617 act = NULL;
71618
71619 pthread_mutex_lock(&client_mutex);
71620 if (!list_empty(&adopt_results)) {
71621 act = list_first_entry(&adopt_results, struct action, list);
71622 list_del(&act->list);
71623 }
71624 pthread_mutex_unlock(&client_mutex);
71625
71626 if (!act)
71627 continue;
71628
71629 if (act->result < 0) {
71630 log_error("adopt add lockspace failed vg %s %d", act->vg_name, act->result);
71631 count_start_fail++;
71632 }
71633
71634 free_action(act);
71635 count_start_done++;
71636 }
71637
71638 log_debug("adopt started %d lockspaces done %d fail %d",
71639 count_start, count_start_done, count_start_fail);
71640
71641 /*
71642 * Create lock-adopt actions for active LVs (ls->resources),
71643 * and GL/VG locks (we don't know if these locks were held
71644 * and orphaned by the last lvmlockd, so try to adopt them
71645 * to see.)
71646 *
71647 * A proper struct lockspace now exists on the lockspaces list
71648 * for each ls in ls_found. Lock ops for one of those
71649 * lockspaces can be done as OP_LOCK actions queued using
71650 * add_lock_action();
71651 *
71652 * Start by attempting to adopt the lock in the most likely
71653 * mode it was left in (ex for lvs, sh for vg/gl). If
71654 * the mode is wrong, the lm will return an error and we
71655 * try again with the other mode.
71656 */
71657
71658 list_for_each_entry(ls, &ls_found, list) {
71659
71660 /*
71661 * Adopt orphan LV locks.
71662 */
71663
71664 list_for_each_entry(r, &ls->resources, list) {
71665 if (!(act = alloc_action()))
71666 goto fail;
71667 act->op = LD_OP_LOCK;
71668 act->rt = LD_RT_LV;
71669 act->mode = LD_LK_EX;
71670 act->flags = (LD_AF_ADOPT | LD_AF_PERSISTENT);
71671 act->client_id = INTERNAL_CLIENT_ID;
71672 act->lm_type = ls->lm_type;
71673 strncpy(act->vg_name, ls->vg_name, MAX_NAME);
71674 strncpy(act->lv_uuid, r->name, MAX_NAME);
71675 strncpy(act->lv_args, r->lv_args, MAX_ARGS);
71676
71677 log_debug("adopt lock for lv %s %s", act->vg_name, act->lv_uuid);
71678
71679 rv = add_lock_action(act);
71680 if (rv < 0) {
71681 log_error("adopt add_lock_action lv %s %s error %d", act->vg_name, act->lv_uuid, rv);
71682 count_adopt_fail++;
71683 free_action(act);
71684 } else {
71685 count_adopt++;
71686 }
71687 }
71688
71689 /*
71690 * Adopt orphan VG lock.
71691 */
71692
71693 if (!(act = alloc_action()))
71694 goto fail;
71695 act->op = LD_OP_LOCK;
71696 act->rt = LD_RT_VG;
71697 act->mode = LD_LK_SH;
71698 act->flags = LD_AF_ADOPT;
71699 act->client_id = INTERNAL_CLIENT_ID;
71700 act->lm_type = ls->lm_type;
71701 strncpy(act->vg_name, ls->vg_name, MAX_NAME);
71702
71703 log_debug("adopt lock for vg %s", act->vg_name);
71704
71705 rv = add_lock_action(act);
71706 if (rv < 0) {
71707 log_error("adopt add_lock_action vg %s error %d", act->vg_name, rv);
71708 count_adopt_fail++;
71709 free_action(act);
71710 } else {
71711 count_adopt++;
71712 }
71713 }
71714
71715 /*
71716 * Adopt orphan GL lock.
71717 */
71718
71719 if (!(act = alloc_action()))
71720 goto fail;
71721 act->op = LD_OP_LOCK;
71722 act->rt = LD_RT_GL;
71723 act->mode = LD_LK_SH;
71724 act->flags = LD_AF_ADOPT;
71725 act->client_id = INTERNAL_CLIENT_ID;
71726 act->lm_type = (gl_use_sanlock ? LD_LM_SANLOCK : LD_LM_DLM);
71727
71728 log_debug("adopt lock for gl");
71729
71730 rv = add_lock_action(act);
71731 if (rv < 0) {
71732 log_error("adopt add_lock_action gl %s error %d", act->vg_name, rv);
71733 count_adopt_fail++;
71734 free_action(act);
71735 } else {
71736 count_adopt++;
71737 }
71738
71739 /*
71740 * Wait for lock-adopt actions to complete. The completed
71741 * actions are passed back here via the adopt_results list.
71742 */
71743
71744 while (count_adopt_done < count_adopt) {
71745 sleep(1);
71746 act = NULL;
71747
71748 pthread_mutex_lock(&client_mutex);
71749 if (!list_empty(&adopt_results)) {
71750 act = list_first_entry(&adopt_results, struct action, list);
71751 list_del(&act->list);
71752 }
71753 pthread_mutex_unlock(&client_mutex);
71754
71755 if (!act)
71756 continue;
71757
71758 /*
71759 * lock adopt results
71760 */
71761
71762 if (act->result == -EUCLEAN) {
71763 /*
71764 * Adopt failed because the orphan has a different mode
71765 * than initially requested. Repeat the lock-adopt operation
71766 * with the other mode. N.B. this logic depends on first
71767 * trying sh then ex for GL/VG locks, and ex then sh for
71768 * LV locks.
71769 */
71770
71771 if ((act->rt != LD_RT_LV) && (act->mode == LD_LK_SH)) {
71772 /* GL/VG locks: attempt to adopt ex after sh failed. */
71773 act->mode = LD_LK_EX;
71774 rv = add_lock_action(act);
71775
71776 } else if ((act->rt == LD_RT_LV) && (act->mode == LD_LK_EX)) {
71777 /* LV locks: attempt to adopt sh after ex failed. */
71778 act->mode = LD_LK_SH;
71779 rv = add_lock_action(act);
71780
71781 } else {
71782 log_error("Failed to adopt %s lock in vg %s error %d",
71783 rt_str(act->rt), act->vg_name, act->result);
71784 count_adopt_fail++;
71785 count_adopt_done++;
71786 free_action(act);
71787 rv = 0;
71788 }
71789
71790 if (rv < 0) {
71791 log_error("adopt add_lock_action again %s", act->vg_name);
71792 count_adopt_fail++;
71793 count_adopt_done++;
71794 free_action(act);
71795 }
71796
71797 } else if (act->result == -ENOENT) {
71798 /*
71799 * No orphan lock exists. This is common for GL/VG locks
71800 * because they may not have been held when lvmlockd exited.
71801 * It's also expected for LV types that do not use a lock.
71802 */
71803
71804 if (act->rt == LD_RT_LV) {
71805 /* Unexpected, we should have found an orphan. */
71806 log_error("Failed to adopt LV lock for %s %s error %d",
71807 act->vg_name, act->lv_uuid, act->result);
71808 count_adopt_fail++;
71809 } else {
71810 /* Normal, no GL/VG lock was orphaned. */
71811 log_debug("Did not adopt %s lock in vg %s error %d",
71812 rt_str(act->rt), act->vg_name, act->result);
71813 }
71814
71815 count_adopt_done++;
71816 free_action(act);
71817
71818 } else if (act->result < 0) {
71819 /*
71820 * Some unexpected error.
71821 */
71822
71823 log_error("adopt lock rt %s vg %s lv %s error %d",
71824 rt_str(act->rt), act->vg_name, act->lv_uuid, act->result);
71825 count_adopt_fail++;
71826 count_adopt_done++;
71827 free_action(act);
71828
71829 } else {
71830 /*
71831 * Adopt success.
71832 */
71833
71834 if (act->rt == LD_RT_LV) {
71835 log_debug("adopt success lv %s %s %s", act->vg_name, act->lv_uuid, mode_str(act->mode));
71836 free_action(act);
71837 } else if (act->rt == LD_RT_VG) {
71838 log_debug("adopt success vg %s %s", act->vg_name, mode_str(act->mode));
71839 list_add_tail(&act->list, &to_unlock);
71840 } else if (act->rt == LD_RT_GL) {
71841 log_debug("adopt success gl %s %s", act->vg_name, mode_str(act->mode));
71842 list_add_tail(&act->list, &to_unlock);
71843 }
71844 count_adopt_done++;
71845 }
71846 }
71847
71848 /*
71849 * Release adopted GL/VG locks.
71850 * The to_unlock actions were the ones used to lock-adopt the GL/VG locks;
71851 * now use them to do the unlocks. These actions will again be placed
71852 * on adopt_results for us to collect because they have the ADOPT flag set.
71853 */
71854
71855 count_adopt = 0;
71856 count_adopt_done = 0;
71857
71858 list_for_each_entry_safe(act, asafe, &to_unlock, list) {
71859 list_del(&act->list);
71860
71861 if (act->mode == LD_LK_EX) {
71862 /*
71863 * FIXME: we probably want to check somehow that
71864 * there's no lvm command still running that's
71865 * using this ex lock and changing things.
71866 */
71867 log_warn("adopt releasing ex %s lock %s",
71868 rt_str(act->rt), act->vg_name);
71869 }
71870
71871 act->mode = LD_LK_UN;
71872
71873 log_debug("adopt unlock for %s %s", rt_str(act->rt), act->vg_name);
71874
71875 rv = add_lock_action(act);
71876 if (rv < 0) {
71877 log_error("adopt unlock add_lock_action error %d", rv);
71878 free_action(act);
71879 } else {
71880 count_adopt++;
71881 }
71882 }
71883
71884 /* Wait for the unlocks to complete. */
71885
71886 while (count_adopt_done < count_adopt) {
71887 sleep(1);
71888 act = NULL;
71889
71890 pthread_mutex_lock(&client_mutex);
71891 if (!list_empty(&adopt_results)) {
71892 act = list_first_entry(&adopt_results, struct action, list);
71893 list_del(&act->list);
71894 }
71895 pthread_mutex_unlock(&client_mutex);
71896
71897 if (!act)
71898 continue;
71899
71900 if (act->result < 0)
71901 log_error("adopt unlock error %d", act->result);
71902
71903 count_adopt_done++;
71904 free_action(act);
71905 }
71906
71907
71908 /* FIXME: purge any remaining orphan locks in each rejoined ls? */
71909
71910 if (count_start_fail || count_adopt_fail)
71911 goto fail;
71912
71913 log_debug("adopt_locks done");
71914 return;
71915
71916fail:
71917 log_error("adopt_locks failed, reset host");
71918}
71919
71920static int get_peer_pid(int fd)
71921{
71922 struct ucred cred;
71923 unsigned int len = sizeof(cred);
71924
71925 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) != 0)
71926 return -1;
71927
71928 return cred.pid;
71929}
71930
71931static void process_listener(int poll_fd)
71932{
71933 struct client *cl;
71934 int fd, pi;
71935
71936 /* assert poll_fd == listen_fd */
71937
71938 fd = accept(listen_fd, NULL, NULL);
71939 if (fd < 0)
71940 return;
71941
71942 if (!(cl = alloc_client())) {
71943 if (!close(fd))
71944 log_error("failed to close lockd poll fd");
71945 return;
71946 }
71947
71948 pi = add_pollfd(fd);
71949 if (pi < 0) {
71950 log_error("process_listener add_pollfd error %d", pi);
71951 free_client(cl);
71952 return;
71953 }
71954
71955 cl->pi = pi;
71956 cl->fd = fd;
71957 cl->pid = get_peer_pid(fd);
71958
71959 pthread_mutex_init(&cl->mutex, NULL);
71960
71961 pthread_mutex_lock(&client_mutex);
71962 client_ids++;
71963
71964 if (client_ids == INTERNAL_CLIENT_ID)
71965 client_ids++;
71966 if (!client_ids)
71967 client_ids++;
71968
71969 cl->id = client_ids;
71970 list_add_tail(&cl->list, &client_list);
71971 pthread_mutex_unlock(&client_mutex);
71972
71973 log_debug("new cl %u pi %d fd %d", cl->id, cl->pi, cl->fd);
71974}
71975
71976/*
71977 * main loop polls on pipe[0] so that a thread can
71978 * restart the poll by writing to pipe[1].
71979 */
71980static int setup_restart(void)
71981{
71982 if (pipe(restart_fds)) {
71983 log_error("setup_restart pipe error %d", errno);
71984 return -1;
71985 }
71986
71987 restart_pi = add_pollfd(restart_fds[0]);
71988 if (restart_pi < 0)
71989 return restart_pi;
71990
71991 return 0;
71992}
71993
71994/*
71995 * thread wrote 'w' to restart_fds[1] to restart poll()
71996 * after adding an fd back into pollfd.
71997 */
71998static void process_restart(int fd)
71999{
72000 char wake[1];
72001 int rv;
72002
72003 /* assert fd == restart_fds[0] */
72004
72005 rv = read(restart_fds[0], wake, 1);
72006 if (!rv || rv < 0)
72007 log_debug("process_restart error %d", errno);
72008}
72009
72010static void sigterm_handler(int sig __attribute__((unused)))
72011{
72012 daemon_quit = 1;
72013}
72014
72015static int main_loop(daemon_state *ds_arg)
72016{
72017 struct client *cl;
72018 int i, rv, is_recv, is_dead;
72019
72020 signal(SIGTERM, &sigterm_handler);
72021
72022 rv = setup_structs();
72023 if (rv < 0) {
72024 log_error("Can't allocate memory");
72025 return rv;
72026 }
72027
72028 strcpy(gl_lsname_dlm, S_NAME_GL_DLM);
72029
72030 INIT_LIST_HEAD(&lockspaces);
72031 pthread_mutex_init(&lockspaces_mutex, NULL);
72032 pthread_mutex_init(&pollfd_mutex, NULL);
72033 pthread_mutex_init(&log_mutex, NULL);
72034
72035 openlog("lvmlockd", LOG_CONS | LOG_PID, LOG_DAEMON);
72036 log_warn("lvmlockd started");
72037
72038 listen_fd = ds_arg->socket_fd;
72039 listen_pi = add_pollfd(listen_fd);
72040
72041 setup_client_thread();
72042 setup_worker_thread();
72043 setup_restart();
72044
72045 pthread_mutex_init(&lvmetad_mutex, NULL);
72046 lvmetad_handle = lvmetad_open(NULL);
72047 if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0)
72048 log_error("lvmetad_open error %d", lvmetad_handle.error);
72049 else
72050 lvmetad_connected = 1;
72051
72052 /*
72053 * Attempt to rejoin lockspaces and adopt locks from a previous
72054 * instance of lvmlockd that left behind lockspaces/locks.
72055 */
72056 if (adopt_opt)
72057 adopt_locks();
72058
72059 while (1) {
72060 rv = poll(pollfd, pollfd_maxi + 1, -1);
72061 if ((rv == -1 && errno == EINTR) || daemon_quit) {
72062 if (daemon_quit) {
72063 int count;
72064 /* first sigterm would trigger stops, and
72065 second sigterm may finish the joins. */
72066 count = for_each_lockspace(DO_STOP, DO_FREE, NO_FORCE);
72067 if (!count)
72068 break;
72069 log_debug("ignore shutdown for %d lockspaces", count);
72070 daemon_quit = 0;
72071 }
72072 continue;
72073 }
72074 if (rv < 0) {
72075 log_error("poll errno %d", errno);
72076 break;
72077 }
72078
72079 for (i = 0; i <= pollfd_maxi; i++) {
72080 if (pollfd[i].fd < 0)
72081 continue;
72082
72083 is_recv = 0;
72084 is_dead = 0;
72085
72086 if (pollfd[i].revents & POLLIN)
72087 is_recv = 1;
72088 if (pollfd[i].revents & (POLLERR | POLLHUP | POLLNVAL))
72089 is_dead = 1;
72090
72091 if (!is_recv && !is_dead)
72092 continue;
72093
72094 if (i == listen_pi) {
72095 process_listener(pollfd[i].fd);
72096 continue;
72097 }
72098
72099 if (i == restart_pi) {
72100 process_restart(pollfd[i].fd);
72101 continue;
72102 }
72103
72104 /*
72105 log_debug("poll pi %d fd %d revents %x",
72106 i, pollfd[i].fd, pollfd[i].revents);
72107 */
72108
72109 pthread_mutex_lock(&client_mutex);
72110 cl = find_client_pi(i);
72111 if (cl) {
72112 pthread_mutex_lock(&cl->mutex);
72113
72114 if (cl->recv) {
72115 /* should not happen */
72116 log_error("main client %u already recv", cl->id);
72117
72118 } else if (cl->dead) {
72119 /* should not happen */
72120 log_error("main client %u already dead", cl->id);
72121
72122 } else if (is_dead) {
72123 log_debug("close %s[%d] cl %u fd %d",
72124 cl->name[0] ? cl->name : "client",
72125 cl->pid, cl->id, cl->fd);
72126 cl->dead = 1;
72127 cl->pi = -1;
72128 cl->fd = -1;
72129 cl->poll_ignore = 0;
72130 if (close(pollfd[i].fd))
72131 log_error("close fd %d failed", pollfd[i].fd);
72132 pollfd[i].fd = POLL_FD_UNUSED;
72133 pollfd[i].events = 0;
72134 pollfd[i].revents = 0;
72135
72136 } else if (is_recv) {
72137 cl->recv = 1;
72138 cl->poll_ignore = 1;
72139 pollfd[i].fd = POLL_FD_IGNORE;
72140 pollfd[i].events = 0;
72141 pollfd[i].revents = 0;
72142 }
72143
72144 pthread_mutex_unlock(&cl->mutex);
72145
72146 client_work = 1;
72147 pthread_cond_signal(&client_cond);
72148
72149 /* client_thread will pick up and work on any
72150 client with cl->recv or cl->dead set */
72151
72152 } else {
72153 /* don't think this can happen */
72154 log_error("no client for index %d fd %d",
72155 i, pollfd[i].fd);
72156 if (close(pollfd[i].fd))
72157 log_error("close fd %d failed", pollfd[i].fd);
72158 pollfd[i].fd = POLL_FD_UNUSED;
72159 pollfd[i].events = 0;
72160 pollfd[i].revents = 0;
72161 }
72162 pthread_mutex_unlock(&client_mutex);
72163
72164 /* After set_dead, should we scan pollfd for
72165 last unused slot and reduce pollfd_maxi? */
72166 }
72167 }
72168
72169 for_each_lockspace_retry(DO_STOP, DO_FREE, DO_FORCE);
72170 close_worker_thread();
72171 close_client_thread();
72172 closelog();
72173 daemon_close(lvmetad_handle);
72174 return 1; /* libdaemon uses 1 for success */
72175}
72176
72177static void usage(char *prog, FILE *file)
72178{
72179 fprintf(file, "Usage:\n");
72180 fprintf(file, "%s [options]\n\n", prog);
72181 fprintf(file, " --help | -h\n");
72182 fprintf(file, " Show this help information.\n");
72183 fprintf(file, " --version | -V\n");
72184 fprintf(file, " Show version of lvmlockd.\n");
72185 fprintf(file, " --test | -T\n");
72186 fprintf(file, " Test mode, do not call lock manager.\n");
72187 fprintf(file, " --foreground | -f\n");
72188 fprintf(file, " Don't fork.\n");
72189 fprintf(file, " --daemon-debug | -D\n");
72190 fprintf(file, " Don't fork and print debugging to stdout.\n");
72191 fprintf(file, " --pid-file | -p <path>\n");
72192 fprintf(file, " Set path to the pid file. [%s]\n", LVMLOCKD_PIDFILE);
72193 fprintf(file, " --socket-path | -s <path>\n");
72194 fprintf(file, " Set path to the socket to listen on. [%s]\n", LVMLOCKD_SOCKET);
72195 fprintf(file, " --syslog-priority | -S err|warning|debug\n");
72196 fprintf(file, " Write log messages from this level up to syslog. [%s]\n", _syslog_num_to_name(LOG_SYSLOG_PRIO));
72197 fprintf(file, " --gl-type | -g <str>\n");
72198 fprintf(file, " Set global lock type to be dlm|sanlock.\n");
72199 fprintf(file, " --host-id | -i <num>\n");
72200 fprintf(file, " Set the local sanlock host id.\n");
72201 fprintf(file, " --host-id-file | -F <path>\n");
72202 fprintf(file, " A file containing the local sanlock host_id.\n");
72203 fprintf(file, " --sanlock-timeout | -o <seconds>\n");
72204 fprintf(file, " Set the sanlock lockspace I/O timeout.\n");
72205 fprintf(file, " --adopt | -A 0|1\n");
72206 fprintf(file, " Adopt locks from a previous instance of lvmlockd.\n");
72207}
72208
72209int main(int argc, char *argv[])
72210{
72211 daemon_state ds = {
72212 .daemon_main = main_loop,
72213 .daemon_init = NULL,
72214 .daemon_fini = NULL,
72215 .pidfile = getenv("LVM_LVMLOCKD_PIDFILE"),
72216 .socket_path = getenv("LVM_LVMLOCKD_SOCKET"),
72217 .protocol = lvmlockd_protocol,
72218 .protocol_version = lvmlockd_protocol_version,
72219 .name = "lvmlockd",
72220 };
72221
72222 static struct option long_options[] = {
72223 {"help", no_argument, 0, 'h' },
72224 {"version", no_argument, 0, 'V' },
72225 {"test", no_argument, 0, 'T' },
72226 {"foreground", no_argument, 0, 'f' },
72227 {"daemon-debug", no_argument, 0, 'D' },
72228 {"pid-file", required_argument, 0, 'p' },
72229 {"socket-path", required_argument, 0, 's' },
72230 {"gl-type", required_argument, 0, 'g' },
72231 {"host-id", required_argument, 0, 'i' },
72232 {"host-id-file", required_argument, 0, 'F' },
72233 {"adopt", required_argument, 0, 'A' },
72234 {"syslog-priority", required_argument, 0, 'S' },
72235 {"sanlock-timeout", required_argument, 0, 'o' },
72236 {0, 0, 0, 0 }
72237 };
72238
72239 while (1) {
72240 int c;
72241 int lm;
72242 int option_index = 0;
72243
72244 c = getopt_long(argc, argv, "hVTfDp:s:l:g:S:I:A:o:",
72245 long_options, &option_index);
72246 if (c == -1)
72247 break;
72248
72249 switch (c) {
72250 case '0':
72251 break;
72252 case 'h':
72253 usage(argv[0], stdout);
72254 exit(EXIT_SUCCESS);
72255 case 'V':
72256 printf("lvmlockd version: " LVM_VERSION "\n");
72257 exit(EXIT_SUCCESS);
72258 case 'T':
72259 daemon_test = 1;
72260 break;
72261 case 'f':
72262 ds.foreground = 1;
72263 break;
72264 case 'D':
72265 ds.foreground = 1;
72266 daemon_debug = 1;
72267 break;
72268 case 'p':
72269 ds.pidfile = strdup(optarg);
72270 break;
72271 case 's':
72272 ds.socket_path = strdup(optarg);
72273 break;
72274 case 'g':
72275 lm = str_to_lm(optarg);
72276 if (lm == LD_LM_DLM && lm_support_dlm())
72277 gl_use_dlm = 1;
72278 else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
72279 gl_use_sanlock = 1;
72280 else {
72281 fprintf(stderr, "invalid gl-type option\n");
72282 exit(EXIT_FAILURE);
72283 }
72284 break;
72285 case 'i':
72286 daemon_host_id = atoi(optarg);
72287 break;
72288 case 'F':
72289 daemon_host_id_file = strdup(optarg);
72290 break;
72291 case 'o':
72292 sanlock_io_timeout = atoi(optarg);
72293 break;
72294 case 'A':
72295 adopt_opt = atoi(optarg);
72296 break;
72297 case 'S':
72298 syslog_priority = _syslog_name_to_num(optarg);
72299 break;
72300 case '?':
72301 default:
72302 usage(argv[0], stdout);
72303 exit(EXIT_FAILURE);
72304 }
72305 }
72306
72307 if (!ds.pidfile)
72308 ds.pidfile = LVMLOCKD_PIDFILE;
72309
72310 if (!ds.socket_path)
72311 ds.socket_path = LVMLOCKD_SOCKET;
72312
72313 /* runs daemon_main/main_loop */
72314 daemon_start(ds);
72315
72316 return 0;
72317}
72318\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003372\013062740170\0022362\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
72319# Copyright (C) 2014-2015 Red Hat, Inc.
72320#
72321# This file is part of LVM2.
72322#
72323# This copyrighted material is made available to anyone wishing to use,
72324# modify, copy, or redistribute it subject to the terms and conditions
72325# of the GNU Lesser General Public License v.2.1.
72326#
72327# You should have received a copy of the GNU Lesser General Public License
72328# along with this program; if not, write to the Free Software Foundation,
72329# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
72330
72331srcdir = @srcdir@
72332top_srcdir = @top_srcdir@
72333top_builddir = @top_builddir@
72334
72335SOURCES = lvmlockd-core.c
72336
72337ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
72338 SOURCES += lvmlockd-sanlock.c
72339endif
72340
72341ifeq ("@BUILD_LOCKDDLM@", "yes")
72342 SOURCES += lvmlockd-dlm.c
72343endif
72344
72345TARGETS = lvmlockd lvmlockctl
72346
72347.PHONY: install_lvmlockd
72348
72349include $(top_builddir)/make.tmpl
72350
72351INCLUDES += -I$(top_srcdir)/libdaemon/server
72352LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
72353
72354LIBS += $(PTHREAD_LIBS)
72355
72356ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
72357 LIBS += -lsanlock_client
72358endif
72359
72360ifeq ("@BUILD_LOCKDDLM@", "yes")
72361 LIBS += -ldlm_lt
72362endif
72363
72364LDFLAGS += -L$(top_builddir)/libdaemon/server
72365CLDFLAGS += -L$(top_builddir)/libdaemon/server
72366
72367lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
72368 $(top_builddir)/libdaemon/server/libdaemonserver.a
72369 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
72370
72371lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
72372 $(top_builddir)/libdaemon/server/libdaemonserver.a
72373 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(LVMLIBS)
72374
72375install_lvmlockd: lvmlockd
72376 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
72377
72378install_lvmlockctl: lvmlockctl
72379 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
72380
72381install_lvm2: install_lvmlockd install_lvmlockctl
72382
72383install: install_lvm2
72384\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockd-sanlock.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000144467\013062740170\0023737\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
72385 * Copyright (C) 2014-2015 Red Hat, Inc.
72386 *
72387 * This file is part of LVM2.
72388 *
72389 * This copyrighted material is made available to anyone wishing to use,
72390 * modify, copy, or redistribute it subject to the terms and conditions
72391 * of the GNU Lesser General Public License v.2.1.
72392 */
72393
72394#define _XOPEN_SOURCE 500 /* pthread */
72395#define _ISOC99_SOURCE
72396
72397#include "tool.h"
72398
72399#include "daemon-server.h"
72400#include "xlate.h"
72401
72402#include "lvmlockd-internal.h"
72403#include "lvmlockd-client.h"
72404
72405#include "sanlock.h"
72406#include "sanlock_rv.h"
72407#include "sanlock_admin.h"
72408#include "sanlock_resource.h"
72409
72410#include <stddef.h>
72411#include <poll.h>
72412#include <errno.h>
72413#include <syslog.h>
72414
72415/*
72416-------------------------------------------------------------------------------
72417For each VG, lvmlockd creates a sanlock lockspace that holds the leases for
72418that VG. There's a lease for the VG lock, and there's a lease for each active
72419LV. sanlock maintains (reads/writes) these leases, which exist on storage.
72420That storage is a hidden LV within the VG: /dev/vg/lvmlock. lvmlockd gives the
72421path of this internal LV to sanlock, which then reads/writes the leases on it.
72422
72423# lvs -a cc -o+uuid
72424 LV VG Attr LSize LV UUID
72425 lv1 cc -wi-a----- 2.00g 7xoDtu-yvNM-iwQx-C94t-BbYs-UzBl-o8hAIa
72426 lv2 cc -wi-a----- 100.00g exxNPX-wZdO-uCNy-yiGa-aJGT-JKVl-arfcYT
72427 [lvmlock] cc -wi-ao---- 256.00m iLpDel-hR0T-hJ3u-rnVo-PcDh-mcjt-sF9egM
72428
72429# sanlock status
72430s lvm_cc:1:/dev/mapper/cc-lvmlock:0
72431r lvm_cc:exxNPX-wZdO-uCNy-yiGa-aJGT-JKVl-arfcYT:/dev/mapper/cc-lvmlock:71303168:13 p 26099
72432r lvm_cc:7xoDtu-yvNM-iwQx-C94t-BbYs-UzBl-o8hAIa:/dev/mapper/cc-lvmlock:70254592:3 p 26099
72433
72434This shows that sanlock is maintaining leases on /dev/mapper/cc-lvmlock.
72435
72436sanlock acquires a lockspace lease when the lockspace is joined, i.e. when the
72437VG is started by 'vgchange --lock-start cc'. This lockspace lease exists at
72438/dev/mapper/cc-lvmlock offset 0, and sanlock regularly writes to it to maintain
72439ownership of it. Joining the lockspace (by acquiring the lockspace lease in
72440it) then allows standard resource leases to be acquired in the lockspace for
72441whatever the application wants. lvmlockd uses resource leases for the VG lock
72442and LV locks.
72443
72444sanlock acquires a resource lease for each actual lock that lvm commands use.
72445Above, there are two LV locks that are held because the two LVs are active.
72446These are on /dev/mapper/cc-lvmlock at offsets 71303168 and 70254592. sanlock
72447does not write to these resource leases except when acquiring and releasing
72448them (e.g. lvchange -ay/-an). The renewal of the lockspace lease maintains
72449ownership of all the resource leases in the lockspace.
72450
72451If the host loses access to the disk that the sanlock lv lives on, then sanlock
72452can no longer renew its lockspace lease. The lockspace lease will eventually
72453expire, at which point the host will lose ownership of it, and of all resource
72454leases it holds in the lockspace. Eventually, other hosts will be able to
72455acquire those leases. sanlock ensures that another host will not be able to
72456acquire one of the expired leases until the current host has quit using it.
72457
72458It is important that the host "quit using" the leases it is holding if the
72459sanlock storage is lost and they begin expiring. If the host cannot quit using
72460the leases and release them within a limited time, then sanlock will use the
72461local watchdog to forcibly reset the host before any other host can acquire
72462them. This is severe, but preferable to possibly corrupting the data protected
72463by the lease. It ensures that two nodes will not be using the same lease at
72464once. For LV leases, that means that another host will not be able to activate
72465the LV while another host still has it active.
72466
72467sanlock notifies the application that it cannot renew the lockspace lease. The
72468application needs to quit using all leases in the lockspace and release them as
72469quickly as possible. In the initial version, lvmlockd ignored this
72470notification, so sanlock would eventually reach the point where it would use
72471the local watchdog to reset the host. However, it's better to attempt a
72472response. If that response succeeds, the host can avoid being reset. If the
72473response fails, then sanlock will eventually reset the host as the last resort.
72474sanlock gives the application about 40 seconds to complete its response and
72475release its leases before resetting the host.
72476
72477An application can specify the path and args of a program that sanlock should
72478run to notify it if the lockspace lease cannot be renewed. This program should
72479carry out the application's response to the expiring leases: attempt to quit
72480using the leases and then release them. lvmlockd gives this command to sanlock
72481for each VG when that VG is started: 'lvmlockctl --kill vg_name'
72482
72483If sanlock loses access to lease storage in that VG, it runs lvmlockctl --kill,
72484which:
72485
724861. Uses syslog to explain what is happening.
72487
724882. Notifies lvmlockd that the VG is being killed, so lvmlockd can
72489 immediatley return an error for this condition if any new lock
72490 requests are made. (This step would not be strictly necessary.)
72491
724923. Attempts to quit using the VG. This is not yet implemented, but
72493 will eventually use blkdeactivate on the VG (or a more forceful
72494 equivalent.)
72495
724964. If step 3 was successful at terminating all use of the VG, then
72497 lvmlockd is told to release all the leases for the VG. If this
72498 is all done without about 40 seconds, the host can avoid being
72499 reset.
72500
72501Until steps 3 and 4 are fully implemented, manual steps can be substituted.
72502This is primarily for testing since the problem needs to be noticed and
72503responded to in a very short time. The manual alternative to step 3 is to kill
72504any processes using file systems on LV's in the VG, unmount all file systems on
72505the LVs, and deactivate all the LVs. Once this is done, the manual alternative
72506to step 4 is to run 'lvmlockctl --drop vg_name', which tells lvmlockd to
72507release all the leases for the VG.
72508-------------------------------------------------------------------------------
72509*/
72510
72511
72512/*
72513 * Each lockspace thread has its own sanlock daemon connection.
72514 * If they shared one, sanlock acquire/release calls would be
72515 * serialized. Some aspects of sanlock expect a single connection
72516 * from each pid: signals due to a sanlock_request, and
72517 * acquire/release/convert/inquire. The later can probably be
72518 * addressed with a flag to indicate that the pid field should be
72519 * interpretted as 'ci' (which the caller would need to figure
72520 * out somehow.)
72521 */
72522
72523struct lm_sanlock {
72524 struct sanlk_lockspace ss;
72525 int align_size;
72526 int sock; /* sanlock daemon connection */
72527};
72528
72529struct rd_sanlock {
72530 union {
72531 struct sanlk_resource rs;
72532 char buf[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
72533 };
72534 struct val_blk *vb;
72535};
72536
72537struct sanlk_resourced {
72538 union {
72539 struct sanlk_resource rs;
72540 char buf[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
72541 };
72542};
72543
72544int lm_data_size_sanlock(void)
72545{
72546 return sizeof(struct rd_sanlock);
72547}
72548
72549/*
72550 * lock_args format
72551 *
72552 * vg_lock_args format for sanlock is
72553 * vg_version_string:undefined:lock_lv_name
72554 *
72555 * lv_lock_args format for sanlock is
72556 * lv_version_string:undefined:offset
72557 *
72558 * version_string is MAJOR.MINOR.PATCH
72559 * undefined may contain ":"
72560 *
72561 * If a new version of the lock_args string cannot be
72562 * handled by an old version of lvmlockd, then the
72563 * new lock_args string should contain a larger major number.
72564 */
72565
72566#define VG_LOCK_ARGS_MAJOR 1
72567#define VG_LOCK_ARGS_MINOR 0
72568#define VG_LOCK_ARGS_PATCH 0
72569
72570#define LV_LOCK_ARGS_MAJOR 1
72571#define LV_LOCK_ARGS_MINOR 0
72572#define LV_LOCK_ARGS_PATCH 0
72573
72574/*
72575 * offset 0 is lockspace
72576 * offset align_size * 1 is unused
72577 * offset align_size * 2 is unused
72578 * ...
72579 * offset align_size * 64 is unused
72580 * offset align_size * 65 is gl lock
72581 * offset align_size * 66 is vg lock
72582 * offset align_size * 67 is first lv lock
72583 * offset align_size * 68 is second lv lock
72584 * ...
72585 */
72586
72587#define LS_BEGIN 0
72588#define GL_LOCK_BEGIN UINT64_C(65)
72589#define VG_LOCK_BEGIN UINT64_C(66)
72590#define LV_LOCK_BEGIN UINT64_C(67)
72591
72592static uint64_t daemon_test_lv_count;
72593
72594static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
72595{
72596 return last_string_from_args(vg_args, lock_lv_name);
72597}
72598
72599static int lock_lv_offset_from_args(char *lv_args, uint64_t *lock_lv_offset)
72600{
72601 char offset_str[MAX_ARGS+1];
72602 int rv;
72603
72604 memset(offset_str, 0, sizeof(offset_str));
72605
72606 rv = last_string_from_args(lv_args, offset_str);
72607 if (rv < 0)
72608 return rv;
72609
72610 *lock_lv_offset = strtoull(offset_str, NULL, 10);
72611 return 0;
72612}
72613
72614static int check_args_version(char *args, unsigned int our_major)
72615{
72616 unsigned int major = 0;
72617 int rv;
72618
72619 rv = version_from_args(args, &major, NULL, NULL);
72620 if (rv < 0) {
72621 log_error("check_args_version %s error %d", args, rv);
72622 return rv;
72623 }
72624
72625 if (major > our_major) {
72626 log_error("check_args_version %s major %u %u", args, major, our_major);
72627 return -1;
72628 }
72629
72630 return 0;
72631}
72632
72633#define MAX_LINE 64
72634
72635static int read_host_id_file(void)
72636{
72637 FILE *file;
72638 char line[MAX_LINE];
72639 char key_str[MAX_LINE];
72640 char val_str[MAX_LINE];
72641 char *key, *val, *sep;
72642 int host_id = 0;
72643
72644 file = fopen(daemon_host_id_file, "r");
72645 if (!file)
72646 goto out;
72647
72648 while (fgets(line, MAX_LINE, file)) {
72649 if (line[0] == '#' || line[0] == '\n')
72650 continue;
72651
72652 key = line;
72653 sep = strstr(line, "=");
72654 val = sep + 1;
72655
72656 if (!sep || !val)
72657 continue;
72658
72659 *sep = '\0';
72660 memset(key_str, 0, sizeof(key_str));
72661 memset(val_str, 0, sizeof(val_str));
72662 (void) sscanf(key, "%s", key_str);
72663 (void) sscanf(val, "%s", val_str);
72664
72665 if (!strcmp(key_str, "host_id")) {
72666 host_id = atoi(val_str);
72667 break;
72668 }
72669 }
72670 if (fclose(file))
72671 log_error("failed to close host id file %s", daemon_host_id_file);
72672out:
72673 log_debug("host_id %d from %s", host_id, daemon_host_id_file);
72674 return host_id;
72675}
72676
72677/*
72678 * vgcreate
72679 *
72680 * For init_vg, vgcreate passes the internal lv name as vg_args.
72681 * This constructs the full/proper vg_args format, containing the
72682 * version and lv name, and returns the real lock_args in vg_args.
72683 */
72684
72685int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
72686{
72687 struct sanlk_lockspace ss;
72688 struct sanlk_resourced rd;
72689 struct sanlk_disk disk;
72690 char lock_lv_name[MAX_ARGS+1];
72691 char lock_args_version[MAX_ARGS+1];
72692 const char *gl_name = NULL;
72693 uint32_t daemon_version;
72694 uint32_t daemon_proto;
72695 uint64_t offset;
72696 int align_size;
72697 int i, rv;
72698
72699 memset(&ss, 0, sizeof(ss));
72700 memset(&rd, 0, sizeof(rd));
72701 memset(&disk, 0, sizeof(disk));
72702 memset(lock_lv_name, 0, sizeof(lock_lv_name));
72703 memset(lock_args_version, 0, sizeof(lock_args_version));
72704
72705 if (!vg_args || !vg_args[0] || !strcmp(vg_args, "none")) {
72706 log_error("S %s init_vg_san vg_args missing", ls_name);
72707 return -EARGS;
72708 }
72709
72710 snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
72711 VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
72712
72713 /* see comment above about input vg_args being only lock_lv_name */
72714 snprintf(lock_lv_name, MAX_ARGS, "%s", vg_args);
72715
72716 if (strlen(lock_lv_name) + strlen(lock_args_version) + 2 > MAX_ARGS)
72717 return -EARGS;
72718
72719 snprintf(disk.path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
72720
72721 log_debug("S %s init_vg_san path %s", ls_name, disk.path);
72722
72723 if (daemon_test) {
72724 if (!gl_lsname_sanlock[0])
72725 strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
72726 snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
72727 return 0;
72728 }
72729
72730 rv = sanlock_version(0, &daemon_version, &daemon_proto);
72731 if (rv < 0) {
72732 log_error("S %s init_vg_san failed to connect to sanlock daemon", ls_name);
72733 return -EMANAGER;
72734 }
72735
72736 log_debug("sanlock daemon version %08x proto %08x",
72737 daemon_version, daemon_proto);
72738
72739 align_size = sanlock_align(&disk);
72740 if (align_size <= 0) {
72741 log_error("S %s init_vg_san bad disk align size %d %s",
72742 ls_name, align_size, disk.path);
72743 return -EARGS;
72744 }
72745
72746 strncpy(ss.name, ls_name, SANLK_NAME_LEN);
72747 memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
72748 ss.host_id_disk.offset = LS_BEGIN * align_size;
72749
72750 rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
72751 if (rv < 0) {
72752 log_error("S %s init_vg_san write_lockspace error %d %s",
72753 ls_name, rv, ss.host_id_disk.path);
72754 return rv;
72755 }
72756
72757 /*
72758 * We want to create the global lock in the first sanlock vg.
72759 * If other sanlock vgs exist, then one of them must contain
72760 * the gl. If gl_lsname_sanlock is not set, then perhaps
72761 * the sanlock vg with the gl has been removed or has not yet
72762 * been seen. (Would vgcreate get this far in that case?)
72763 * If dlm vgs exist, then we choose to use the dlm gl and
72764 * not a sanlock gl.
72765 */
72766
72767 if (flags & LD_AF_ENABLE)
72768 gl_name = R_NAME_GL;
72769 else if (flags & LD_AF_DISABLE)
72770 gl_name = R_NAME_GL_DISABLED;
72771 else if (!gl_use_sanlock || gl_lsname_sanlock[0] || !lockspaces_empty())
72772 gl_name = R_NAME_GL_DISABLED;
72773 else
72774 gl_name = R_NAME_GL;
72775
72776 memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
72777 strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
72778 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
72779 rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
72780 rd.rs.num_disks = 1;
72781
72782 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
72783 if (rv < 0) {
72784 log_error("S %s init_vg_san write_resource gl error %d %s",
72785 ls_name, rv, rd.rs.disks[0].path);
72786 return rv;
72787 }
72788
72789 memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
72790 strncpy(rd.rs.name, R_NAME_VG, SANLK_NAME_LEN);
72791 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
72792 rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
72793 rd.rs.num_disks = 1;
72794
72795 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
72796 if (rv < 0) {
72797 log_error("S %s init_vg_san write_resource vg error %d %s",
72798 ls_name, rv, rd.rs.disks[0].path);
72799 return rv;
72800 }
72801
72802 if (!strcmp(gl_name, R_NAME_GL))
72803 strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
72804
72805 snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
72806
72807 log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
72808
72809 /*
72810 * Go through all lv resource slots and initialize them with the
72811 * correct lockspace name but a special resource name that indicates
72812 * it is unused.
72813 */
72814
72815 memset(&rd, 0, sizeof(rd));
72816 rd.rs.num_disks = 1;
72817 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
72818 strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
72819 strcpy(rd.rs.name, "#unused");
72820
72821 offset = align_size * LV_LOCK_BEGIN;
72822
72823 log_debug("S %s init_vg_san clearing lv lease areas", ls_name);
72824
72825 for (i = 0; ; i++) {
72826 rd.rs.disks[0].offset = offset;
72827
72828 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
72829 if (rv == -EMSGSIZE || rv == -ENOSPC) {
72830 /* This indicates the end of the device is reached. */
72831 rv = -EMSGSIZE;
72832 break;
72833 }
72834
72835 if (rv) {
72836 log_error("clear lv resource area %llu error %d",
72837 (unsigned long long)offset, rv);
72838 break;
72839 }
72840 offset += align_size;
72841 }
72842
72843 return 0;
72844}
72845
72846/*
72847 * lvcreate
72848 *
72849 * The offset at which the lv lease is written is passed
72850 * all the way back to the lvcreate command so that it
72851 * can be saved in the lv's lock_args in the vg metadata.
72852 */
72853
72854int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
72855 char *vg_args, char *lv_args, uint64_t free_offset)
72856{
72857 struct sanlk_resourced rd;
72858 char lock_lv_name[MAX_ARGS+1];
72859 char lock_args_version[MAX_ARGS+1];
72860 uint64_t offset;
72861 int align_size;
72862 int rv;
72863
72864 memset(&rd, 0, sizeof(rd));
72865 memset(lock_lv_name, 0, sizeof(lock_lv_name));
72866 memset(lock_args_version, 0, sizeof(lock_args_version));
72867
72868 rv = lock_lv_name_from_args(vg_args, lock_lv_name);
72869 if (rv < 0) {
72870 log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
72871 ls_name, rv, vg_args);
72872 return rv;
72873 }
72874
72875 snprintf(lock_args_version, MAX_ARGS, "%u.%u.%u",
72876 LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
72877
72878 if (daemon_test) {
72879 align_size = 1048576;
72880 snprintf(lv_args, MAX_ARGS, "%s:%llu",
72881 lock_args_version,
72882 (unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
72883 daemon_test_lv_count++;
72884 return 0;
72885 }
72886
72887 strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
72888 rd.rs.num_disks = 1;
72889 snprintf(rd.rs.disks[0].path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
72890
72891 align_size = sanlock_align(&rd.rs.disks[0]);
72892 if (align_size <= 0) {
72893 log_error("S %s init_lv_san align error %d", ls_name, align_size);
72894 return -EINVAL;
72895 }
72896
72897 if (free_offset)
72898 offset = free_offset;
72899 else
72900 offset = align_size * LV_LOCK_BEGIN;
72901 rd.rs.disks[0].offset = offset;
72902
72903 while (1) {
72904 rd.rs.disks[0].offset = offset;
72905
72906 memset(rd.rs.name, 0, SANLK_NAME_LEN);
72907
72908 rv = sanlock_read_resource(&rd.rs, 0);
72909 if (rv == -EMSGSIZE || rv == -ENOSPC) {
72910 /* This indicates the end of the device is reached. */
72911 log_debug("S %s init_lv_san read limit offset %llu",
72912 ls_name, (unsigned long long)offset);
72913 rv = -EMSGSIZE;
72914 return rv;
72915 }
72916
72917 if (rv && rv != SANLK_LEADER_MAGIC) {
72918 log_error("S %s init_lv_san read error %d offset %llu",
72919 ls_name, rv, (unsigned long long)offset);
72920 break;
72921 }
72922
72923 if (!strncmp(rd.rs.name, lv_name, SANLK_NAME_LEN)) {
72924 log_error("S %s init_lv_san resource name %s already exists at %llu",
72925 ls_name, lv_name, (unsigned long long)offset);
72926 return -EEXIST;
72927 }
72928
72929 /*
72930 * If we read newly extended space, it will not be initialized
72931 * with an "#unused" resource, but will return SANLK_LEADER_MAGIC
72932 * indicating an uninitialized paxos structure on disk.
72933 */
72934 if ((rv == SANLK_LEADER_MAGIC) || !strcmp(rd.rs.name, "#unused")) {
72935 log_debug("S %s init_lv_san %s found unused area at %llu",
72936 ls_name, lv_name, (unsigned long long)offset);
72937
72938 strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
72939
72940 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
72941 if (!rv) {
72942 snprintf(lv_args, MAX_ARGS, "%s:%llu",
72943 lock_args_version, (unsigned long long)offset);
72944 } else {
72945 log_error("S %s init_lv_san write error %d offset %llu",
72946 ls_name, rv, (unsigned long long)rv);
72947 }
72948 break;
72949 }
72950
72951 offset += align_size;
72952 }
72953
72954 return rv;
72955}
72956
72957/*
72958 * Read the lockspace and each resource, replace the lockspace name,
72959 * and write it back.
72960 */
72961
72962int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
72963{
72964 struct sanlk_lockspace ss;
72965 struct sanlk_resourced rd;
72966 struct sanlk_disk disk;
72967 char lock_lv_name[MAX_ARGS+1];
72968 uint64_t offset;
72969 uint32_t io_timeout;
72970 int align_size;
72971 int i, rv;
72972
72973 memset(&disk, 0, sizeof(disk));
72974 memset(lock_lv_name, 0, sizeof(lock_lv_name));
72975
72976 if (!vg_args || !vg_args[0] || !strcmp(vg_args, "none")) {
72977 log_error("S %s rename_vg_san vg_args missing", ls_name);
72978 return -EINVAL;
72979 }
72980
72981 rv = lock_lv_name_from_args(vg_args, lock_lv_name);
72982 if (rv < 0) {
72983 log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
72984 ls_name, rv, vg_args);
72985 return rv;
72986 }
72987
72988 snprintf(disk.path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s", vg_name, lock_lv_name);
72989
72990 log_debug("S %s rename_vg_san path %s", ls_name, disk.path);
72991
72992 if (daemon_test)
72993 return 0;
72994
72995 /* FIXME: device is not always ready for us here */
72996 sleep(1);
72997
72998 align_size = sanlock_align(&disk);
72999 if (align_size <= 0) {
73000 log_error("S %s rename_vg_san bad align size %d %s",
73001 ls_name, align_size, disk.path);
73002 return -EINVAL;
73003 }
73004
73005 /*
73006 * Lockspace
73007 */
73008
73009 memset(&ss, 0, sizeof(ss));
73010 memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
73011 ss.host_id_disk.offset = LS_BEGIN * align_size;
73012
73013 rv = sanlock_read_lockspace(&ss, 0, &io_timeout);
73014 if (rv < 0) {
73015 log_error("S %s rename_vg_san read_lockspace error %d %s",
73016 ls_name, rv, ss.host_id_disk.path);
73017 return rv;
73018 }
73019
73020 strncpy(ss.name, ls_name, SANLK_NAME_LEN);
73021
73022 rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
73023 if (rv < 0) {
73024 log_error("S %s rename_vg_san write_lockspace error %d %s",
73025 ls_name, rv, ss.host_id_disk.path);
73026 return rv;
73027 }
73028
73029 /*
73030 * GL resource
73031 */
73032
73033 memset(&rd, 0, sizeof(rd));
73034 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
73035 rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
73036 rd.rs.num_disks = 1;
73037
73038 rv = sanlock_read_resource(&rd.rs, 0);
73039 if (rv < 0) {
73040 log_error("S %s rename_vg_san read_resource gl error %d %s",
73041 ls_name, rv, rd.rs.disks[0].path);
73042 return rv;
73043 }
73044
73045 strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
73046
73047 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
73048 if (rv < 0) {
73049 log_error("S %s rename_vg_san write_resource gl error %d %s",
73050 ls_name, rv, rd.rs.disks[0].path);
73051 return rv;
73052 }
73053
73054 /*
73055 * VG resource
73056 */
73057
73058 memset(&rd, 0, sizeof(rd));
73059 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
73060 rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
73061 rd.rs.num_disks = 1;
73062
73063 rv = sanlock_read_resource(&rd.rs, 0);
73064 if (rv < 0) {
73065 log_error("S %s rename_vg_san write_resource vg error %d %s",
73066 ls_name, rv, rd.rs.disks[0].path);
73067 return rv;
73068 }
73069
73070 strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
73071
73072 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
73073 if (rv < 0) {
73074 log_error("S %s rename_vg_san write_resource vg error %d %s",
73075 ls_name, rv, rd.rs.disks[0].path);
73076 return rv;
73077 }
73078
73079 /*
73080 * LV resources
73081 */
73082
73083 offset = align_size * LV_LOCK_BEGIN;
73084
73085 for (i = 0; ; i++) {
73086 memset(&rd, 0, sizeof(rd));
73087 memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
73088 rd.rs.disks[0].offset = offset;
73089 rd.rs.num_disks = 1;
73090
73091 rv = sanlock_read_resource(&rd.rs, 0);
73092 if (rv == -EMSGSIZE || rv == -ENOSPC) {
73093 /* This indicates the end of the device is reached. */
73094 rv = -EMSGSIZE;
73095 break;
73096 }
73097
73098 if (rv < 0) {
73099 log_error("S %s rename_vg_san read_resource resource area %llu error %d",
73100 ls_name, (unsigned long long)offset, rv);
73101 break;
73102 }
73103
73104 strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
73105
73106 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
73107 if (rv) {
73108 log_error("S %s rename_vg_san write_resource resource area %llu error %d",
73109 ls_name, (unsigned long long)offset, rv);
73110 break;
73111 }
73112 offset += align_size;
73113 }
73114
73115 return 0;
73116}
73117
73118/* lvremove */
73119int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
73120{
73121 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
73122 struct sanlk_resource *rs = &rds->rs;
73123 int rv;
73124
73125 log_debug("S %s R %s free_lv_san", ls->name, r->name);
73126
73127 if (daemon_test)
73128 return 0;
73129
73130 strcpy(rs->name, "#unused");
73131
73132 rv = sanlock_write_resource(rs, 0, 0, 0);
73133 if (rv < 0) {
73134 log_error("S %s R %s free_lv_san write error %d",
73135 ls->name, r->name, rv);
73136 }
73137
73138 return rv;
73139}
73140
73141int lm_ex_disable_gl_sanlock(struct lockspace *ls)
73142{
73143 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73144 struct sanlk_resourced rd1;
73145 struct sanlk_resourced rd2;
73146 struct sanlk_resource *rs1;
73147 struct sanlk_resource *rs2;
73148 struct sanlk_resource **rs_args;
73149 int rv;
73150
73151 if (daemon_test)
73152 return 0;
73153
73154 rs_args = malloc(2 * sizeof(struct sanlk_resource *));
73155 if (!rs_args)
73156 return -ENOMEM;
73157
73158 rs1 = &rd1.rs;
73159 rs2 = &rd2.rs;
73160
73161 memset(&rd1, 0, sizeof(rd1));
73162 memset(&rd2, 0, sizeof(rd2));
73163
73164 strncpy(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73165 strncpy(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN);
73166
73167 strncpy(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73168 strncpy(rd2.rs.name, R_NAME_GL_DISABLED, SANLK_NAME_LEN);
73169
73170 rd1.rs.num_disks = 1;
73171 strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
73172 rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
73173
73174 rv = sanlock_acquire(lms->sock, -1, 0, 1, &rs1, NULL);
73175 if (rv < 0) {
73176 log_error("S %s ex_disable_gl_san acquire error %d",
73177 ls->name, rv);
73178 goto out;
73179 }
73180
73181 rs_args[0] = rs1;
73182 rs_args[1] = rs2;
73183
73184 rv = sanlock_release(lms->sock, -1, SANLK_REL_RENAME, 2, rs_args);
73185 if (rv < 0) {
73186 log_error("S %s ex_disable_gl_san release_rename error %d",
73187 ls->name, rv);
73188 }
73189
73190out:
73191 free(rs_args);
73192 return rv;
73193}
73194
73195/*
73196 * enable/disable exist because each vg contains a global lock,
73197 * but we only want to use the gl from one of them. The first
73198 * sanlock vg created, has its gl enabled, and subsequent
73199 * sanlock vgs have their gl disabled. If the vg containing the
73200 * gl is removed, the gl from another sanlock vg needs to be
73201 * enabled. Or, if gl in multiple vgs are somehow enabled, we
73202 * want to be able to disable one of them.
73203 *
73204 * Disable works by naming/renaming the gl resource to have a
73205 * name that is different from the predefined name.
73206 * When a host attempts to acquire the gl with its standard
73207 * predefined name, it will fail because the resource's name
73208 * on disk doesn't match.
73209 */
73210
73211int lm_able_gl_sanlock(struct lockspace *ls, int enable)
73212{
73213 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73214 struct sanlk_resourced rd;
73215 const char *gl_name;
73216 int rv;
73217
73218 if (enable)
73219 gl_name = R_NAME_GL;
73220 else
73221 gl_name = R_NAME_GL_DISABLED;
73222
73223 if (daemon_test)
73224 goto out;
73225
73226 memset(&rd, 0, sizeof(rd));
73227
73228 strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73229 strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
73230
73231 rd.rs.num_disks = 1;
73232 strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
73233 rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
73234
73235 rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
73236 if (rv < 0) {
73237 log_error("S %s able_gl %d write_resource gl error %d %s",
73238 ls->name, enable, rv, rd.rs.disks[0].path);
73239 return rv;
73240 }
73241out:
73242 log_debug("S %s able_gl %s", ls->name, gl_name);
73243
73244 ls->sanlock_gl_enabled = enable;
73245
73246 if (enable)
73247 strncpy(gl_lsname_sanlock, ls->name, MAX_NAME);
73248
73249 if (!enable && !strcmp(gl_lsname_sanlock, ls->name))
73250 memset(gl_lsname_sanlock, 0, sizeof(gl_lsname_sanlock));
73251
73252 return 0;
73253}
73254
73255static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
73256{
73257 char strname[SANLK_NAME_LEN + 1];
73258 struct sanlk_resourced rd;
73259 uint64_t offset;
73260 int rv;
73261
73262 if (daemon_test)
73263 return 1;
73264
73265 memset(&rd, 0, sizeof(rd));
73266
73267 strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73268
73269 /* leave rs.name empty, it is what we're checking */
73270
73271 rd.rs.num_disks = 1;
73272 strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
73273
73274 offset = lms->align_size * GL_LOCK_BEGIN;
73275 rd.rs.disks[0].offset = offset;
73276
73277 rv = sanlock_read_resource(&rd.rs, 0);
73278 if (rv < 0) {
73279 log_error("gl_is_enabled read_resource error %d", rv);
73280 return rv;
73281 }
73282
73283 memset(strname, 0, sizeof(strname));
73284 memcpy(strname, rd.rs.name, SANLK_NAME_LEN);
73285
73286 if (!strcmp(strname, R_NAME_GL_DISABLED)) {
73287 return 0;
73288 }
73289
73290 if (!strcmp(strname, R_NAME_GL)) {
73291 return 1;
73292 }
73293
73294 log_error("gl_is_enabled invalid gl name %s", strname);
73295 return -1;
73296}
73297
73298int lm_gl_is_enabled(struct lockspace *ls)
73299{
73300 int rv;
73301 rv = gl_is_enabled(ls, ls->lm_data);
73302 ls->sanlock_gl_enabled = rv;
73303 return rv;
73304}
73305
73306/*
73307 * This is called at the beginning of lvcreate to
73308 * ensure there is free space for a new LV lock.
73309 * If not, lvcreate will extend the lvmlock lv
73310 * before continuing with creating the new LV.
73311 * This way, lm_init_lv_san() should find a free
73312 * lock (unless the autoextend of lvmlock lv has
73313 * been disabled.)
73314 */
73315
73316int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
73317{
73318 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73319 struct sanlk_resourced rd;
73320 uint64_t offset;
73321 int rv;
73322
73323 if (daemon_test) {
73324 *free_offset = (1048576 * LV_LOCK_BEGIN) + (1048576 * (daemon_test_lv_count + 1));
73325 return 0;
73326 }
73327
73328 memset(&rd, 0, sizeof(rd));
73329
73330 strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73331 rd.rs.num_disks = 1;
73332 strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
73333
73334 offset = lms->align_size * LV_LOCK_BEGIN;
73335
73336 while (1) {
73337 rd.rs.disks[0].offset = offset;
73338
73339 memset(rd.rs.name, 0, SANLK_NAME_LEN);
73340
73341 rv = sanlock_read_resource(&rd.rs, 0);
73342 if (rv == -EMSGSIZE || rv == -ENOSPC) {
73343 /* This indicates the end of the device is reached. */
73344 log_debug("S %s find_free_lock_san read limit offset %llu",
73345 ls->name, (unsigned long long)offset);
73346 return -EMSGSIZE;
73347 }
73348
73349 /*
73350 * If we read newly extended space, it will not be initialized
73351 * with an "#unused" resource, but will return an error about
73352 * an invalid paxos structure on disk.
73353 */
73354 if (rv == SANLK_LEADER_MAGIC) {
73355 log_debug("S %s find_free_lock_san found empty area at %llu",
73356 ls->name, (unsigned long long)offset);
73357 *free_offset = offset;
73358 return 0;
73359 }
73360
73361 if (rv) {
73362 log_error("S %s find_free_lock_san read error %d offset %llu",
73363 ls->name, rv, (unsigned long long)offset);
73364 break;
73365 }
73366
73367 if (!strcmp(rd.rs.name, "#unused")) {
73368 log_debug("S %s find_free_lock_san found unused area at %llu",
73369 ls->name, (unsigned long long)offset);
73370 *free_offset = offset;
73371 return 0;
73372 }
73373
73374 offset += lms->align_size;
73375 }
73376
73377 return rv;
73378}
73379
73380/*
73381 * host A: start_vg/add_lockspace
73382 * host B: vgremove
73383 *
73384 * The global lock cannot always be held around start_vg
73385 * on host A because the gl is in a vg that may not be
73386 * started yet, or may be in the vg we are starting.
73387 *
73388 * If B removes the vg, destroying the delta leases,
73389 * while A is a lockspace member, it will cause A's
73390 * sanlock delta lease renewal to fail, and lockspace
73391 * recovery.
73392 *
73393 * I expect this overlap would usually cause a failure
73394 * in the add_lockspace() on host A when it sees that
73395 * the lockspace structures have been clobbered by B.
73396 * Having add_lockspace() fail should be a fine result.
73397 *
73398 * If add_lockspace was somehow able to finish, the
73399 * subsequent renewal would probably fail instead.
73400 * This should also not create any major problems.
73401 */
73402
73403int lm_prepare_lockspace_sanlock(struct lockspace *ls)
73404{
73405 struct stat st;
73406 struct lm_sanlock *lms = NULL;
73407 char lock_lv_name[MAX_ARGS+1];
73408 char lsname[SANLK_NAME_LEN + 1];
73409 char disk_path[SANLK_PATH_LEN];
73410 char killpath[SANLK_PATH_LEN];
73411 char killargs[SANLK_PATH_LEN];
73412 int gl_found;
73413 int ret, rv;
73414
73415 memset(disk_path, 0, sizeof(disk_path));
73416 memset(lock_lv_name, 0, sizeof(lock_lv_name));
73417
73418 /*
73419 * Construct the path to lvmlockctl by using the path to the lvm binary
73420 * and appending "lockctl" to get /path/to/lvmlockctl.
73421 */
73422 memset(killpath, 0, sizeof(killpath));
73423 snprintf(killpath, SANLK_PATH_LEN - 1, "%slockctl", LVM_PATH);
73424
73425 memset(killargs, 0, sizeof(killargs));
73426 snprintf(killargs, SANLK_PATH_LEN - 1, "--kill %s", ls->vg_name);
73427
73428 rv = check_args_version(ls->vg_args, VG_LOCK_ARGS_MAJOR);
73429 if (rv < 0) {
73430 ret = -EARGS;
73431 goto fail;
73432 }
73433
73434 rv = lock_lv_name_from_args(ls->vg_args, lock_lv_name);
73435 if (rv < 0) {
73436 log_error("S %s prepare_lockspace_san lock_lv_name_from_args error %d %s",
73437 ls->name, rv, ls->vg_args);
73438 ret = -EARGS;
73439 goto fail;
73440 }
73441
73442 snprintf(disk_path, SANLK_PATH_LEN-1, "/dev/mapper/%s-%s",
73443 ls->vg_name, lock_lv_name);
73444
73445 /*
73446 * When a vg is started, the internal sanlock lv should be
73447 * activated before lvmlockd is asked to add the lockspace.
73448 * (sanlock needs to use the lv.)
73449 *
73450 * In the future we might be able to ask something on the system
73451 * to activate the sanlock lv from here, and with that we might be
73452 * able to start sanlock VGs without requiring a
73453 * vgchange --lock-start command.
73454 */
73455
73456 /* FIXME: device is not always ready for us here */
73457 sleep(1);
73458
73459 rv = stat(disk_path, &st);
73460 if (rv < 0) {
73461 log_error("S %s prepare_lockspace_san stat error %d disk_path %s",
73462 ls->name, errno, disk_path);
73463 ret = -EARGS;
73464 goto fail;
73465 }
73466
73467 if (!ls->host_id) {
73468 if (daemon_host_id)
73469 ls->host_id = daemon_host_id;
73470 else if (daemon_host_id_file)
73471 ls->host_id = read_host_id_file();
73472 }
73473
73474 if (!ls->host_id || ls->host_id > 2000) {
73475 log_error("S %s prepare_lockspace_san invalid host_id %llu",
73476 ls->name, (unsigned long long)ls->host_id);
73477 ret = -EHOSTID;
73478 goto fail;
73479 }
73480
73481 lms = malloc(sizeof(struct lm_sanlock));
73482 if (!lms) {
73483 ret = -ENOMEM;
73484 goto fail;
73485 }
73486
73487 memset(lsname, 0, sizeof(lsname));
73488 strncpy(lsname, ls->name, SANLK_NAME_LEN);
73489
73490 memset(lms, 0, sizeof(struct lm_sanlock));
73491 memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
73492 lms->ss.host_id_disk.offset = 0;
73493 lms->ss.host_id = ls->host_id;
73494 strncpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
73495
73496 if (daemon_test) {
73497 if (!gl_lsname_sanlock[0]) {
73498 strncpy(gl_lsname_sanlock, lsname, MAX_NAME);
73499 log_debug("S %s prepare_lockspace_san use global lock", lsname);
73500 }
73501 goto out;
73502 }
73503
73504 lms->sock = sanlock_register();
73505 if (lms->sock < 0) {
73506 log_error("S %s prepare_lockspace_san register error %d", lsname, lms->sock);
73507 lms->sock = 0;
73508 ret = -EMANAGER;
73509 goto fail;
73510 }
73511
73512 log_debug("set killpath to %s %s", killpath, killargs);
73513
73514 rv = sanlock_killpath(lms->sock, 0, killpath, killargs);
73515 if (rv < 0) {
73516 log_error("S %s killpath error %d", lsname, rv);
73517 ret = -EMANAGER;
73518 goto fail;
73519 }
73520
73521 rv = sanlock_restrict(lms->sock, SANLK_RESTRICT_SIGKILL);
73522 if (rv < 0) {
73523 log_error("S %s restrict error %d", lsname, rv);
73524 ret = -EMANAGER;
73525 goto fail;
73526 }
73527
73528 lms->align_size = sanlock_align(&lms->ss.host_id_disk);
73529 if (lms->align_size <= 0) {
73530 log_error("S %s prepare_lockspace_san align error %d", lsname, lms->align_size);
73531 ret = -EMANAGER;
73532 goto fail;
73533 }
73534
73535 gl_found = gl_is_enabled(ls, lms);
73536 if (gl_found < 0) {
73537 log_error("S %s prepare_lockspace_san gl_enabled error %d", lsname, gl_found);
73538 ret = -EARGS;
73539 goto fail;
73540 }
73541
73542 ls->sanlock_gl_enabled = gl_found;
73543
73544 if (gl_found) {
73545 if (gl_use_dlm) {
73546 log_error("S %s prepare_lockspace_san gl_use_dlm is set", lsname);
73547 } else if (gl_lsname_sanlock[0] && strcmp(gl_lsname_sanlock, lsname)) {
73548 log_error("S %s prepare_lockspace_san multiple sanlock global locks current %s",
73549 lsname, gl_lsname_sanlock);
73550 } else {
73551 strncpy(gl_lsname_sanlock, lsname, MAX_NAME);
73552 log_debug("S %s prepare_lockspace_san use global lock %s",
73553 lsname, gl_lsname_sanlock);
73554 }
73555 }
73556
73557out:
73558 ls->lm_data = lms;
73559 log_debug("S %s prepare_lockspace_san done", lsname);
73560 return 0;
73561
73562fail:
73563 if (lms && lms->sock)
73564 close(lms->sock);
73565 if (lms)
73566 free(lms);
73567 return ret;
73568}
73569
73570int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
73571{
73572 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73573 int rv;
73574
73575 if (daemon_test) {
73576 sleep(2);
73577 goto out;
73578 }
73579
73580 rv = sanlock_add_lockspace_timeout(&lms->ss, 0, sanlock_io_timeout);
73581 if (rv == -EEXIST && adopt) {
73582 /* We could alternatively just skip the sanlock call for adopt. */
73583 log_debug("S %s add_lockspace_san adopt found ls", ls->name);
73584 goto out;
73585 }
73586 if (rv < 0) {
73587 /* retry for some errors? */
73588 log_error("S %s add_lockspace_san add_lockspace error %d", ls->name, rv);
73589 goto fail;
73590 }
73591
73592 /*
73593 * Don't let the lockspace be cleanly released if orphan locks
73594 * exist, because the orphan locks are still protecting resources
73595 * that are being used on the host, e.g. active lvs. If the
73596 * lockspace is cleanly released, another host could acquire the
73597 * orphan leases.
73598 */
73599
73600 rv = sanlock_set_config(ls->name, 0, SANLK_CONFIG_USED_BY_ORPHANS, NULL);
73601 if (rv < 0) {
73602 log_error("S %s add_lockspace_san set_config error %d", ls->name, rv);
73603 sanlock_rem_lockspace(&lms->ss, 0);
73604 goto fail;
73605 }
73606
73607out:
73608 log_debug("S %s add_lockspace_san done", ls->name);
73609 return 0;
73610
73611fail:
73612 if (close(lms->sock))
73613 log_error("failed to close sanlock daemon socket connection");
73614 free(lms);
73615 ls->lm_data = NULL;
73616 return rv;
73617}
73618
73619int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
73620{
73621 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73622 int rv;
73623
73624 if (daemon_test)
73625 goto out;
73626
73627 rv = sanlock_rem_lockspace(&lms->ss, 0);
73628 if (rv < 0) {
73629 log_error("S %s rem_lockspace_san error %d", ls->name, rv);
73630 return rv;
73631 }
73632
73633 if (free_vg) {
73634 /*
73635 * Destroy sanlock lockspace (delta leases). Forces failure for any
73636 * other host that is still using or attempts to use this lockspace.
73637 * This shouldn't be generally necessary, but there may some races
73638 * between nodes starting and removing a vg which this could help.
73639 */
73640 strncpy(lms->ss.name, "#unused", SANLK_NAME_LEN);
73641
73642 rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout);
73643 if (rv < 0) {
73644 log_error("S %s rem_lockspace free_vg write_lockspace error %d %s",
73645 ls->name, rv, lms->ss.host_id_disk.path);
73646 }
73647 }
73648
73649 if (close(lms->sock))
73650 log_error("failed to close sanlock daemon socket connection");
73651out:
73652 free(lms);
73653 ls->lm_data = NULL;
73654
73655 /* FIXME: should we only clear gl_lsname when doing free_vg? */
73656
73657 if (!strcmp(ls->name, gl_lsname_sanlock))
73658 memset(gl_lsname_sanlock, 0, sizeof(gl_lsname_sanlock));
73659
73660 return 0;
73661}
73662
73663static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
73664{
73665 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73666 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
73667
73668 strncpy(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
73669 strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
73670 rds->rs.num_disks = 1;
73671 memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
73672
73673 if (r->type == LD_RT_GL)
73674 rds->rs.disks[0].offset = GL_LOCK_BEGIN * lms->align_size;
73675 else if (r->type == LD_RT_VG)
73676 rds->rs.disks[0].offset = VG_LOCK_BEGIN * lms->align_size;
73677
73678 /* LD_RT_LV offset is set in each lm_lock call from lv_args. */
73679
73680 if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
73681 rds->vb = malloc(sizeof(struct val_blk));
73682 if (!rds->vb)
73683 return -ENOMEM;
73684 memset(rds->vb, 0, sizeof(struct val_blk));
73685 }
73686
73687 return 0;
73688}
73689
73690int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
73691{
73692 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
73693
73694 /* FIXME: assert r->mode == UN or unlock if it's not? */
73695
73696 if (rds->vb)
73697 free(rds->vb);
73698
73699 memset(rds, 0, sizeof(struct rd_sanlock));
73700 r->lm_init = 0;
73701 return 0;
73702}
73703
73704int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
73705 struct val_blk *vb_out, int *retry, int adopt)
73706{
73707 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73708 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
73709 struct sanlk_resource *rs;
73710 struct sanlk_options opt;
73711 uint64_t lock_lv_offset;
73712 uint32_t flags = 0;
73713 struct val_blk vb;
73714 int added = 0;
73715 int rv;
73716
73717 if (!r->lm_init) {
73718 rv = lm_add_resource_sanlock(ls, r);
73719 if (rv < 0)
73720 return rv;
73721 r->lm_init = 1;
73722 added = 1;
73723 }
73724
73725 rs = &rds->rs;
73726
73727 /*
73728 * While there are duplicate global locks, keep checking
73729 * to see if any have been disabled.
73730 */
73731 if (sanlock_gl_dup && ls->sanlock_gl_enabled &&
73732 (r->type == LD_RT_GL || r->type == LD_RT_VG))
73733 ls->sanlock_gl_enabled = gl_is_enabled(ls, ls->lm_data);
73734
73735 if (r->type == LD_RT_LV) {
73736 /*
73737 * The lv may have been removed and recreated with a new lease
73738 * offset, so we need to get the offset from lv_args each time
73739 * instead of reusing the value that we last set in rds->rs.
73740 * act->lv_args is copied to r->lv_args before every lm_lock().
73741 */
73742
73743 rv = check_args_version(r->lv_args, LV_LOCK_ARGS_MAJOR);
73744 if (rv < 0) {
73745 log_error("S %s R %s lock_san wrong lv_args version %s",
73746 ls->name, r->name, r->lv_args);
73747 return rv;
73748 }
73749
73750 rv = lock_lv_offset_from_args(r->lv_args, &lock_lv_offset);
73751 if (rv < 0) {
73752 log_error("S %s R %s lock_san lv_offset_from_args error %d %s",
73753 ls->name, r->name, rv, r->lv_args);
73754 return rv;
73755 }
73756
73757 if (!added && (rds->rs.disks[0].offset != lock_lv_offset)) {
73758 log_debug("S %s R %s lock_san offset old %llu new %llu",
73759 ls->name, r->name,
73760 (unsigned long long)rds->rs.disks[0].offset,
73761 (unsigned long long)lock_lv_offset);
73762 }
73763
73764 rds->rs.disks[0].offset = lock_lv_offset;
73765 }
73766
73767 if (ld_mode == LD_LK_SH) {
73768 rs->flags |= SANLK_RES_SHARED;
73769 } else if (ld_mode == LD_LK_EX) {
73770 rs->flags &= ~SANLK_RES_SHARED;
73771 } else {
73772 log_error("lock_san invalid mode %d", ld_mode);
73773 return -EINVAL;
73774 }
73775
73776 /*
73777 * Use PERSISTENT because if lvmlockd exits while holding
73778 * a lock, it's not safe to simply clear/drop the lock while
73779 * a command or lv is using it.
73780 */
73781
73782 rs->flags |= SANLK_RES_PERSISTENT;
73783
73784 log_debug("S %s R %s lock_san %s at %s:%llu",
73785 ls->name, r->name, mode_str(ld_mode), rs->disks[0].path,
73786 (unsigned long long)rs->disks[0].offset);
73787
73788 if (daemon_test) {
73789 if (rds->vb) {
73790 vb_out->version = le16_to_cpu(rds->vb->version);
73791 vb_out->flags = le16_to_cpu(rds->vb->flags);
73792 vb_out->r_version = le32_to_cpu(rds->vb->r_version);
73793 }
73794 return 0;
73795 }
73796
73797 if (rds->vb)
73798 flags |= SANLK_ACQUIRE_LVB;
73799 if (adopt)
73800 flags |= SANLK_ACQUIRE_ORPHAN_ONLY;
73801
73802 /*
73803 * Don't block waiting for a failed lease to expire since it causes
73804 * sanlock_acquire to block for a long time, which would prevent this
73805 * thread from processing other lock requests.
73806 */
73807 flags |= SANLK_ACQUIRE_OWNER_NOWAIT;
73808
73809 memset(&opt, 0, sizeof(opt));
73810 sprintf(opt.owner_name, "%s", "lvmlockd");
73811
73812 rv = sanlock_acquire(lms->sock, -1, flags, 1, &rs, &opt);
73813
73814 if (rv == -EAGAIN) {
73815 /*
73816 * It appears that sanlock_acquire returns EAGAIN when we request
73817 * a shared lock but the lock is held ex by another host.
73818 * There's no point in retrying this case, just return an error.
73819 */
73820 log_debug("S %s R %s lock_san acquire mode %d rv EAGAIN", ls->name, r->name, ld_mode);
73821 *retry = 0;
73822 return -EAGAIN;
73823 }
73824
73825 if ((rv == -EMSGSIZE) && (r->type == LD_RT_LV)) {
73826 /*
73827 * sanlock tried to read beyond the end of the device,
73828 * so the offset of the lv lease is beyond the end of the
73829 * device, which means that the lease lv was extended, and
73830 * the lease for this lv was allocated in the new space.
73831 * The lvm command will see this error, refresh the lvmlock
73832 * lv, and try again.
73833 */
73834 log_debug("S %s R %s lock_san acquire offset %llu rv EMSGSIZE",
73835 ls->name, r->name, (unsigned long long)rs->disks[0].offset);
73836 *retry = 0;
73837 return -EMSGSIZE;
73838 }
73839
73840 if (adopt && (rv == -EUCLEAN)) {
73841 /*
73842 * The orphan lock exists but in a different mode than we asked
73843 * for, so the caller should try again with the other mode.
73844 */
73845 log_debug("S %s R %s lock_san adopt mode %d try other mode",
73846 ls->name, r->name, ld_mode);
73847 *retry = 0;
73848 return -EUCLEAN;
73849 }
73850
73851 if (adopt && (rv == -ENOENT)) {
73852 /*
73853 * No orphan lock exists.
73854 */
73855 log_debug("S %s R %s lock_san adopt mode %d no orphan found",
73856 ls->name, r->name, ld_mode);
73857 *retry = 0;
73858 return -ENOENT;
73859 }
73860
73861 if (rv == SANLK_ACQUIRE_IDLIVE || rv == SANLK_ACQUIRE_OWNED || rv == SANLK_ACQUIRE_OTHER) {
73862 /*
73863 * The lock is held by another host. These failures can
73864 * happen while multiple hosts are concurrently acquiring
73865 * shared locks. We want to retry a couple times in this
73866 * case because we'll probably get the sh lock.
73867 *
73868 * I believe these are also the errors when requesting an
73869 * ex lock that another host holds ex. We want to report
73870 * something like: "lock is held by another host" in this case.
73871 * Retry is pointless here.
73872 *
73873 * We can't distinguish between the two cases above,
73874 * so if requesting a sh lock, retry a couple times,
73875 * otherwise don't.
73876 */
73877 log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
73878 *retry = (ld_mode == LD_LK_SH) ? 1 : 0;
73879 return -EAGAIN;
73880 }
73881
73882 if (rv == SANLK_ACQUIRE_OWNED_RETRY) {
73883 /*
73884 * The lock is held by a failed host, and will eventually
73885 * expire. If we retry we'll eventually acquire the lock
73886 * (or find someone else has acquired it). The EAGAIN retry
73887 * attempts for SH locks above would not be sufficient for
73888 * the length of expiration time. We could add a longer
73889 * retry time here to cover the full expiration time and block
73890 * the activation command for that long. For now just return
73891 * the standard error indicating that another host still owns
73892 * the lease. FIXME: return a different error number so the
73893 * command can print an different error indicating that the
73894 * owner of the lease is in the process of expiring?
73895 */
73896 log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
73897 *retry = 0;
73898 return -EAGAIN;
73899 }
73900
73901 if (rv < 0) {
73902 log_error("S %s R %s lock_san acquire error %d",
73903 ls->name, r->name, rv);
73904
73905 /* if the gl has been disabled, remove and free the gl resource */
73906 if ((rv == SANLK_LEADER_RESOURCE) && (r->type == LD_RT_GL)) {
73907 if (!lm_gl_is_enabled(ls)) {
73908 log_error("S %s R %s lock_san gl has been disabled",
73909 ls->name, r->name);
73910 if (!strcmp(gl_lsname_sanlock, ls->name))
73911 memset(gl_lsname_sanlock, 0, sizeof(gl_lsname_sanlock));
73912 return -EUNATCH;
73913 }
73914 }
73915
73916 if (added)
73917 lm_rem_resource_sanlock(ls, r);
73918
73919 /* sanlock gets i/o errors trying to read/write the leases. */
73920 if (rv == -EIO)
73921 rv = -ELOCKIO;
73922
73923 /*
73924 * The sanlock lockspace can disappear if the lease storage fails,
73925 * the delta lease renewals fail, the lockspace enters recovery,
73926 * lvmlockd holds no leases in the lockspace, so sanlock can
73927 * stop and free the lockspace.
73928 */
73929 if (rv == -ENOSPC)
73930 rv = -ELOCKIO;
73931
73932 return rv;
73933 }
73934
73935 if (rds->vb) {
73936 rv = sanlock_get_lvb(0, rs, (char *)&vb, sizeof(vb));
73937 if (rv < 0) {
73938 log_error("S %s R %s lock_san get_lvb error %d", ls->name, r->name, rv);
73939 memset(rds->vb, 0, sizeof(struct val_blk));
73940 memset(vb_out, 0, sizeof(struct val_blk));
73941 goto out;
73942 }
73943
73944 /*
73945 * 'vb' contains disk endian values, not host endian.
73946 * It is copied directly to rrs->vb which is also kept
73947 * in disk endian form.
73948 * vb_out is returned to the caller in host endian form.
73949 */
73950
73951 memcpy(rds->vb, &vb, sizeof(vb));
73952
73953 vb_out->version = le16_to_cpu(vb.version);
73954 vb_out->flags = le16_to_cpu(vb.flags);
73955 vb_out->r_version = le32_to_cpu(vb.r_version);
73956 }
73957out:
73958 return rv;
73959}
73960
73961int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
73962 int ld_mode, uint32_t r_version)
73963{
73964 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
73965 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
73966 struct sanlk_resource *rs = &rds->rs;
73967 struct val_blk vb;
73968 uint32_t flags = 0;
73969 int rv;
73970
73971 log_debug("S %s R %s convert_san %s to %s",
73972 ls->name, r->name, mode_str(r->mode), mode_str(ld_mode));
73973
73974 if (daemon_test)
73975 goto rs_flag;
73976
73977 if (rds->vb && r_version && (r->mode == LD_LK_EX)) {
73978 if (!rds->vb->version) {
73979 /* first time vb has been written */
73980 rds->vb->version = cpu_to_le16(VAL_BLK_VERSION);
73981 }
73982 if (r_version)
73983 rds->vb->r_version = cpu_to_le32(r_version);
73984 memcpy(&vb, rds->vb, sizeof(vb));
73985
73986 log_debug("S %s R %s convert_san set r_version %u",
73987 ls->name, r->name, r_version);
73988
73989 rv = sanlock_set_lvb(0, rs, (char *)&vb, sizeof(vb));
73990 if (rv < 0) {
73991 log_error("S %s R %s convert_san set_lvb error %d",
73992 ls->name, r->name, rv);
73993 }
73994 }
73995
73996 rs_flag:
73997 if (ld_mode == LD_LK_SH)
73998 rs->flags |= SANLK_RES_SHARED;
73999 else
74000 rs->flags &= ~SANLK_RES_SHARED;
74001
74002 if (daemon_test)
74003 return 0;
74004
74005 rv = sanlock_convert(lms->sock, -1, flags, rs);
74006 if (rv == -EAGAIN) {
74007 /* FIXME: When could this happen? Should something different be done? */
74008 log_error("S %s R %s convert_san EAGAIN", ls->name, r->name);
74009 return -EAGAIN;
74010 }
74011 if (rv < 0) {
74012 log_error("S %s R %s convert_san convert error %d", ls->name, r->name, rv);
74013 }
74014
74015 return rv;
74016}
74017
74018static int release_rename(struct lockspace *ls, struct resource *r)
74019{
74020 struct rd_sanlock rd1;
74021 struct rd_sanlock rd2;
74022 struct sanlk_resource *res1;
74023 struct sanlk_resource *res2;
74024 struct sanlk_resource **res_args;
74025 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
74026 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
74027 int rv;
74028
74029 log_debug("S %s R %s release rename", ls->name, r->name);
74030
74031 res_args = malloc(2 * sizeof(struct sanlk_resource *));
74032 if (!res_args)
74033 return -ENOMEM;
74034
74035 memcpy(&rd1, rds, sizeof(struct rd_sanlock));
74036 memcpy(&rd2, rds, sizeof(struct rd_sanlock));
74037
74038 res1 = (struct sanlk_resource *)&rd1;
74039 res2 = (struct sanlk_resource *)&rd2;
74040
74041 strcpy(res2->name, "invalid_removed");
74042
74043 res_args[0] = res1;
74044 res_args[1] = res2;
74045
74046 rv = sanlock_release(lms->sock, -1, SANLK_REL_RENAME, 2, res_args);
74047 if (rv < 0) {
74048 log_error("S %s R %s unlock_san release rename error %d", ls->name, r->name, rv);
74049 }
74050
74051 free(res_args);
74052
74053 return rv;
74054}
74055
74056/*
74057 * rds->vb is stored in le
74058 *
74059 * r_version is r->version
74060 *
74061 * for GL locks lvmlockd just increments this value
74062 * each time the global lock is released from ex.
74063 *
74064 * for VG locks it is the seqno from the vg metadata.
74065 */
74066
74067int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
74068 uint32_t r_version, uint32_t lmu_flags)
74069{
74070 struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
74071 struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
74072 struct sanlk_resource *rs = &rds->rs;
74073 struct val_blk vb;
74074 int rv;
74075
74076 log_debug("S %s R %s unlock_san %s r_version %u flags %x",
74077 ls->name, r->name, mode_str(r->mode), r_version, lmu_flags);
74078
74079 if (daemon_test) {
74080 if (rds->vb && r_version && (r->mode == LD_LK_EX)) {
74081 if (!rds->vb->version)
74082 rds->vb->version = cpu_to_le16(VAL_BLK_VERSION);
74083 if (r_version)
74084 rds->vb->r_version = cpu_to_le32(r_version);
74085 }
74086 return 0;
74087 }
74088
74089 if (rds->vb && r_version && (r->mode == LD_LK_EX)) {
74090 if (!rds->vb->version) {
74091 /* first time vb has been written */
74092 rds->vb->version = cpu_to_le16(VAL_BLK_VERSION);
74093 }
74094 if (r_version)
74095 rds->vb->r_version = cpu_to_le32(r_version);
74096 memcpy(&vb, rds->vb, sizeof(vb));
74097
74098 log_debug("S %s R %s unlock_san set r_version %u",
74099 ls->name, r->name, r_version);
74100
74101 rv = sanlock_set_lvb(0, rs, (char *)&vb, sizeof(vb));
74102 if (rv < 0) {
74103 log_error("S %s R %s unlock_san set_lvb error %d",
74104 ls->name, r->name, rv);
74105 }
74106 }
74107
74108 /*
74109 * For vgremove (FREE_VG) we unlock-rename the vg and gl locks
74110 * so they cannot be reacquired.
74111 */
74112 if ((lmu_flags & LMUF_FREE_VG) &&
74113 (r->type == LD_RT_GL || r->type == LD_RT_VG)) {
74114 return release_rename(ls, r);
74115 }
74116
74117 rv = sanlock_release(lms->sock, -1, 0, 1, &rs);
74118 if (rv < 0)
74119 log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
74120
74121 if (rv == -EIO)
74122 rv = -ELOCKIO;
74123
74124 return rv;
74125}
74126
74127int lm_hosts_sanlock(struct lockspace *ls, int notify)
74128{
74129 struct sanlk_host *hss = NULL;
74130 struct sanlk_host *hs;
74131 uint32_t state;
74132 int hss_count = 0;
74133 int found_self = 0;
74134 int found_others = 0;
74135 int i, rv;
74136
74137 if (daemon_test)
74138 return 0;
74139
74140 rv = sanlock_get_hosts(ls->name, 0, &hss, &hss_count, 0);
74141 if (rv < 0) {
74142 log_error("S %s hosts_san get_hosts error %d", ls->name, rv);
74143 return 0;
74144 }
74145
74146 if (!hss || !hss_count) {
74147 log_error("S %s hosts_san zero hosts", ls->name);
74148 return 0;
74149 }
74150
74151 hs = hss;
74152
74153 for (i = 0; i < hss_count; i++) {
74154 log_debug("S %s hosts_san host_id %llu gen %llu flags %x",
74155 ls->name,
74156 (unsigned long long)hs->host_id,
74157 (unsigned long long)hs->generation,
74158 hs->flags);
74159
74160 if (hs->host_id == ls->host_id) {
74161 found_self = 1;
74162 hs++;
74163 continue;
74164 }
74165
74166 state = hs->flags & SANLK_HOST_MASK;
74167 if (state == SANLK_HOST_LIVE)
74168 found_others++;
74169 hs++;
74170 }
74171 free(hss);
74172
74173 if (found_others && notify) {
74174 /*
74175 * We could use the sanlock event mechanism to notify lvmlockd
74176 * on other hosts to stop this VG. lvmlockd would need to
74177 * register for and listen for sanlock events in the main loop.
74178 * The events are slow to propagate. We'd need to retry for a
74179 * while before all the hosts see the event and stop the VG.
74180 * sanlock_set_event(ls->name, &he, SANLK_SETEV_ALL_HOSTS);
74181 *
74182 * Wait to try this until there appears to be real value/interest
74183 * in doing it.
74184 */
74185 }
74186
74187 if (!found_self) {
74188 log_error("S %s hosts_san self not found others %d", ls->name, found_others);
74189 return 0;
74190 }
74191
74192 return found_others;
74193}
74194
74195int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin)
74196{
74197 struct sanlk_lockspace *ss_all = NULL;
74198 struct sanlk_lockspace *ss;
74199 struct lockspace *ls;
74200 int ss_count = 0;
74201 int i, rv;
74202
74203 rv = sanlock_get_lockspaces(&ss_all, &ss_count, 0);
74204 if (rv < 0)
74205 return rv;
74206
74207 if (!ss_all || !ss_count)
74208 return 0;
74209
74210 ss = ss_all;
74211
74212 for (i = 0; i < ss_count; i++) {
74213
74214 if (strncmp(ss->name, LVM_LS_PREFIX, strlen(LVM_LS_PREFIX)))
74215 continue;
74216
74217 if (!(ls = alloc_lockspace()))
74218 return -ENOMEM;
74219
74220 ls->lm_type = LD_LM_SANLOCK;
74221 ls->host_id = ss->host_id;
74222 strncpy(ls->name, ss->name, MAX_NAME);
74223 strncpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), MAX_NAME);
74224 list_add_tail(&ls->list, ls_rejoin);
74225
74226 ss++;
74227 }
74228
74229 free(ss_all);
74230 return 0;
74231}
74232
74233int lm_is_running_sanlock(void)
74234{
74235 uint32_t daemon_version;
74236 uint32_t daemon_proto;
74237 int rv;
74238
74239 if (daemon_test)
74240 return gl_use_sanlock;
74241
74242 rv = sanlock_version(0, &daemon_version, &daemon_proto);
74243 if (rv < 0)
74244 return 0;
74245 return 1;
74246}
74247\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmlockd/lvmlockd-internal.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000036520\013062740170\0024114\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
74248 * Copyright (C) 2014-2015 Red Hat, Inc.
74249 *
74250 * This file is part of LVM2.
74251 *
74252 * This copyrighted material is made available to anyone wishing to use,
74253 * modify, copy, or redistribute it subject to the terms and conditions
74254 * of the GNU Lesser General Public License v.2.1.
74255 */
74256
74257#ifndef _LVM_LVMLOCKD_INTERNAL_H
74258#define _LVM_LVMLOCKD_INTERNAL_H
74259
74260#define MAX_NAME 64
74261#define MAX_ARGS 64
74262
74263#define R_NAME_GL_DISABLED "_GLLK_disabled"
74264#define R_NAME_GL "GLLK"
74265#define R_NAME_VG "VGLK"
74266#define S_NAME_GL_DLM "lvm_global"
74267#define LVM_LS_PREFIX "lvm_" /* ls name is prefix + vg_name */
74268/* global lockspace name for sanlock is a vg name */
74269
74270/* lock manager types */
74271enum {
74272 LD_LM_NONE = 0,
74273 LD_LM_UNUSED = 1, /* place holder so values match lib/locking/lvmlockd.h */
74274 LD_LM_DLM = 2,
74275 LD_LM_SANLOCK = 3,
74276};
74277
74278/* operation types */
74279enum {
74280 LD_OP_HELLO = 1,
74281 LD_OP_QUIT,
74282 LD_OP_INIT,
74283 LD_OP_FREE,
74284 LD_OP_START,
74285 LD_OP_STOP,
74286 LD_OP_LOCK,
74287 LD_OP_UPDATE,
74288 LD_OP_CLOSE,
74289 LD_OP_ENABLE,
74290 LD_OP_DISABLE,
74291 LD_OP_START_WAIT,
74292 LD_OP_STOP_ALL,
74293 LD_OP_DUMP_INFO,
74294 LD_OP_DUMP_LOG,
74295 LD_OP_RENAME_BEFORE,
74296 LD_OP_RENAME_FINAL,
74297 LD_OP_RUNNING_LM,
74298 LD_OP_FIND_FREE_LOCK,
74299 LD_OP_KILL_VG,
74300 LD_OP_DROP_VG,
74301 LD_OP_BUSY,
74302};
74303
74304/* resource types */
74305enum {
74306 LD_RT_GL = 1,
74307 LD_RT_VG,
74308 LD_RT_LV,
74309};
74310
74311/* lock modes, more restrictive must be larger value */
74312enum {
74313 LD_LK_IV = -1,
74314 LD_LK_UN = 0,
74315 LD_LK_NL = 1,
74316 LD_LK_SH = 2,
74317 LD_LK_EX = 3,
74318};
74319
74320struct list_head {
74321 struct list_head *next, *prev;
74322};
74323
74324struct client {
74325 struct list_head list;
74326 pthread_mutex_t mutex;
74327 int pid;
74328 int fd;
74329 int pi;
74330 uint32_t id;
74331 unsigned int recv : 1;
74332 unsigned int dead : 1;
74333 unsigned int poll_ignore : 1;
74334 unsigned int lock_ops : 1;
74335 char name[MAX_NAME+1];
74336};
74337
74338#define LD_AF_PERSISTENT 0x00000001
74339#define LD_AF_NO_CLIENT 0x00000002
74340#define LD_AF_UNLOCK_CANCEL 0x00000004
74341#define LD_AF_NEXT_VERSION 0x00000008
74342#define LD_AF_WAIT 0x00000010
74343#define LD_AF_FORCE 0x00000020
74344#define LD_AF_EX_DISABLE 0x00000040
74345#define LD_AF_ENABLE 0x00000080
74346#define LD_AF_DISABLE 0x00000100
74347#define LD_AF_SEARCH_LS 0x00000200
74348#define LD_AF_WAIT_STARTING 0x00001000
74349#define LD_AF_DUP_GL_LS 0x00002000
74350#define LD_AF_ADOPT 0x00010000
74351#define LD_AF_WARN_GL_REMOVED 0x00020000
74352#define LD_AF_LV_LOCK 0x00040000
74353#define LD_AF_LV_UNLOCK 0x00080000
74354
74355/*
74356 * Number of times to repeat a lock request after
74357 * a lock conflict (-EAGAIN) if unspecified in the
74358 * request.
74359 */
74360#define DEFAULT_MAX_RETRIES 4
74361
74362struct action {
74363 struct list_head list;
74364 uint32_t client_id;
74365 uint32_t flags; /* LD_AF_ */
74366 uint32_t version;
74367 uint64_t host_id;
74368 int8_t op; /* operation type LD_OP_ */
74369 int8_t rt; /* resource type LD_RT_ */
74370 int8_t mode; /* lock mode LD_LK_ */
74371 int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
74372 int retries;
74373 int max_retries;
74374 int result;
74375 int lm_rv; /* return value from lm_ function */
74376 char vg_uuid[64];
74377 char vg_name[MAX_NAME+1];
74378 char lv_name[MAX_NAME+1];
74379 char lv_uuid[MAX_NAME+1];
74380 char vg_args[MAX_ARGS+1];
74381 char lv_args[MAX_ARGS+1];
74382 char vg_sysid[MAX_NAME+1];
74383};
74384
74385struct resource {
74386 struct list_head list; /* lockspace.resources */
74387 char name[MAX_NAME+1]; /* vg name or lv name */
74388 int8_t type; /* resource type LD_RT_ */
74389 int8_t mode;
74390 unsigned int sh_count; /* number of sh locks on locks list */
74391 uint32_t version;
74392 uint32_t last_client_id; /* last client_id to lock or unlock resource */
74393 unsigned int lm_init : 1; /* lm_data is initialized */
74394 unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
74395 unsigned int version_zero_valid : 1;
74396 unsigned int use_vb : 1;
74397 struct list_head locks;
74398 struct list_head actions;
74399 char lv_args[MAX_ARGS+1];
74400 char lm_data[0]; /* lock manager specific data */
74401};
74402
74403#define LD_LF_PERSISTENT 0x00000001
74404
74405struct lock {
74406 struct list_head list; /* resource.locks */
74407 int8_t mode; /* lock mode LD_LK_ */
74408 uint32_t version;
74409 uint32_t flags; /* LD_LF_ */
74410 uint32_t client_id; /* may be 0 for persistent or internal locks */
74411};
74412
74413struct lockspace {
74414 struct list_head list; /* lockspaces */
74415 char name[MAX_NAME+1];
74416 char vg_name[MAX_NAME+1];
74417 char vg_uuid[64];
74418 char vg_args[MAX_ARGS+1]; /* lock manager specific args */
74419 char vg_sysid[MAX_NAME+1];
74420 int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
74421 void *lm_data;
74422 uint64_t host_id;
74423 uint64_t free_lock_offset; /* start search for free lock here */
74424
74425 uint32_t start_client_id; /* client_id that started the lockspace */
74426 pthread_t thread; /* makes synchronous lock requests */
74427 pthread_cond_t cond;
74428 pthread_mutex_t mutex;
74429 unsigned int create_fail : 1;
74430 unsigned int create_done : 1;
74431 unsigned int thread_work : 1;
74432 unsigned int thread_stop : 1;
74433 unsigned int thread_done : 1;
74434 unsigned int sanlock_gl_enabled: 1;
74435 unsigned int sanlock_gl_dup: 1;
74436 unsigned int free_vg: 1;
74437 unsigned int kill_vg: 1;
74438 unsigned int drop_vg: 1;
74439
74440 struct list_head actions; /* new client actions */
74441 struct list_head resources; /* resource/lock state for gl/vg/lv */
74442};
74443
74444/* val_blk version */
74445#define VAL_BLK_VERSION 0x0101
74446
74447/* val_blk flags */
74448#define VBF_REMOVED 0x0001
74449
74450struct val_blk {
74451 uint16_t version;
74452 uint16_t flags;
74453 uint32_t r_version;
74454};
74455
74456/* lm_unlock flags */
74457#define LMUF_FREE_VG 0x00000001
74458
74459#define container_of(ptr, type, member) ({ \
74460 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
74461 (type *)( (char *)__mptr - offsetof(type,member) );})
74462
74463static inline void INIT_LIST_HEAD(struct list_head *list)
74464{
74465 list->next = list;
74466 list->prev = list;
74467}
74468
74469static inline void __list_add(struct list_head *new,
74470 struct list_head *prev,
74471 struct list_head *next)
74472{
74473 next->prev = new;
74474 new->next = next;
74475 new->prev = prev;
74476 prev->next = new;
74477}
74478
74479static inline void __list_del(struct list_head *prev, struct list_head *next)
74480{
74481 next->prev = prev;
74482 prev->next = next;
74483}
74484
74485static inline void list_add(struct list_head *new, struct list_head *head)
74486{
74487 __list_add(new, head, head->next);
74488}
74489
74490static inline void list_add_tail(struct list_head *new, struct list_head *head)
74491{
74492 __list_add(new, head->prev, head);
74493}
74494
74495static inline void list_del(struct list_head *entry)
74496{
74497 __list_del(entry->prev, entry->next);
74498}
74499
74500static inline int list_empty(const struct list_head *head)
74501{
74502 return head->next == head;
74503}
74504
74505#define list_entry(ptr, type, member) \
74506 container_of(ptr, type, member)
74507
74508#define list_first_entry(ptr, type, member) \
74509 list_entry((ptr)->next, type, member)
74510
74511#define list_for_each_entry(pos, head, member) \
74512 for (pos = list_entry((head)->next, typeof(*pos), member); \
74513 &pos->member != (head); \
74514 pos = list_entry(pos->member.next, typeof(*pos), member))
74515
74516#define list_for_each_entry_safe(pos, n, head, member) \
74517 for (pos = list_entry((head)->next, typeof(*pos), member), \
74518 n = list_entry(pos->member.next, typeof(*pos), member); \
74519 &pos->member != (head); \
74520 pos = n, n = list_entry(n->member.next, typeof(*n), member))
74521
74522
74523/* to improve readability */
74524#define WAIT 1
74525#define NO_WAIT 0
74526#define FORCE 1
74527#define NO_FORCE 0
74528
74529/*
74530 * global variables
74531 */
74532
74533#ifndef EXTERN
74534#define EXTERN extern
74535#define INIT(X)
74536#else
74537#undef EXTERN
74538#define EXTERN
74539#define INIT(X) =X
74540#endif
74541
74542/*
74543 * gl_type_static and gl_use_ are set by command line or config file
74544 * to specify whether the global lock comes from dlm or sanlock.
74545 * Without a static setting, lvmlockd will figure out where the
74546 * global lock should be (but it could get mixed up in cases where
74547 * both sanlock and dlm vgs exist.)
74548 *
74549 * gl_use_dlm means that the gl should come from lockspace gl_lsname_dlm
74550 * gl_use_sanlock means that the gl should come from lockspace gl_lsname_sanlock
74551 *
74552 * gl_use_dlm has precedence over gl_use_sanlock, so if a node sees both
74553 * dlm and sanlock vgs, it will use the dlm gl.
74554 *
74555 * gl_use_ is set when the first evidence of that lm_type is seen
74556 * in any command.
74557 *
74558 * gl_lsname_sanlock is set when the first vg is seen in which an
74559 * enabled gl is exists, or when init_vg creates a vg with gl enabled,
74560 * or when enable_gl is used.
74561 *
74562 * gl_lsname_sanlock is cleared when free_vg deletes a vg with gl enabled
74563 * or when disable_gl matches.
74564 */
74565
74566EXTERN int gl_type_static;
74567EXTERN int gl_use_dlm;
74568EXTERN int gl_use_sanlock;
74569EXTERN int gl_vg_removed;
74570EXTERN char gl_lsname_dlm[MAX_NAME+1];
74571EXTERN char gl_lsname_sanlock[MAX_NAME+1];
74572EXTERN int global_dlm_lockspace_exists;
74573
74574EXTERN int daemon_test; /* run as much as possible without a live lock manager */
74575EXTERN int daemon_debug;
74576EXTERN int daemon_host_id;
74577EXTERN const char *daemon_host_id_file;
74578EXTERN int sanlock_io_timeout;
74579
74580/*
74581 * This flag is set to 1 if we see multiple vgs with the global
74582 * lock enabled. While this is set, we return a special flag
74583 * with the vg lock result indicating to the lvm command that
74584 * there is a duplicate gl in the vg which should be resolved.
74585 * While this is set, find_lockspace_name has the side job of
74586 * counting the number of lockspaces with enabled gl's so that
74587 * this can be set back to zero when the duplicates are disabled.
74588 */
74589EXTERN int sanlock_gl_dup;
74590
74591void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
74592#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
74593#define log_error(fmt, args...) log_level(LOG_ERR, fmt, ##args)
74594#define log_warn(fmt, args...) log_level(LOG_WARNING, fmt, ##args)
74595
74596struct lockspace *alloc_lockspace(void);
74597int lockspaces_empty(void);
74598int last_string_from_args(char *args_in, char *last);
74599int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
74600
74601static inline const char *mode_str(int x)
74602{
74603 switch (x) {
74604 case LD_LK_IV:
74605 return "iv";
74606 case LD_LK_UN:
74607 return "un";
74608 case LD_LK_NL:
74609 return "nl";
74610 case LD_LK_SH:
74611 return "sh";
74612 case LD_LK_EX:
74613 return "ex";
74614 default:
74615 return ".";
74616 };
74617}
74618
74619#ifdef LOCKDDLM_SUPPORT
74620
74621int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
74622int lm_prepare_lockspace_dlm(struct lockspace *ls);
74623int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
74624int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
74625int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
74626 struct val_blk *vb_out, int adopt);
74627int lm_convert_dlm(struct lockspace *ls, struct resource *r,
74628 int ld_mode, uint32_t r_version);
74629int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
74630 uint32_t r_version, uint32_t lmu_flags);
74631int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r);
74632int lm_get_lockspaces_dlm(struct list_head *ls_rejoin);
74633int lm_data_size_dlm(void);
74634int lm_is_running_dlm(void);
74635int lm_hosts_dlm(struct lockspace *ls, int notify);
74636
74637static inline int lm_support_dlm(void)
74638{
74639 return 1;
74640}
74641
74642#else
74643
74644static inline int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
74645{
74646 return -1;
74647}
74648
74649static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
74650{
74651 return -1;
74652}
74653
74654static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
74655{
74656 return -1;
74657}
74658
74659static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
74660{
74661 return -1;
74662}
74663
74664static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
74665 struct val_blk *vb_out, int adopt)
74666{
74667 return -1;
74668}
74669
74670static inline int lm_convert_dlm(struct lockspace *ls, struct resource *r,
74671 int ld_mode, uint32_t r_version)
74672{
74673 return -1;
74674}
74675
74676static inline int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
74677 uint32_t r_version, uint32_t lmu_flags)
74678{
74679 return -1;
74680}
74681
74682static inline int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
74683{
74684 return -1;
74685}
74686
74687static inline int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
74688{
74689 return -1;
74690}
74691
74692static inline int lm_data_size_dlm(void)
74693{
74694 return -1;
74695}
74696
74697static inline int lm_is_running_dlm(void)
74698{
74699 return 0;
74700}
74701
74702static inline int lm_support_dlm(void)
74703{
74704 return 0;
74705}
74706
74707static inline int lm_hosts_dlm(struct lockspace *ls, int notify)
74708{
74709 return 0;
74710}
74711
74712#endif /* dlm support */
74713
74714#ifdef LOCKDSANLOCK_SUPPORT
74715
74716int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
74717int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset);
74718int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
74719int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
74720int lm_prepare_lockspace_sanlock(struct lockspace *ls);
74721int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
74722int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
74723int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
74724 struct val_blk *vb_out, int *retry, int adopt);
74725int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
74726 int ld_mode, uint32_t r_version);
74727int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
74728 uint32_t r_version, uint32_t lmu_flags);
74729int lm_able_gl_sanlock(struct lockspace *ls, int enable);
74730int lm_ex_disable_gl_sanlock(struct lockspace *ls);
74731int lm_hosts_sanlock(struct lockspace *ls, int notify);
74732int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r);
74733int lm_gl_is_enabled(struct lockspace *ls);
74734int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
74735int lm_data_size_sanlock(void);
74736int lm_is_running_sanlock(void);
74737int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset);
74738
74739static inline int lm_support_sanlock(void)
74740{
74741 return 1;
74742}
74743
74744#else
74745
74746static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
74747{
74748 return -1;
74749}
74750
74751static inline int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, uint64_t free_offset)
74752{
74753 return -1;
74754}
74755
74756static inline int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
74757{
74758 return -1;
74759}
74760
74761static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
74762{
74763 return -1;
74764}
74765
74766static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
74767{
74768 return -1;
74769}
74770
74771static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
74772{
74773 return -1;
74774}
74775
74776static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
74777{
74778 return -1;
74779}
74780
74781static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
74782 struct val_blk *vb_out, int *retry, int adopt)
74783{
74784 return -1;
74785}
74786
74787static inline int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
74788 int ld_mode, uint32_t r_version)
74789{
74790 return -1;
74791}
74792
74793static inline int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
74794 uint32_t r_version, uint32_t lmu_flags)
74795{
74796 return -1;
74797}
74798
74799static inline int lm_able_gl_sanlock(struct lockspace *ls, int enable)
74800{
74801 return -1;
74802}
74803
74804static inline int lm_ex_disable_gl_sanlock(struct lockspace *ls)
74805{
74806 return -1;
74807}
74808
74809static inline int lm_hosts_sanlock(struct lockspace *ls, int notify)
74810{
74811 return -1;
74812}
74813
74814static inline int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
74815{
74816 return -1;
74817}
74818
74819static inline int lm_gl_is_enabled(struct lockspace *ls)
74820{
74821 return -1;
74822}
74823
74824static inline int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin)
74825{
74826 return -1;
74827}
74828
74829static inline int lm_data_size_sanlock(void)
74830{
74831 return -1;
74832}
74833
74834static inline int lm_is_running_sanlock(void)
74835{
74836 return 0;
74837}
74838
74839static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset)
74840{
74841 return -1;
74842}
74843
74844static inline int lm_support_sanlock(void)
74845{
74846 return 0;
74847}
74848
74849#endif /* sanlock support */
74850
74851#endif /* _LVM_LVMLOCKD_INTERNAL_H */
74852\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020131\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/testclient.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000010132\013062740170\0022450\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
74853 * Copyright (C) 2011-2014 Red Hat, Inc.
74854 *
74855 * This file is part of LVM2.
74856 *
74857 * This copyrighted material is made available to anyone wishing to use,
74858 * modify, copy, or redistribute it subject to the terms and conditions
74859 * of the GNU General Public License v.2.
74860 *
74861 * You should have received a copy of the GNU General Public License
74862 * along with this program; if not, write to the Free Software Foundation,
74863 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
74864 */
74865#include "tool.h"
74866
74867#include "lvmetad-client.h"
74868#include "label.h"
74869#include "lvmcache.h"
74870#include "metadata.h"
74871
74872const char *uuid1 = "abcd-efgh";
74873const char *uuid2 = "bbcd-efgh";
74874const char *vgid = "yada-yada";
74875const char *uuid3 = "cbcd-efgh";
74876
74877const char *metadata2 = "{\n"
74878 "id = \"yada-yada\"\n"
74879 "seqno = 15\n"
74880 "status = [\"READ\", \"WRITE\"]\n"
74881 "flags = []\n"
74882 "extent_size = 8192\n"
74883 "physical_volumes {\n"
74884 " pv0 {\n"
74885 " id = \"abcd-efgh\"\n"
74886 " }\n"
74887 " pv1 {\n"
74888 " id = \"bbcd-efgh\"\n"
74889 " }\n"
74890 " pv2 {\n"
74891 " id = \"cbcd-efgh\"\n"
74892 " }\n"
74893 "}\n"
74894 "}\n";
74895
74896void _handle_reply(daemon_reply reply) {
74897 const char *repl = daemon_reply_str(reply, "response", NULL);
74898 const char *status = daemon_reply_str(reply, "status", NULL);
74899 const char *vgid = daemon_reply_str(reply, "vgid", NULL);
74900
74901 fprintf(stderr, "[C] REPLY: %s\n", repl);
74902 if (!strcmp(repl, "failed"))
74903 fprintf(stderr, "[C] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown"));
74904 if (vgid)
74905 fprintf(stderr, "[C] VGID: %s\n", vgid);
74906 if (status)
74907 fprintf(stderr, "[C] STATUS: %s\n", status);
74908 daemon_reply_destroy(reply);
74909}
74910
74911void _pv_add(daemon_handle h, const char *uuid, const char *metadata)
74912{
74913 daemon_reply reply = daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
74914 "metadata = %b", metadata,
74915 NULL);
74916 _handle_reply(reply);
74917}
74918
74919int scan(daemon_handle h, char *fn) {
74920 struct device *dev = dev_cache_get(fn, NULL);
74921
74922 struct label *label;
74923 if (!label_read(dev, &label, 0)) {
74924 fprintf(stderr, "[C] no label found on %s\n", fn);
74925 return;
74926 }
74927
74928 char uuid[64];
74929 if (!id_write_format(dev->pvid, uuid, 64)) {
74930 fprintf(stderr, "[C] Failed to format PV UUID for %s", dev_name(dev));
74931 return;
74932 }
74933 fprintf(stderr, "[C] found PV: %s\n", uuid);
74934 struct lvmcache_info *info = (struct lvmcache_info *) label->info;
74935 struct physical_volume pv = { 0, };
74936
74937 if (!(info->fmt->ops->pv_read(info->fmt, dev_name(dev), &pv, 0))) {
74938 fprintf(stderr, "[C] Failed to read PV %s", dev_name(dev));
74939 return;
74940 }
74941
74942 struct format_instance_ctx fic;
74943 struct format_instance *fid = info->fmt->ops->create_instance(info->fmt, &fic);
74944 struct metadata_area *mda;
74945 struct volume_group *vg = NULL;
74946 dm_list_iterate_items(mda, &info->mdas) {
74947 struct volume_group *this = mda->ops->vg_read(fid, "", mda);
74948 if (this && !vg || this->seqno > vg->seqno)
74949 vg = this;
74950 }
74951 if (vg) {
74952 char *buf = NULL;
74953 /* TODO. This is not entirely correct, since export_vg_to_buffer
74954 * adds trailing garbage to the buffer. We may need to use
74955 * export_vg_to_config_tree and format the buffer ourselves. It
74956 * does, however, work for now, since the garbage is well
74957 * formatted and has no conflicting keys with the rest of the
74958 * request. */
74959 export_vg_to_buffer(vg, &buf);
74960 daemon_reply reply =
74961 daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
74962 "metadata = %b", strchr(buf, '{'),
74963 NULL);
74964 _handle_reply(reply);
74965 }
74966}
74967
74968void _dump_vg(daemon_handle h, const char *uuid)
74969{
74970 daemon_reply reply = daemon_send_simple(h, "vg_by_uuid", "uuid = %s", uuid, NULL);
74971 fprintf(stderr, "[C] reply buffer: %s\n", reply.buffer);
74972 daemon_reply_destroy(reply);
74973}
74974
74975int main(int argc, char **argv) {
74976 daemon_handle h = lvmetad_open();
74977 /* FIXME Missing error path */
74978
74979 if (argc > 1) {
74980 int i;
74981 struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0, 1, 1);
74982 for (i = 1; i < argc; ++i) {
74983 const char *uuid = NULL;
74984 scan(h, argv[i]);
74985 }
74986 destroy_toolcontext(cmd);
74987 /* FIXME Missing lvmetad_close() */
74988 return 0;
74989 }
74990
74991 _pv_add(h, uuid1, NULL);
74992 _pv_add(h, uuid2, metadata2);
74993 _dump_vg(h, vgid);
74994 _pv_add(h, uuid3, NULL);
74995
74996 daemon_close(h); /* FIXME lvmetad_close? */
74997 return 0;
74998}
74999\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/lvmetad-client.h\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000005265\013062740170\0023222\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
75000 * Copyright (C) 2011-2012 Red Hat, Inc.
75001 *
75002 * This file is part of LVM2.
75003 *
75004 * This copyrighted material is made available to anyone wishing to use,
75005 * modify, copy, or redistribute it subject to the terms and conditions
75006 * of the GNU Lesser General Public License v.2.1.
75007 *
75008 * You should have received a copy of the GNU Lesser General Public License
75009 * along with this program; if not, write to the Free Software Foundation,
75010 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
75011 */
75012
75013#ifndef _LVM_LVMETAD_CLIENT_H
75014#define _LVM_LVMETAD_CLIENT_H
75015
75016#include "daemon-client.h"
75017
75018#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
75019
75020#define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
75021
75022#define LVMETAD_DISABLE_REASON_DIRECT "DIRECT"
75023#define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
75024#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
75025#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
75026
75027struct volume_group;
75028
75029/* Different types of replies we may get from lvmetad. */
75030
75031typedef struct {
75032 daemon_reply r;
75033 const char **uuids; /* NULL terminated array */
75034} lvmetad_uuidlist;
75035
75036typedef struct {
75037 daemon_reply r;
75038 struct dm_config_tree *cft;
75039} lvmetad_vg;
75040
75041/* Get a list of VG UUIDs that match a given VG name. */
75042lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name);
75043
75044/* Get the metadata of a single VG, identified by UUID. */
75045lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid);
75046
75047/*
75048 * Add and remove PVs on demand. Udev-driven systems will use this interface
75049 * instead of scanning.
75050 */
75051daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content);
75052daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid);
75053
75054/* Trigger a full disk scan, throwing away all caches. XXX do we eventually want
75055 * this? Probably not yet, anyway.
75056 * daemon_reply lvmetad_rescan(daemon_handle h);
75057 */
75058
75059/*
75060 * Update the version of metadata of a volume group. The VG has to be locked for
75061 * writing for this, and the VG metadata here has to match whatever has been
75062 * written to the disk (under this lock). This initially avoids the requirement
75063 * for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may
75064 * also do the writing, or we probably add another function to do that).
75065 */
75066daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg);
75067
75068/* Wrappers to open/close connection */
75069
75070static inline daemon_handle lvmetad_open(const char *socket)
75071{
75072 daemon_info lvmetad_info = {
75073 .path = "lvmetad",
75074 .socket = socket ?: LVMETAD_SOCKET,
75075 .protocol = "lvmetad",
75076 .protocol_version = 1,
75077 .autostart = 0
75078 };
75079
75080 return daemon_open(lvmetad_info);
75081}
75082
75083static inline void lvmetad_close(daemon_handle h)
75084{
75085 return daemon_close(h);
75086}
75087
75088#endif
75089\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000003753\013062740170\0022206\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
75090# Copyright (C) 2011-2012 Red Hat, Inc.
75091#
75092# This file is part of LVM2.
75093#
75094# This copyrighted material is made available to anyone wishing to use,
75095# modify, copy, or redistribute it subject to the terms and conditions
75096# of the GNU Lesser General Public License v.2.1.
75097#
75098# You should have received a copy of the GNU Lesser General Public License
75099# along with this program; if not, write to the Free Software Foundation,
75100# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
75101
75102srcdir = @srcdir@
75103top_srcdir = @top_srcdir@
75104top_builddir = @top_builddir@
75105
75106SOURCES = lvmetad-core.c
75107SOURCES2 = testclient.c
75108
75109TARGETS = lvmetad lvmetactl
75110
75111.PHONY: install_lvmetad
75112
75113CFLOW_LIST = $(SOURCES)
75114CFLOW_LIST_TARGET = $(LIB_NAME).cflow
75115CFLOW_TARGET = lvmetad
75116
75117include $(top_builddir)/make.tmpl
75118
75119INCLUDES += -I$(top_srcdir)/libdaemon/server
75120LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
75121
75122LIBS += $(PTHREAD_LIBS)
75123
75124LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS)
75125CLDFLAGS += -L$(top_builddir)/libdaemon/server
75126CFLAGS += $(EXTRA_EXEC_CFLAGS)
75127
75128lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
75129 $(top_builddir)/libdaemon/server/libdaemonserver.a
75130 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LVMLIBS) $(LIBS)
75131
75132lvmetactl: lvmetactl.o $(top_builddir)/libdaemon/client/libdaemonclient.a \
75133 $(top_builddir)/libdaemon/server/libdaemonserver.a
75134 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmetactl.o $(LVMLIBS)
75135
75136CLEAN_TARGETS += lvmetactl.o
75137
75138# TODO: No idea. No idea how to test either.
75139#ifneq ("$(CFLOW_CMD)", "")
75140#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
75141#-include $(top_builddir)/libdm/libdevmapper.cflow
75142#-include $(top_builddir)/lib/liblvm-internal.cflow
75143#-include $(top_builddir)/lib/liblvm2cmd.cflow
75144#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
75145#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
75146#endif
75147
75148install_lvmetad: lvmetad
75149 $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
75150
75151install_lvm2: install_lvmetad
75152
75153install: install_lvm2
75154\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/lvmetad-core.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000262414\013062740170\0022670\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
75155 * Copyright (C) 2012-2015 Red Hat, Inc.
75156 *
75157 * This file is part of LVM2.
75158 *
75159 * This copyrighted material is made available to anyone wishing to use,
75160 * modify, copy, or redistribute it subject to the terms and conditions
75161 * of the GNU Lesser General Public License v.2.1.
75162 *
75163 * You should have received a copy of the GNU Lesser General Public License
75164 * along with this program; if not, write to the Free Software Foundation,
75165 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
75166 */
75167
75168#define _XOPEN_SOURCE 500 /* pthread */
75169
75170#define _REENTRANT
75171
75172#include "tool.h"
75173
75174#include "daemon-io.h"
75175#include "daemon-server.h"
75176#include "daemon-log.h"
75177#include "lvm-version.h"
75178#include "lvmetad-client.h"
75179
75180#include <assert.h>
75181#include <errno.h>
75182#include <pthread.h>
75183
75184#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
75185
75186/*
75187 * cache states:
75188 * . Empty: no devices visible to the system have been added to lvmetad
75189 * . Scanning: some devices visible to the system have been added to lvmetad
75190 * . Initialized: all devices visible to the system have been added to lvmetad
75191 * . Outdated: event on system or storage is not yet processed by lvmetad
75192 * Outdated variations:
75193 * - MissingDev: device added to system, not yet added to lvmetad
75194 * - RemovedDev: device removed from system, not yet removed from lvmetad
75195 * - MissingVG: new vg is written on disk, not yet added to lvmetad
75196 * - RemovedVG: vg is removed on disk, not yet removed in lvmetad
75197 * - ChangedVG: vg metadata is changed on disk, not yet updated in lvmetad
75198 * - MissingPV: new pv is written on disk, not yet added to in lvmetad
75199 * - RemovedPV: pv is removed on disk, not yet removed in lvmetad
75200 * - ChangedPV: pv metadata is changed on disk, not yet updated in lvmetad
75201 * . Updated: events have been processed by lvmetad
75202 *
75203 * state transitions:
75204 * . Empty -> Scanning
75205 * . Scanning -> Initialized
75206 * . Initialized -> Scanning
75207 * . Initialized -> Outdated
75208 * . Outdated -> Updated
75209 * . Updated -> Outdated
75210 * . Updated -> Scanning
75211 * . Outdated -> Scanning
75212 *
75213 * state transitions caused by:
75214 * . Empty is caused by:
75215 * - starting/restarting lvmetad
75216 * . Scanning is caused by:
75217 * - running pvscan --cache
75218 * - running any command with different global_filter (token mismatch)
75219 * - running any command while lvmetad is Empty
75220 * - running a report/display command with --foreign
75221 * - running a report/display command with --shared
75222 * - running a command using lvmlockd global lock where global state is changed
75223 * . Initialized is caused by:
75224 * - completion of Scanning
75225 * . Outdated is caused by:
75226 * - device being added or removed on the system
75227 * - creating/removing/changing a VG
75228 * - creating/removing/changing a PV
75229 * . Updated is caused by:
75230 * - receiving and processing all events
75231 *
75232 * request handling:
75233 * . Empty: short period during startup, token error returned
75234 * . Scanning: should be very short, lvmetad responds to requests with
75235 * the token error "updating"
75236 * . Initialized: lvmetad responds to requests
75237 * . Updated: lvmetad responds to requests
75238 * . Outdated: should be very short, lvmetad responds to requests
75239 *
75240 * In general, the cache state before and after the transition
75241 * "Updated -> Scanning -> Initialized" should match, unless
75242 * events occur during that transition.
75243 *
75244 * The Scanning state includes:
75245 * . receive a request to set the token to "updating" (Scanning state begins.)
75246 * . receive a pv_clear_all request to clear current cache
75247 * . receive a number of pv_found events to repopulate cache
75248 * . receive a request to set the token to a hash value (Initialized state begins.)
75249 *
75250 * The transition from Outdated to Updated depends on lvm commands
75251 * sending events to lvmetad, i.e. pv_found, pv_gone, vg_update,
75252 * vg_remove. Prior to receiving these events, lvmetad is not aware
75253 * that it is in the Outdated state.
75254 *
75255 * When using a shared VG with lvmlockd, the Outdated state can last a
75256 * longer time, but it won't be used in that state. lvmlockd forces a
75257 * transition "Outdated -> Scanning -> Initialized" before the cache
75258 * is used.
75259 */
75260
75261
75262/*
75263 * valid/invalid state of cached metadata
75264 *
75265 * Normally when using lvmetad, the state is kept up-to-date through a
75266 * combination of notifications from clients and updates triggered by uevents.
75267 * When using lvmlockd, the lvmetad state is expected to become out of
75268 * date (invalid/stale) when other hosts make changes to the metadata on disk.
75269 *
75270 * To deal with this, the metadata cached in lvmetad can be flagged as invalid.
75271 * This invalid flag is returned along with the metadata when read by a
75272 * command. The command can check for the invalid flag and decide that it
75273 * should either use the stale metadata (uncommon), or read the latest metadata
75274 * from disk rather than using the invalid metadata that was returned. If the
75275 * command reads the latest metadata from disk, it can choose to send it to
75276 * lvmetad to update the cached copy and clear the invalid flag in lvmetad.
75277 * Otherwise, the next command to read the metadata from lvmetad will also
75278 * receive the invalid metadata with the invalid flag (and like the previous
75279 * command, it too may choose to read the latest metadata from disk and can
75280 * then also choose to update the lvmetad copy.)
75281 *
75282 * For purposes of tracking the invalid state, LVM metadata is considered
75283 * to be either VG-specific or global. VG-specific metadata is metadata
75284 * that is isolated to a VG, such as the LVs it contains. Global
75285 * metadata is metadata that is not isolated to a single VG. Global
75286 * metdata includes:
75287 * . the VG namespace (which VG names are used)
75288 * . the set of orphan PVs (which PVs are in VGs and which are not)
75289 * . properties of orphan PVs (the size of an orphan PV)
75290 *
75291 * If the metadata for a single VG becomes invalid, the VGFL_INVALID
75292 * flag can be set in the vg_info struct for that VG. If the global
75293 * metdata becomes invalid, the GLFL_INVALID flag can be set in the
75294 * lvmetad daemon state.
75295 *
75296 * If a command reads VG metadata and VGFL_INVALID is set, an
75297 * extra config node called "vg_invalid" is added to the config
75298 * data returned to the command.
75299 *
75300 * If a command reads global metdata and GLFL_INVALID is set, an
75301 * extra config node called "global_invalid" is added to the
75302 * config data returned to the command.
75303 *
75304 * If a command sees vg_invalid, and wants the latest VG metadata,
75305 * it only needs to scan disks of the PVs in that VG.
75306 * It can then use vg_update to send the latest metadata to lvmetad
75307 * which clears the VGFL_INVALID flag.
75308 *
75309 * If a command sees global_invalid, and wants the latest metadata,
75310 * it should scan all devices to update lvmetad, and then send
75311 * lvmetad the "set_global_info global_invalid=0" message to clear
75312 * GLFL_INVALID.
75313 *
75314 * (When rescanning devices to update lvmetad, the command must use
75315 * the global filter cmd->lvmetad_filter so that it processes the same
75316 * devices that are seen by lvmetad.)
75317 *
75318 * The lvmetad INVALID flags can be set by sending lvmetad the messages:
75319 *
75320 * . set_vg_info with the latest VG seqno. If the VG seqno is larger
75321 * than the cached VG seqno, VGFL_INVALID is set for the VG.
75322 *
75323 * . set_global_info with global_invalid=1 sets GLFL_INVALID.
75324 *
75325 * Different entities could use these functions to invalidate metadata
75326 * if/when they detected that the cache is stale. How they detect that
75327 * the cache is stale depends on the details of the specific entity.
75328 *
75329 * In the case of lvmlockd, it embeds values into its locks to keep track
75330 * of when other nodes have changed metadata on disk related to those locks.
75331 * When acquring locks it can look at these values and detect that
75332 * the metadata associated with the lock has been changed.
75333 * When the values change, it uses set_vg_info/set_global_info to
75334 * invalidate the lvmetad cache.
75335 *
75336 * The values that lvmlockd distributes through its locks are the
75337 * latest VG seqno in VG locks and a global counter in the global lock.
75338 * When a host acquires a VG lock and sees that the embedded seqno is
75339 * larger than it was previously, it knows that it should invalidate the
75340 * lvmetad cache for the VG. If the host acquires the global lock
75341 * and sees that the counter is larger than previously, it knows that
75342 * it should invalidate the global info in lvmetad. This invalidation
75343 * is done before the lock is returned to the command. This way the
75344 * invalid flag will be set on the metadata before the command reads
75345 * it from lvmetad.
75346 */
75347
75348struct vg_info {
75349 int64_t external_version;
75350 uint32_t flags; /* VGFL_ */
75351};
75352
75353#define GLFL_INVALID 0x00000001
75354#define GLFL_DISABLE 0x00000002
75355#define GLFL_DISABLE_REASON_DIRECT 0x00000004
75356#define GLFL_DISABLE_REASON_LVM1 0x00000008
75357#define GLFL_DISABLE_REASON_DUPLICATES 0x00000010
75358#define GLFL_DISABLE_REASON_VGRESTORE 0x00000020
75359
75360#define GLFL_DISABLE_REASON_ALL (GLFL_DISABLE_REASON_DIRECT | GLFL_DISABLE_REASON_LVM1 | GLFL_DISABLE_REASON_DUPLICATES | GLFL_DISABLE_REASON_VGRESTORE)
75361
75362#define VGFL_INVALID 0x00000001
75363
75364#define CMD_NAME_SIZE 32
75365
75366typedef struct {
75367 daemon_idle *idle;
75368 log_state *log; /* convenience */
75369 const char *log_config;
75370
75371 struct dm_hash_table *pvid_to_pvmeta;
75372 struct dm_hash_table *device_to_pvid; /* shares locks with above */
75373
75374 struct dm_hash_table *vgid_to_metadata;
75375 struct dm_hash_table *vgid_to_vgname;
75376 struct dm_hash_table *vgid_to_outdated_pvs;
75377 struct dm_hash_table *vgid_to_info;
75378 struct dm_hash_table *vgname_to_vgid;
75379 struct dm_hash_table *pvid_to_vgid;
75380 char token[128];
75381 char update_cmd[CMD_NAME_SIZE];
75382 int update_pid;
75383 int update_timeout;
75384 uint64_t update_begin;
75385 uint32_t flags; /* GLFL_ */
75386 pthread_mutex_t token_lock;
75387 pthread_mutex_t info_lock;
75388 pthread_rwlock_t cache_lock;
75389} lvmetad_state;
75390
75391static uint64_t _monotonic_seconds(void)
75392{
75393 struct timespec ts;
75394
75395 if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
75396 return 0;
75397 return ts.tv_sec;
75398}
75399
75400static void destroy_metadata_hashes(lvmetad_state *s)
75401{
75402 struct dm_hash_node *n = NULL;
75403
75404 dm_hash_iterate(n, s->vgid_to_metadata)
75405 dm_config_destroy(dm_hash_get_data(s->vgid_to_metadata, n));
75406
75407 dm_hash_iterate(n, s->vgid_to_outdated_pvs)
75408 dm_config_destroy(dm_hash_get_data(s->vgid_to_outdated_pvs, n));
75409
75410 dm_hash_iterate(n, s->pvid_to_pvmeta)
75411 dm_config_destroy(dm_hash_get_data(s->pvid_to_pvmeta, n));
75412
75413 dm_hash_destroy(s->pvid_to_pvmeta);
75414 dm_hash_destroy(s->vgid_to_metadata);
75415 dm_hash_destroy(s->vgid_to_vgname);
75416 dm_hash_destroy(s->vgid_to_outdated_pvs);
75417 dm_hash_destroy(s->vgid_to_info);
75418 dm_hash_destroy(s->vgname_to_vgid);
75419
75420 dm_hash_destroy(s->device_to_pvid);
75421 dm_hash_destroy(s->pvid_to_vgid);
75422}
75423
75424static void create_metadata_hashes(lvmetad_state *s)
75425{
75426 s->pvid_to_pvmeta = dm_hash_create(32);
75427 s->device_to_pvid = dm_hash_create(32);
75428 s->vgid_to_metadata = dm_hash_create(32);
75429 s->vgid_to_vgname = dm_hash_create(32);
75430 s->vgid_to_outdated_pvs = dm_hash_create(32);
75431 s->vgid_to_info = dm_hash_create(32);
75432 s->pvid_to_vgid = dm_hash_create(32);
75433 s->vgname_to_vgid = dm_hash_create(32);
75434}
75435
75436static response reply_fail(const char *reason)
75437{
75438 return daemon_reply_simple("failed", "reason = %s", reason, NULL);
75439}
75440
75441static response reply_unknown(const char *reason)
75442{
75443 return daemon_reply_simple("unknown", "reason = %s", reason, NULL);
75444}
75445
75446static struct dm_config_node *pvs(struct dm_config_node *vg)
75447{
75448 struct dm_config_node *pv = dm_config_find_node(vg, "metadata/physical_volumes");
75449 if (pv)
75450 pv = pv->child;
75451 return pv;
75452}
75453
75454static void filter_metadata(struct dm_config_node *vg) {
75455 struct dm_config_node *pv = pvs(vg);
75456 while (pv) {
75457 struct dm_config_node *item = pv->child;
75458 while (item) {
75459 /* Remove the advisory device nodes. */
75460 if (item->sib && !strcmp(item->sib->key, "device"))
75461 item->sib = item->sib->sib;
75462 item = item->sib;
75463 }
75464 pv = pv->sib;
75465 }
75466 vg->sib = NULL; /* Drop any trailing garbage. */
75467}
75468
75469static void merge_pvmeta(struct dm_config_node *pv, struct dm_config_node *pvmeta)
75470{
75471 struct dm_config_node *tmp;
75472
75473 if (!pvmeta)
75474 return;
75475
75476 tmp = pvmeta;
75477 while (tmp->sib) {
75478 /* drop the redundant ID and dev_size nodes */
75479 if (!strcmp(tmp->sib->key, "id") || !strcmp(tmp->sib->key, "dev_size"))
75480 tmp->sib = tmp->sib->sib;
75481 if (!tmp->sib) break;
75482 tmp = tmp->sib;
75483 tmp->parent = pv;
75484 }
75485 tmp->sib = pv->child;
75486 pv->child = pvmeta;
75487 pvmeta->parent = pv;
75488}
75489
75490/*
75491 * Either the "big" vgs lock, or a per-vg lock needs to be held before entering
75492 * this function.
75493 *
75494 * cft and vg is data being sent to the caller.
75495 */
75496
75497static int update_pv_status(lvmetad_state *s,
75498 struct dm_config_tree *cft,
75499 struct dm_config_node *vg)
75500{
75501 struct dm_config_node *pv;
75502 const char *uuid;
75503 struct dm_config_tree *pvmeta;
75504 struct dm_config_node *pvmeta_cn;
75505 int ret = 1;
75506
75507 for (pv = pvs(vg); pv; pv = pv->sib) {
75508 if (!(uuid = dm_config_find_str(pv->child, "id", NULL))) {
75509 ERROR(s, "update_pv_status found no uuid for PV");
75510 continue;
75511 }
75512
75513 pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, uuid);
75514
75515 set_flag(cft, pv, "status", "MISSING", !pvmeta);
75516
75517 if (pvmeta) {
75518 if (!(pvmeta_cn = dm_config_clone_node(cft, pvmeta->root->child, 1))) {
75519 ERROR(s, "update_pv_status out of memory");
75520 ret = 0;
75521 goto out;
75522 }
75523
75524 merge_pvmeta(pv, pvmeta_cn);
75525 }
75526 }
75527out:
75528 return ret;
75529}
75530
75531static struct dm_config_node *add_last_node(struct dm_config_tree *cft, const char *node_name)
75532{
75533 struct dm_config_node *cn, *last;
75534
75535 cn = cft->root;
75536 last = cn;
75537
75538 while (cn->sib) {
75539 last = cn->sib;
75540 cn = last;
75541 }
75542
75543 cn = dm_config_create_node(cft, node_name);
75544 if (!cn)
75545 return NULL;
75546
75547 cn->v = NULL;
75548 cn->sib = NULL;
75549 cn->parent = cft->root;
75550 last->sib = cn;
75551
75552 return cn;
75553}
75554
75555static struct dm_config_node *make_pv_node(lvmetad_state *s, const char *pvid,
75556 struct dm_config_tree *cft,
75557 struct dm_config_node *parent,
75558 struct dm_config_node *pre_sib)
75559{
75560 struct dm_config_tree *pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
75561 const char *vgid = dm_hash_lookup(s->pvid_to_vgid, pvid), *vgname = NULL;
75562 struct dm_config_node *pv;
75563 struct dm_config_node *cn = NULL;
75564
75565 if (!pvmeta)
75566 return NULL;
75567
75568 if (vgid) {
75569 vgname = dm_hash_lookup(s->vgid_to_vgname, vgid);
75570 }
75571
75572 /* Nick the pvmeta config tree. */
75573 if (!(pv = dm_config_clone_node(cft, pvmeta->root, 0)))
75574 return 0;
75575
75576 if (pre_sib)
75577 pre_sib->sib = pv;
75578 if (parent && !parent->child)
75579 parent->child = pv;
75580 pv->parent = parent;
75581 pv->key = pvid;
75582
75583 /* Add the "variable" bits to it. */
75584
75585 if (vgid && strcmp(vgid, "#orphan"))
75586 cn = make_text_node(cft, "vgid", vgid, pv, cn);
75587 if (vgname)
75588 cn = make_text_node(cft, "vgname", vgname, pv, cn);
75589
75590 return pv;
75591}
75592
75593static response pv_list(lvmetad_state *s, request r)
75594{
75595 struct dm_config_node *cn = NULL, *cn_pvs;
75596 struct dm_hash_node *n;
75597 const char *id;
75598 response res = { 0 };
75599
75600 DEBUGLOG(s, "pv_list");
75601
75602 buffer_init( &res.buffer );
75603
75604 if (!(res.cft = dm_config_create()))
75605 return res; /* FIXME error reporting */
75606
75607 /* The response field */
75608 if (!(res.cft->root = make_text_node(res.cft, "response", "OK", NULL, NULL)))
75609 return res; /* FIXME doomed */
75610
75611 cn_pvs = make_config_node(res.cft, "physical_volumes", NULL, res.cft->root);
75612
75613 dm_hash_iterate(n, s->pvid_to_pvmeta) {
75614 id = dm_hash_get_key(s->pvid_to_pvmeta, n);
75615 cn = make_pv_node(s, id, res.cft, cn_pvs, cn);
75616 }
75617
75618 if (s->flags & GLFL_INVALID)
75619 add_last_node(res.cft, "global_invalid");
75620
75621 return res;
75622}
75623
75624static response pv_lookup(lvmetad_state *s, request r)
75625{
75626 const char *pvid = daemon_request_str(r, "uuid", NULL);
75627 int64_t devt = daemon_request_int(r, "device", 0);
75628 response res = { 0 };
75629 struct dm_config_node *pv;
75630
75631 DEBUGLOG(s, "pv_lookup pvid %s", pvid);
75632
75633 buffer_init( &res.buffer );
75634
75635 if (!pvid && !devt)
75636 return reply_fail("need PVID or device");
75637
75638 if (!(res.cft = dm_config_create()))
75639 return reply_fail("out of memory");
75640
75641 if (!(res.cft->root = make_text_node(res.cft, "response", "OK", NULL, NULL)))
75642 return reply_fail("out of memory");
75643
75644 if (!pvid && devt)
75645 pvid = dm_hash_lookup_binary(s->device_to_pvid, &devt, sizeof(devt));
75646
75647 if (!pvid) {
75648 WARN(s, "pv_lookup: could not find device %" PRIu64, devt);
75649 dm_config_destroy(res.cft);
75650 return reply_unknown("device not found");
75651 }
75652
75653 pv = make_pv_node(s, pvid, res.cft, NULL, res.cft->root);
75654 if (!pv) {
75655 dm_config_destroy(res.cft);
75656 return reply_unknown("PV not found");
75657 }
75658
75659 pv->key = "physical_volume";
75660
75661 if (s->flags & GLFL_INVALID)
75662 add_last_node(res.cft, "global_invalid");
75663
75664 return res;
75665}
75666
75667static response vg_list(lvmetad_state *s, request r)
75668{
75669 struct dm_config_node *cn, *cn_vgs, *cn_last = NULL;
75670 struct dm_hash_node *n;
75671 const char *id;
75672 const char *name;
75673 response res = { 0 };
75674
75675 DEBUGLOG(s, "vg_list");
75676
75677 buffer_init( &res.buffer );
75678
75679 if (!(res.cft = dm_config_create()))
75680 goto bad; /* FIXME: better error reporting */
75681
75682 /* The response field */
75683 res.cft->root = cn = dm_config_create_node(res.cft, "response");
75684 if (!cn)
75685 goto bad; /* FIXME */
75686 cn->parent = res.cft->root;
75687 if (!(cn->v = dm_config_create_value(res.cft)))
75688 goto bad; /* FIXME */
75689
75690 cn->v->type = DM_CFG_STRING;
75691 cn->v->v.str = "OK";
75692
75693 cn_vgs = cn = cn->sib = dm_config_create_node(res.cft, "volume_groups");
75694 if (!cn_vgs)
75695 goto bad; /* FIXME */
75696
75697 cn->parent = res.cft->root;
75698 cn->v = NULL;
75699 cn->child = NULL;
75700
75701 dm_hash_iterate(n, s->vgid_to_vgname) {
75702 id = dm_hash_get_key(s->vgid_to_vgname, n),
75703 name = dm_hash_get_data(s->vgid_to_vgname, n);
75704
75705 if (!(cn = dm_config_create_node(res.cft, id)))
75706 goto bad; /* FIXME */
75707
75708 if (cn_last)
75709 cn_last->sib = cn;
75710
75711 cn->parent = cn_vgs;
75712 cn->sib = NULL;
75713 cn->v = NULL;
75714
75715 if (!(cn->child = dm_config_create_node(res.cft, "name")))
75716 goto bad; /* FIXME */
75717
75718 cn->child->parent = cn;
75719 cn->child->sib = 0;
75720 if (!(cn->child->v = dm_config_create_value(res.cft)))
75721 goto bad; /* FIXME */
75722
75723 cn->child->v->type = DM_CFG_STRING;
75724 cn->child->v->v.str = name;
75725
75726 if (!cn_vgs->child)
75727 cn_vgs->child = cn;
75728 cn_last = cn;
75729 }
75730
75731 if (s->flags & GLFL_INVALID)
75732 add_last_node(res.cft, "global_invalid");
75733bad:
75734 return res;
75735}
75736
75737static void mark_outdated_pv(lvmetad_state *s, const char *vgid, const char *pvid)
75738{
75739 struct dm_config_tree *pvmeta, *outdated_pvs;
75740 struct dm_config_node *list, *cft_vgid;
75741 struct dm_config_value *v;
75742
75743 pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid);
75744
75745 /* if the MDA exists and is used, it will have ignore=0 set */
75746 if (!pvmeta ||
75747 (dm_config_find_int64(pvmeta->root, "pvmeta/mda0/ignore", 1) &&
75748 dm_config_find_int64(pvmeta->root, "pvmeta/mda1/ignore", 1)))
75749 return;
75750
75751 ERROR(s, "PV %s has outdated metadata for VG %s", pvid, vgid);
75752
75753 outdated_pvs = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid);
75754 if (!outdated_pvs) {
75755 if (!(outdated_pvs = config_tree_from_string_without_dup_node_check("outdated_pvs/pv_list = []")) ||
75756 !(cft_vgid = make_text_node(outdated_pvs, "vgid", dm_pool_strdup(outdated_pvs->mem, vgid),
75757 outdated_pvs->root, NULL)))
75758 abort();
75759 if (!dm_hash_insert(s->vgid_to_outdated_pvs, cft_vgid->v->v.str, outdated_pvs))
75760 abort();
75761 DEBUGLOG(s, "created outdated_pvs list for VG %s", vgid);
75762 }
75763
75764 list = dm_config_find_node(outdated_pvs->root, "outdated_pvs/pv_list");
75765 v = list->v;
75766 while (v) {
75767 if (v->type != DM_CFG_EMPTY_ARRAY && !strcmp(v->v.str, pvid))
75768 return;
75769 v = v->next;
75770 }
75771 if (!(v = dm_config_create_value(outdated_pvs)))
75772 abort();
75773 v->type = DM_CFG_STRING;
75774 v->v.str = dm_pool_strdup(outdated_pvs->mem, pvid);
75775 v->next = list->v;
75776 list->v = v;
75777}
75778
75779static void chain_outdated_pvs(lvmetad_state *s, const char *vgid, struct dm_config_tree *metadata_cft, struct dm_config_node *metadata)
75780{
75781 struct dm_config_tree *cft = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid), *pvmeta;
75782 struct dm_config_node *pv, *res, *out_pvs = cft ? dm_config_find_node(cft->root, "outdated_pvs/pv_list") : NULL;
75783 struct dm_config_value *pvs_v = out_pvs ? out_pvs->v : NULL;
75784 if (!pvs_v)
75785 return;
75786 if (!(res = make_config_node(metadata_cft, "outdated_pvs", metadata_cft->root, 0)))
75787 return; /* oops */
75788 res->sib = metadata->child;
75789 metadata->child = res;
75790 for (; pvs_v && pvs_v->type != DM_CFG_EMPTY_ARRAY; pvs_v = pvs_v->next) {
75791 pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvs_v->v.str);
75792 if (!pvmeta) {
75793 WARN(s, "metadata for PV %s not found", pvs_v->v.str);
75794 continue;
75795 }
75796 if (!(pv = dm_config_clone_node(metadata_cft, pvmeta->root, 0)))
75797 continue;
75798 pv->key = dm_config_find_str(pv, "pvmeta/id", NULL);
75799 pv->sib = res->child;
75800 res->child = pv;
75801 }
75802}
75803
75804static response vg_lookup(lvmetad_state *s, request r)
75805{
75806 struct dm_config_tree *cft;
75807 struct dm_config_node *metadata, *n;
75808 struct vg_info *info;
75809 response res = { 0 };
75810 const char *uuid = daemon_request_str(r, "uuid", NULL);
75811 const char *name = daemon_request_str(r, "name", NULL);
75812 int count = 0;
75813
75814 buffer_init( &res.buffer );
75815
75816 if (!uuid && !name) {
75817 ERROR(s, "vg_lookup with no uuid or name");
75818 return reply_unknown("VG not found");
75819
75820 } else if (!uuid || !name) {
75821 DEBUGLOG(s, "vg_lookup vgid %s name %s needs lookup",
75822 uuid ?: "none", name ?: "none");
75823
75824 if (name && !uuid)
75825 uuid = dm_hash_lookup_with_count(s->vgname_to_vgid, name, &count);
75826 else if (uuid && !name)
75827 name = dm_hash_lookup(s->vgid_to_vgname, uuid);
75828
75829 if (name && uuid && (count > 1)) {
75830 DEBUGLOG(s, "vg_lookup name %s vgid %s found %d vgids",
75831 name, uuid, count);
75832 return daemon_reply_simple("multiple", "reason = %s", "Multiple VGs found with same name", NULL);
75833 }
75834
75835 if (!uuid || !name)
75836 return reply_unknown("VG not found");
75837
75838 } else {
75839 char *name_lookup = dm_hash_lookup(s->vgid_to_vgname, uuid);
75840 char *uuid_lookup = dm_hash_lookup_with_val(s->vgname_to_vgid, name, uuid, strlen(uuid) + 1);
75841
75842 /* FIXME: comment out these sanity checks when not testing */
75843
75844 if (!name_lookup || !uuid_lookup) {
75845 ERROR(s, "vg_lookup vgid %s name %s found incomplete mapping uuid %s name %s",
75846 uuid, name, uuid_lookup ?: "none", name_lookup ?: "none");
75847 return reply_unknown("VG mapping incomplete");
75848 } else if (strcmp(name_lookup, name) || strcmp(uuid_lookup, uuid)) {
75849 ERROR(s, "vg_lookup vgid %s name %s found inconsistent mapping uuid %s name %s",
75850 uuid, name, uuid_lookup, name_lookup);
75851 return reply_unknown("VG mapping inconsistent");
75852 }
75853 }
75854
75855 DEBUGLOG(s, "vg_lookup vgid %s name %s", uuid ?: "none", name ?: "none");
75856
75857 cft = dm_hash_lookup(s->vgid_to_metadata, uuid);
75858 if (!cft || !cft->root) {
75859 return reply_unknown("UUID not found");
75860 }
75861
75862 metadata = cft->root;
75863 if (!(res.cft = dm_config_create()))
75864 goto nomem_un;
75865
75866 /* The response field */
75867 if (!(res.cft->root = n = dm_config_create_node(res.cft, "response")))
75868 goto nomem_un;
75869
75870 if (!(n->v = dm_config_create_value(cft)))
75871 goto nomem_un;
75872
75873 n->parent = res.cft->root;
75874 n->v->type = DM_CFG_STRING;
75875 n->v->v.str = "OK";
75876
75877 if (!(n = n->sib = dm_config_create_node(res.cft, "name")))
75878 goto nomem_un;
75879
75880 if (!(n->v = dm_config_create_value(res.cft)))
75881 goto nomem_un;
75882
75883 n->parent = res.cft->root;
75884 n->v->type = DM_CFG_STRING;
75885 n->v->v.str = name;
75886
75887 /* The metadata section */
75888 if (!(n = n->sib = dm_config_clone_node(res.cft, metadata, 1)))
75889 goto nomem_un;
75890 n->parent = res.cft->root;
75891
75892 if (!update_pv_status(s, res.cft, n))
75893 goto nomem;
75894 chain_outdated_pvs(s, uuid, res.cft, n);
75895
75896 if (s->flags & GLFL_INVALID)
75897 add_last_node(res.cft, "global_invalid");
75898
75899 info = dm_hash_lookup(s->vgid_to_info, uuid);
75900 if (info && (info->flags & VGFL_INVALID)) {
75901 if (!add_last_node(res.cft, "vg_invalid"))
75902 goto nomem;
75903 }
75904
75905 return res;
75906
75907nomem_un:
75908nomem:
75909 reply_fail("out of memory");
75910 ERROR(s, "vg_lookup vgid %s name %s out of memory.", uuid ?: "none", name ?: "none");
75911 ERROR(s, "lvmetad could not be updated and is aborting.");
75912 exit(EXIT_FAILURE);
75913}
75914
75915static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_pvids);
75916
75917enum update_pvid_mode { UPDATE_ONLY, REMOVE_EMPTY, MARK_OUTDATED };
75918
75919/* You need to be holding the pvid_to_vgid lock already to call this. */
75920static int _update_pvid_to_vgid(lvmetad_state *s, struct dm_config_tree *vg,
75921 const char *vgid, int mode)
75922{
75923 struct dm_config_node *pv;
75924 struct dm_hash_table *to_check;
75925 struct dm_hash_node *n;
75926 const char *pvid;
75927 char *vgid_old;
75928 char *vgid_dup;
75929 const char *check_vgid;
75930 int r = 0;
75931
75932 if (!vgid)
75933 return 0;
75934
75935 if (!(to_check = dm_hash_create(32)))
75936 goto abort_daemon;
75937
75938 for (pv = pvs(vg->root); pv; pv = pv->sib) {
75939 if (!(pvid = dm_config_find_str(pv->child, "id", NULL))) {
75940 ERROR(s, "PV has no id for update_pvid_to_vgid");
75941 continue;
75942 }
75943
75944 vgid_old = dm_hash_lookup(s->pvid_to_vgid, pvid);
75945
75946 if ((mode == REMOVE_EMPTY) && vgid_old) {
75947 /* This copies the vgid_old string, doesn't reference it. */
75948 if (!dm_hash_insert(to_check, vgid_old, (void*) 1)) {
75949 ERROR(s, "update_pvid_to_vgid out of memory for hash insert vgid_old %s", vgid_old);
75950 goto abort_daemon;
75951 }
75952 }
75953
75954 if (mode == MARK_OUTDATED)
75955 mark_outdated_pv(s, vgid, pvid);
75956
75957 if (!(vgid_dup = dm_strdup(vgid))) {
75958 ERROR(s, "update_pvid_to_vgid out of memory for vgid %s", vgid);
75959 goto abort_daemon;
75960 }
75961
75962 if (!dm_hash_insert(s->pvid_to_vgid, pvid, vgid_dup)) {
75963 ERROR(s, "update_pvid_to_vgid out of memory for hash insert vgid %s", vgid_dup);
75964 dm_free(vgid_dup);
75965 goto abort_daemon;
75966 }
75967
75968 /* pvid_to_vgid no longer references vgid_old */
75969 dm_free(vgid_old);
75970
75971 DEBUGLOG(s, "moving PV %s to VG %s", pvid, vgid);
75972 }
75973
75974 dm_hash_iterate(n, to_check) {
75975 check_vgid = dm_hash_get_key(to_check, n);
75976 vg_remove_if_missing(s, check_vgid, 0);
75977 }
75978
75979 r = 1;
75980 dm_hash_destroy(to_check);
75981
75982 return r;
75983
75984abort_daemon:
75985 ERROR(s, "lvmetad could not be updated and is aborting.");
75986 if (to_check)
75987 dm_hash_destroy(to_check);
75988 exit(EXIT_FAILURE);
75989}
75990
75991/* A pvid map lock needs to be held if update_pvids = 1. */
75992static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids)
75993{
75994 struct dm_config_tree *meta_lookup;
75995 struct dm_config_tree *outdated_pvs_lookup;
75996 struct vg_info *info_lookup;
75997 char *name_lookup = NULL;
75998 char *vgid_lookup = NULL;
75999
76000 /* get data pointers from hash table so they can be freed */
76001
76002 info_lookup = dm_hash_lookup(s->vgid_to_info, vgid);
76003 meta_lookup = dm_hash_lookup(s->vgid_to_metadata, vgid);
76004 name_lookup = dm_hash_lookup(s->vgid_to_vgname, vgid);
76005 outdated_pvs_lookup = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid);
76006 if (name_lookup)
76007 vgid_lookup = dm_hash_lookup_with_val(s->vgname_to_vgid, name_lookup, vgid, strlen(vgid) + 1);
76008
76009 /* remove hash table mappings */
76010
76011 dm_hash_remove(s->vgid_to_info, vgid);
76012 dm_hash_remove(s->vgid_to_metadata, vgid);
76013 dm_hash_remove(s->vgid_to_vgname, vgid);
76014 dm_hash_remove(s->vgid_to_outdated_pvs, vgid);
76015 if (name_lookup)
76016 dm_hash_remove_with_val(s->vgname_to_vgid, name_lookup, vgid, strlen(vgid) + 1);
76017
76018 /* update_pvid_to_vgid will clear/free the pvid_to_vgid hash */
76019 if (update_pvids && meta_lookup)
76020 (void) _update_pvid_to_vgid(s, meta_lookup, "#orphan", 0);
76021
76022 /* free the unmapped data */
76023
76024 if (info_lookup)
76025 dm_free(info_lookup);
76026 if (meta_lookup)
76027 dm_config_destroy(meta_lookup);
76028 if (name_lookup)
76029 dm_free(name_lookup);
76030 if (outdated_pvs_lookup)
76031 dm_config_destroy(outdated_pvs_lookup);
76032 if (vgid_lookup)
76033 dm_free(vgid_lookup);
76034 return 1;
76035}
76036
76037/* The VG must be locked. */
76038static int vg_remove_if_missing(lvmetad_state *s, const char *vgid, int update_pvids)
76039{
76040 struct dm_config_tree *vg;
76041 struct dm_config_node *pv;
76042 const char *vgid_check;
76043 const char *pvid;
76044 int missing = 1;
76045
76046 if (!vgid)
76047 return 0;
76048
76049 if (!(vg = dm_hash_lookup(s->vgid_to_metadata, vgid)))
76050 return 1;
76051
76052 for (pv = pvs(vg->root); pv; pv = pv->sib) {
76053 if (!(pvid = dm_config_find_str(pv->child, "id", NULL)))
76054 continue;
76055
76056 if ((vgid_check = dm_hash_lookup(s->pvid_to_vgid, pvid)) &&
76057 dm_hash_lookup(s->pvid_to_pvmeta, pvid) &&
76058 !strcmp(vgid, vgid_check))
76059 missing = 0; /* at least one PV is around */
76060 }
76061
76062 if (missing) {
76063 DEBUGLOG(s, "removing empty VG %s", vgid);
76064 remove_metadata(s, vgid, update_pvids);
76065 }
76066
76067 return 1;
76068}
76069
76070/*
76071 * Remove all hash table references to arg_name and arg_vgid
76072 * so that new metadata using this name and/or vgid can be added
76073 * without interference previous data.
76074 *
76075 * This is used if a command updates metadata in the cache,
76076 * but update_metadata finds that what's in the cache is not
76077 * consistent with a normal transition between old and new
76078 * metadata. If this happens, it assumes that the command
76079 * is providing the correct metadata, so it first calls this
76080 * function to purge all records of the old metadata so the
76081 * new metadata can be added.
76082 */
76083
76084static void _purge_metadata(lvmetad_state *s, const char *arg_name, const char *arg_vgid)
76085{
76086 char *rem_vgid;
76087
76088 remove_metadata(s, arg_vgid, 1);
76089
76090 if ((rem_vgid = dm_hash_lookup_with_val(s->vgname_to_vgid, arg_name, arg_vgid, strlen(arg_vgid) + 1))) {
76091 dm_hash_remove_with_val(s->vgname_to_vgid, arg_name, arg_vgid, strlen(arg_vgid) + 1);
76092 dm_free(rem_vgid);
76093 }
76094}
76095
76096/*
76097 * Updates for new vgid and new metadata.
76098 *
76099 * Remove any existing vg_info struct since it will be
76100 * recreated by lvmlockd if/when needed.
76101 *
76102 * Remove any existing outdated pvs since their metadata
76103 * will no longer be associated with this VG.
76104 */
76105
76106static int _update_metadata_new_vgid(lvmetad_state *s,
76107 const char *arg_name,
76108 const char *old_vgid,
76109 const char *new_vgid,
76110 struct dm_config_tree *old_meta,
76111 struct dm_config_tree *new_meta)
76112{
76113 struct vg_info *rem_info;
76114 struct dm_config_tree *rem_outdated;
76115 char *new_vgid_dup = NULL;
76116 char *arg_name_dup = NULL;
76117 int abort_daemon = 0;
76118 int retval = 0;
76119
76120 if (!(new_vgid_dup = dm_strdup(new_vgid)))
76121 goto ret;
76122
76123 if (!(arg_name_dup = dm_strdup(arg_name)))
76124 goto ret;
76125
76126 /*
76127 * Temporarily orphan the PVs in the old metadata.
76128 */
76129 if (!_update_pvid_to_vgid(s, old_meta, "#orphan", 0)) {
76130 ERROR(s, "update_metadata_new_vgid failed to move PVs for %s old_vgid %s", arg_name, old_vgid);
76131 abort_daemon = 1;
76132 goto ret;
76133 }
76134
76135 /*
76136 * Remove things related to the old vgid. (like remove_metadata)
76137 */
76138
76139 if ((rem_info = dm_hash_lookup(s->vgid_to_info, old_vgid))) {
76140 dm_hash_remove(s->vgid_to_info, old_vgid);
76141 dm_free(rem_info);
76142 }
76143
76144 if ((rem_outdated = dm_hash_lookup(s->vgid_to_outdated_pvs, old_vgid))) {
76145 dm_hash_remove(s->vgid_to_outdated_pvs, old_vgid);
76146 dm_config_destroy(rem_outdated);
76147 }
76148
76149 dm_hash_remove(s->vgid_to_metadata, old_vgid);
76150 dm_config_destroy(old_meta);
76151 old_meta = NULL;
76152
76153 dm_hash_remove_with_val(s->vgname_to_vgid, arg_name, old_vgid, strlen(old_vgid) + 1);
76154 dm_hash_remove(s->vgid_to_vgname, old_vgid);
76155 dm_free((char *)old_vgid);
76156 old_vgid = NULL;
76157
76158 /*
76159 * Insert things with the new vgid.
76160 */
76161
76162 if (!dm_hash_insert(s->vgid_to_metadata, new_vgid, new_meta)) {
76163 ERROR(s, "update_metadata_new_vgid out of memory for meta hash insert for %s %s", arg_name, new_vgid);
76164 abort_daemon = 1;
76165 goto out;
76166 }
76167
76168 if (!dm_hash_insert(s->vgid_to_vgname, new_vgid, arg_name_dup)) {
76169 ERROR(s, "update_metadata_new_vgid out of memory for name hash insert for %s %s", arg_name, new_vgid);
76170 abort_daemon = 1;
76171 goto out;
76172 }
76173
76174 if (!dm_hash_insert_allow_multiple(s->vgname_to_vgid, arg_name, new_vgid_dup, strlen(new_vgid_dup) + 1)) {
76175 ERROR(s, "update_metadata_new_vgid out of memory for vgid hash insert for %s %s", arg_name, new_vgid);
76176 abort_daemon = 1;
76177 goto out;
76178 }
76179
76180 /*
76181 * Reassign PVs based on the new metadata.
76182 */
76183 if (!_update_pvid_to_vgid(s, new_meta, new_vgid, 1)) {
76184 ERROR(s, "update_metadata_new_name failed to update PVs for %s %s", arg_name, new_vgid);
76185 abort_daemon = 1;
76186 goto out;
76187 }
76188
76189 DEBUGLOG(s, "update_metadata_new_vgid is done for %s %s", arg_name, new_vgid);
76190 retval = 1;
76191out:
76192ret:
76193 if (!new_vgid_dup || !arg_name_dup || abort_daemon) {
76194 ERROR(s, "lvmetad could not be updated and is aborting.");
76195 exit(EXIT_FAILURE);
76196 }
76197
76198 if (!retval && new_meta)
76199 dm_config_destroy(new_meta);
76200 return retval;
76201}
76202
76203/*
76204 * Updates for new name and new metadata.
76205 *
76206 * Remove any existing vg_info struct since it will be
76207 * recreated by lvmlockd if/when needed.
76208 *
76209 * Remove any existing outdated pvs since their metadata
76210 * will no longer be associated with this VG.
76211 */
76212
76213static int _update_metadata_new_name(lvmetad_state *s,
76214 const char *arg_vgid,
76215 const char *old_name,
76216 const char *new_name,
76217 struct dm_config_tree *old_meta,
76218 struct dm_config_tree *new_meta)
76219{
76220 struct vg_info *rem_info;
76221 struct dm_config_tree *rem_outdated;
76222 char *new_name_dup = NULL;
76223 char *arg_vgid_dup = NULL;
76224 int abort_daemon = 0;
76225 int retval = 0;
76226
76227 if (!(new_name_dup = dm_strdup(new_name)))
76228 goto ret;
76229
76230 if (!(arg_vgid_dup = dm_strdup(arg_vgid)))
76231 goto ret;
76232
76233 /*
76234 * Temporarily orphan the PVs in the old metadata.
76235 */
76236 if (!_update_pvid_to_vgid(s, old_meta, "#orphan", 0)) {
76237 ERROR(s, "update_metadata_new_name failed to move PVs for old_name %s %s", old_name, arg_vgid);
76238 abort_daemon = 1;
76239 goto ret;
76240 }
76241
76242 /*
76243 * Remove things related to the old name.
76244 */
76245
76246 if ((rem_info = dm_hash_lookup(s->vgid_to_info, arg_vgid))) {
76247 dm_hash_remove(s->vgid_to_info, arg_vgid);
76248 dm_free(rem_info);
76249 }
76250
76251 if ((rem_outdated = dm_hash_lookup(s->vgid_to_outdated_pvs, arg_vgid))) {
76252 dm_hash_remove(s->vgid_to_outdated_pvs, arg_vgid);
76253 dm_config_destroy(rem_outdated);
76254 }
76255
76256 dm_hash_remove(s->vgid_to_metadata, arg_vgid);
76257 dm_config_destroy(old_meta);
76258 old_meta = NULL;
76259
76260 dm_hash_remove(s->vgid_to_vgname, arg_vgid);
76261 dm_hash_remove_with_val(s->vgname_to_vgid, old_name, arg_vgid, strlen(arg_vgid) + 1);
76262 dm_free((char *)old_name);
76263 old_name = NULL;
76264
76265 /*
76266 * Insert things with the new name.
76267 */
76268
76269 if (!dm_hash_insert(s->vgid_to_metadata, arg_vgid, new_meta)) {
76270 ERROR(s, "update_metadata_new_name out of memory for meta hash insert for %s %s", new_name, arg_vgid);
76271 abort_daemon = 1;
76272 goto out;
76273 }
76274
76275 if (!dm_hash_insert(s->vgid_to_vgname, arg_vgid, new_name_dup)) {
76276 ERROR(s, "update_metadata_new_name out of memory for name hash insert for %s %s", new_name, arg_vgid);
76277 abort_daemon = 1;
76278 goto out;
76279 }
76280
76281 if (!dm_hash_insert_allow_multiple(s->vgname_to_vgid, new_name, arg_vgid_dup, strlen(arg_vgid_dup) + 1)) {
76282 ERROR(s, "update_metadata_new_name out of memory for vgid hash insert for %s %s", new_name, arg_vgid);
76283 abort_daemon = 1;
76284 goto out;
76285 }
76286
76287 /*
76288 * Reassign PVs based on the new metadata.
76289 */
76290 if (!_update_pvid_to_vgid(s, new_meta, arg_vgid, 1)) {
76291 ERROR(s, "update_metadata_new_name failed to update PVs for %s %s", new_name, arg_vgid);
76292 abort_daemon = 1;
76293 goto out;
76294 }
76295
76296 DEBUGLOG(s, "update_metadata_new_name is done for %s %s", new_name, arg_vgid);
76297 retval = 1;
76298out:
76299ret:
76300 if (!new_name_dup || !arg_vgid_dup || abort_daemon) {
76301 ERROR(s, "lvmetad could not be updated and is aborting.");
76302 exit(EXIT_FAILURE);
76303 }
76304
76305 if (!retval && new_meta)
76306 dm_config_destroy(new_meta);
76307 return retval;
76308}
76309
76310
76311/*
76312 * Add new entries to all hash tables.
76313 */
76314
76315static int _update_metadata_add_new(lvmetad_state *s, const char *new_name, const char *new_vgid,
76316 struct dm_config_tree *new_meta)
76317{
76318 char *new_name_dup = NULL;
76319 char *new_vgid_dup = NULL;
76320 int abort_daemon = 0;
76321 int retval = 0;
76322
76323 DEBUGLOG(s, "update_metadata_add_new for %s %s", new_name, new_vgid);
76324
76325 if (!(new_name_dup = dm_strdup(new_name)))
76326 goto out_free;
76327
76328 if (!(new_vgid_dup = dm_strdup(new_vgid)))
76329 goto out_free;
76330
76331 if (!dm_hash_insert(s->vgid_to_metadata, new_vgid, new_meta)) {
76332 ERROR(s, "update_metadata_add_new out of memory for meta hash insert for %s %s", new_name, new_vgid);
76333 abort_daemon = 1;
76334 goto out;
76335 }
76336
76337 if (!dm_hash_insert(s->vgid_to_vgname, new_vgid, new_name_dup)) {
76338 ERROR(s, "update_metadata_add_new out of memory for name hash insert for %s %s", new_name, new_vgid);
76339 abort_daemon = 1;
76340 goto out;
76341 }
76342
76343 if (!dm_hash_insert_allow_multiple(s->vgname_to_vgid, new_name, new_vgid_dup, strlen(new_vgid_dup) + 1)) {
76344 ERROR(s, "update_metadata_add_new out of memory for vgid hash insert for %s %s", new_name, new_vgid);
76345 abort_daemon = 1;
76346 goto out;
76347 }
76348
76349 if (!_update_pvid_to_vgid(s, new_meta, new_vgid, 1)) {
76350 ERROR(s, "update_metadata_add_new failed to update PVs for %s %s", new_name, new_vgid);
76351 abort_daemon = 1;
76352 goto out;
76353 }
76354
76355 DEBUGLOG(s, "update_metadata_add_new is done for %s %s", new_name, new_vgid);
76356 retval = 1;
76357out:
76358out_free:
76359 if (!new_name_dup || !new_vgid_dup || abort_daemon) {
76360 if (new_name_dup)
76361 dm_free(new_name_dup);
76362 if (new_vgid_dup)
76363 dm_free(new_vgid_dup);
76364 ERROR(s, "lvmetad could not be updated and is aborting.");
76365 exit(EXIT_FAILURE);
76366 }
76367
76368 if (!retval && new_meta)
76369 dm_config_destroy(new_meta);
76370 return retval;
76371}
76372
76373/*
76374 * No locks need to be held. The pointers are never used outside of the scope of
76375 * this function, so they can be safely destroyed after update_metadata returns
76376 * (anything that might have been retained is copied).
76377 *
76378 * When this is called from pv_found, the metadata was read from a single
76379 * PV specified by the pvid arg and ret_old_seq is not NULL. The metadata
76380 * should match the existing metadata (matching seqno). If the metadata
76381 * from pv_found has a smaller seqno, it means that the PV is outdated
76382 * (was previously used in the VG and now reappeared after changes to the VG).
76383 * The next command to access the VG will erase the outdated PV and then clear
76384 * the outdated pv record here. If the metadata from pv_found has a larger
76385 * seqno than the existing metadata, it means ... (existing pvs are outdated?)
76386 *
76387 * When this is caleld from vg_update, the metadata is from a command that
76388 * has new metadata that should replace the existing metadata.
76389 * pvid and ret_old_seq are both NULL.
76390 */
76391
76392static int _update_metadata(lvmetad_state *s, const char *arg_name, const char *arg_vgid,
76393 struct dm_config_node *new_metadata, int *ret_old_seq,
76394 const char *pvid)
76395{
76396 struct dm_config_tree *old_meta = NULL;
76397 struct dm_config_tree *new_meta = NULL;
76398 const char *arg_name_lookup; /* name lookup result from arg_vgid */
76399 const char *arg_vgid_lookup; /* vgid lookup result from arg_name */
76400 const char *old_name = NULL;
76401 const char *new_name = NULL;
76402 const char *old_vgid = NULL;
76403 const char *new_vgid = NULL;
76404 const char *new_metadata_vgid;
76405 int new_seq;
76406 int old_seq = -1;
76407 int needs_repair = 0;
76408 int abort_daemon = 0;
76409 int retval = 0;
76410 int count = 0;
76411
76412 if (!arg_vgid || !arg_name) {
76413 ERROR(s, "update_metadata missing args arg_vgid %s arg_name %s pvid %s",
76414 arg_vgid ?: "none", arg_name ?: "none", pvid ?: "none");
76415 return 0;
76416 }
76417
76418 DEBUGLOG(s, "update_metadata begin arg_vgid %s arg_name %s pvid %s",
76419 arg_vgid, arg_name, pvid ?: "none");
76420
76421 /*
76422 * Begin by figuring out what has changed:
76423 * . the VG could be new - found no existing record of the vgid or name.
76424 * . the VG could have a new vgid - found an existing record of the name.
76425 * . the VG could have a new name - found an existing record of the vgid.
76426 * . the VG could have unchanged vgid and name - found existing record of both.
76427 */
76428
76429 arg_name_lookup = dm_hash_lookup(s->vgid_to_vgname, arg_vgid);
76430 arg_vgid_lookup = dm_hash_lookup_with_val(s->vgname_to_vgid, arg_name, arg_vgid, strlen(arg_vgid) + 1);
76431
76432 /*
76433 * A new VG when there is no existing record of the name or vgid args.
76434 */
76435 if (!arg_name_lookup && !arg_vgid_lookup) {
76436 new_vgid = arg_vgid;
76437 new_name = arg_name;
76438
76439 DEBUGLOG(s, "update_metadata new name %s and new vgid %s",
76440 new_name, new_vgid);
76441 goto update;
76442 }
76443
76444 /*
76445 * An existing name has a new vgid (new_vgid = arg_vgid).
76446 * A lookup of the name arg was successful in finding arg_vgid_lookup,
76447 * but that resulting vgid doesn't match the arg_vgid.
76448 */
76449 if (arg_vgid_lookup && strcmp(arg_vgid_lookup, arg_vgid)) {
76450 if (arg_name_lookup) {
76451 /*
76452 * This shouldn't happen.
76453 * arg_vgid should be new and should not map to any name.
76454 */
76455 ERROR(s, "update_metadata arg_vgid %s arg_name %s unexpected arg_name_lookup %s",
76456 arg_vgid, arg_name, arg_name_lookup);
76457 needs_repair = 1;
76458 goto update;
76459 }
76460
76461 new_vgid = arg_vgid;
76462 old_vgid = dm_hash_lookup_with_count(s->vgname_to_vgid, arg_name, &count);
76463
76464 /*
76465 * FIXME: this ensures that arg_name maps to only one existing
76466 * VG (old_vgid), because if it maps to multiple vgids, then we
76467 * don't know which one should get the new vgid (arg_vgid). If
76468 * this function was given both the existing name and existing
76469 * vgid to identify the VG, then this wouldn't be a problem.
76470 * But as it is now, the vgid arg to this function is the new
76471 * vgid and the existing VG is specified only by name.
76472 */
76473 if (old_vgid && (count > 1)) {
76474 ERROR(s, "update_metadata arg_vgid %s arg_name %s found %d vgids for name",
76475 arg_vgid, arg_name, count);
76476 old_vgid = NULL;
76477 }
76478
76479 if (!old_vgid) {
76480 /* This shouldn't happen. */
76481 ERROR(s, "update_metadata arg_vgid %s arg_name %s no old_vgid",
76482 arg_vgid, arg_name);
76483 needs_repair = 1;
76484 goto update;
76485 }
76486
76487 if (!(old_meta = dm_hash_lookup(s->vgid_to_metadata, old_vgid))) {
76488 /* This shouldn't happen. */
76489 ERROR(s, "update_metadata arg_vgid %s arg_name %s old_vgid %s no old_meta",
76490 arg_vgid, arg_name, old_vgid);
76491 needs_repair = 1;
76492 goto update;
76493 }
76494
76495 DEBUGLOG(s, "update_metadata existing name %s has new vgid %s old vgid %s",
76496 arg_name, new_vgid, old_vgid);
76497 goto update;
76498 }
76499
76500 /*
76501 * An existing vgid has a new name (new_name = arg_name).
76502 * A lookup of the vgid arg was successful in finding arg_name_lookup,
76503 * but that resulting name doesn't match the arg_name.
76504 */
76505 if (arg_name_lookup && strcmp(arg_name_lookup, arg_name)) {
76506 if (arg_vgid_lookup) {
76507 /*
76508 * This shouldn't happen.
76509 * arg_name should be new and should not map to any vgid.
76510 */
76511 ERROR(s, "update_metadata arg_vgid %s arg_name %s unexpected arg_vgid_lookup %s",
76512 arg_vgid, arg_name, arg_vgid_lookup);
76513 needs_repair = 1;
76514 goto update;
76515 }
76516
76517 new_name = arg_name;
76518 old_name = dm_hash_lookup(s->vgid_to_vgname, arg_vgid);
76519
76520 if (!old_name) {
76521 /* This shouldn't happen. */
76522 ERROR(s, "update_metadata arg_vgid %s arg_name %s no old_name",
76523 arg_vgid, arg_name);
76524 needs_repair = 1;
76525 goto update;
76526 }
76527
76528 if (!(old_meta = dm_hash_lookup(s->vgid_to_metadata, arg_vgid))) {
76529 /* This shouldn't happen. */
76530 ERROR(s, "update_metadata arg_vgid %s arg_name %s old_name %s no old_meta",
76531 arg_vgid, arg_name, old_name);
76532 needs_repair = 1;
76533 goto update;
76534 }
76535
76536 DEBUGLOG(s, "update_metadata existing vgid %s has new name %s old name %s",
76537 arg_vgid, new_name, old_name);
76538 goto update;
76539 }
76540
76541 /*
76542 * An existing VG has unchanged name and vgid.
76543 */
76544 if (!new_vgid && !new_name) {
76545 if (!arg_vgid_lookup || !arg_name_lookup) {
76546 /* This shouldn't happen. */
76547 ERROR(s, "update_metadata arg_vgid %s arg_name %s missing lookups vgid %s name %s",
76548 arg_vgid ?: "none", arg_name ?: "none", arg_vgid_lookup ?: "none", arg_name_lookup ?: "none");
76549 needs_repair = 1;
76550 goto update;
76551 }
76552
76553 if (strcmp(arg_name_lookup, arg_name)) {
76554 /* This shouldn't happen. */
76555 ERROR(s, "update_metadata arg_vgid %s arg_name %s mismatch arg_name_lookup %s",
76556 arg_vgid, arg_name, arg_name_lookup);
76557 needs_repair = 1;
76558 goto update;
76559 }
76560
76561 if (strcmp(arg_vgid_lookup, arg_vgid)) {
76562 /* This shouldn't happen. Two VGs with the same name is handled above. */
76563 ERROR(s, "update_metadata arg_vgid %s arg_name %s mismatch arg_vgid_lookup %s",
76564 arg_vgid, arg_name, arg_vgid_lookup);
76565 needs_repair = 1;
76566 goto update;
76567 }
76568
76569 /* old_vgid == arg_vgid, and old_name == arg_name */
76570
76571 if (!(old_meta = dm_hash_lookup(s->vgid_to_metadata, arg_vgid))) {
76572 /* This shouldn't happen. */
76573 ERROR(s, "update_metadata arg_vgid %s arg_name %s no old_meta",
76574 arg_vgid, arg_name);
76575 needs_repair = 1;
76576 goto update;
76577 }
76578
76579 DEBUGLOG(s, "update_metadata existing vgid %s and existing name %s",
76580 arg_vgid, arg_name);
76581 goto update;
76582 }
76583
76584 update:
76585 filter_metadata(new_metadata); /* sanitize */
76586
76587 /*
76588 * FIXME: verify that there's at least one PV in common between
76589 * the old and new metadata?
76590 */
76591
76592 if (!(new_meta = dm_config_create()) ||
76593 !(new_meta->root = dm_config_clone_node(new_meta, new_metadata, 0))) {
76594 ERROR(s, "update_metadata out of memory for new metadata for %s %s",
76595 arg_name, arg_vgid);
76596 /* FIXME: should we purge the old metadata here? */
76597 retval = 0;
76598 goto out;
76599 }
76600
76601 /*
76602 * Get the seqno from existing (old) and new metadata and perform
76603 * sanity checks for transitions that generally shouldn't happen.
76604 * Sometimes ignore the new metadata and leave the existing metadata
76605 * alone, and sometimes purge the existing metadata and add the new.
76606 * This often depends on whether the new metadata comes from a single
76607 * PV (via pv_found) that's been scanned, or a vg_update sent from a
76608 * command.
76609 */
76610
76611 new_seq = dm_config_find_int(new_metadata, "metadata/seqno", -1);
76612
76613 if (old_meta)
76614 old_seq = dm_config_find_int(old_meta->root, "metadata/seqno", -1);
76615
76616 if (ret_old_seq)
76617 *ret_old_seq = old_meta ? old_seq : new_seq;
76618
76619 /*
76620 * The new metadata has an invalid seqno.
76621 * This shouldn't happen, but if it does, ignore the new metadata.
76622 */
76623 if (new_seq <= 0) {
76624 ERROR(s, "update_metadata ignore new metadata because of invalid seqno for %s %s",
76625 arg_vgid, arg_name);
76626 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76627 retval = 0;
76628 goto out;
76629 }
76630
76631 /*
76632 * The new metadata is missing an internal vgid.
76633 * This shouldn't happen, but if it does, ignore the new metadata.
76634 */
76635 if (!(new_metadata_vgid = dm_config_find_str(new_meta->root, "metadata/id", NULL))) {
76636 ERROR(s, "update_metadata has no internal vgid for %s %s",
76637 arg_name, arg_vgid);
76638 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76639 retval = 0;
76640 goto out;
76641 }
76642
76643 /*
76644 * The new metadata internal vgid doesn't match the arg vgid.
76645 * This shouldn't happen, but if it does, ignore the new metadata.
76646 */
76647 if (strcmp(new_metadata_vgid, arg_vgid)) {
76648 ERROR(s, "update_metadata has bad internal vgid %s for %s %s",
76649 new_metadata_vgid, arg_name, arg_vgid);
76650 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76651 retval = 0;
76652 goto out;
76653 }
76654
76655 /*
76656 * A single PV appears with metadata that's inconsistent with
76657 * existing, ignore the PV. FIXME: make it outdated?
76658 */
76659 if (pvid && needs_repair) {
76660 ERROR(s, "update_metadata ignore inconsistent metadata on PV %s seqno %d for %s %s seqno %d",
76661 pvid, new_seq, arg_vgid, arg_name, old_seq);
76662 if (old_meta)
76663 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76664 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76665 retval = 0;
76666 goto out;
76667 }
76668
76669 /*
76670 * A VG update with metadata that's inconsistent with existing.
76671 */
76672 if (!pvid && needs_repair) {
76673 ERROR(s, "update_metadata inconsistent with cache for vgid %s and name %s",
76674 arg_vgid, arg_name);
76675 if (old_meta)
76676 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76677 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76678 abort_daemon = 1;
76679 retval = 0;
76680 goto out;
76681 }
76682
76683 /*
76684 * A single PV appears with metadata that's older than the existing,
76685 * e.g. an PV that had been in the VG has reappeared after the VG changed.
76686 * old PV: the PV that lvmetad was told about first
76687 * new PV: the PV that lvmetad is being told about here, second
76688 * old_seq: the larger seqno on the old PV, for the newer version of the VG
76689 * new_seq: the smaller seqno on the new PV, for the older version of the VG
76690 *
76691 * So, the new PV (by notification order) is "older" (in terms of
76692 * VG seqno) than the old PV.
76693 *
76694 * Make the new PV outdated so it'll be cleared and keep the existing
76695 * metadata from the old PV.
76696 */
76697 if (pvid && (old_seq > 0) && (new_seq < old_seq)) {
76698 ERROR(s, "update_metadata ignoring outdated metadata on PV %s seqno %d for %s %s seqno %d",
76699 pvid, new_seq, arg_vgid, arg_name, old_seq);
76700 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76701 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76702 mark_outdated_pv(s, arg_vgid, pvid);
76703 retval = 0;
76704 goto out;
76705 }
76706
76707 /*
76708 * A single PV appears with metadata that's newer than the existing,
76709 * e.g. a PV has been found with VG metadata that is newer than the
76710 * VG metdata we know about. This can happen when scanning PVs after
76711 * an outdated PV (with an older version of the VG metadata) has
76712 * reappeared. The rescanning may initially scan the outdated PV
76713 * and notify lvmetad about it, and then scan a current PV from
76714 * the VG and notify lvmetad about it.
76715 * old PV: the PV that lvmetad was told about first
76716 * new PV: the PV that lvmetad is being told about here, second
76717 * old_seq: the smaller seqno on the old PV, for the older version of the VG
76718 * new_seq: the larger seqno on the new PV, for the newer version of the VG
76719 *
76720 * Make the existing PVs outdated, and use the new metadata.
76721 */
76722 if (pvid && (old_seq > 0) && (new_seq > old_seq)) {
76723 ERROR(s, "update_metadata found newer metadata on PV %s seqno %d for %s %s seqno %d",
76724 pvid, new_seq, arg_vgid, arg_name, old_seq);
76725 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76726 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76727 _update_pvid_to_vgid(s, old_meta, arg_vgid, MARK_OUTDATED);
76728 }
76729
76730 /*
76731 * The existing/old metadata has an invalid seqno.
76732 * This shouldn't happen, but if it does, purge old and add the new.
76733 */
76734 if (old_meta && (old_seq <= 0)) {
76735 ERROR(s, "update_metadata bad old seqno %d for %s %s",
76736 old_seq, arg_name, arg_vgid);
76737 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76738 _purge_metadata(s, arg_name, arg_vgid);
76739 new_name = arg_name;
76740 new_vgid = arg_vgid;
76741 old_name = NULL;
76742 old_vgid = NULL;
76743 old_meta = NULL;
76744 old_seq = -1;
76745 }
76746
76747 /*
76748 * A single PV appears with a seqno matching existing metadata,
76749 * but unmatching metadata content. This shouldn't happen,
76750 * but if it does, ignore the PV. FIXME: make it outdated?
76751 */
76752 if (pvid && (new_seq == old_seq) && compare_config(new_metadata, old_meta->root)) {
76753 ERROR(s, "update_metadata from pv %s same seqno %d with unmatching data for %s %s",
76754 pvid, new_seq, arg_name, arg_vgid);
76755 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76756 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76757 retval = 0;
76758 goto out;
76759 }
76760
76761 /*
76762 * A VG update with metadata matching existing seqno but unmatching content.
76763 * This shouldn't happen, but if it does, purge existing and add the new.
76764 */
76765 if (!pvid && (new_seq == old_seq) && compare_config(new_metadata, old_meta->root)) {
76766 ERROR(s, "update_metadata same seqno %d with unmatching data for %s %s",
76767 new_seq, arg_name, arg_vgid);
76768 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76769 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76770 _purge_metadata(s, arg_name, arg_vgid);
76771 new_name = arg_name;
76772 new_vgid = arg_vgid;
76773 old_name = NULL;
76774 old_vgid = NULL;
76775 old_meta = NULL;
76776 old_seq = -1;
76777 }
76778
76779 /*
76780 * A VG update with metadata older than existing. VG updates should
76781 * have increasing seqno. This shouldn't happen, but if it does,
76782 * purge existing and add the new.
76783 */
76784 if (!pvid && (new_seq < old_seq)) {
76785 ERROR(s, "update_metadata new seqno %d less than old seqno %d for %s %s",
76786 new_seq, old_seq, arg_name, arg_vgid);
76787 DEBUGLOG_cft(s, "OLD: ", old_meta->root);
76788 DEBUGLOG_cft(s, "NEW: ", new_metadata);
76789 _purge_metadata(s, arg_name, arg_vgid);
76790 new_name = arg_name;
76791 new_vgid = arg_vgid;
76792 old_name = NULL;
76793 old_vgid = NULL;
76794 old_meta = NULL;
76795 old_seq = -1;
76796 }
76797
76798 /*
76799 * All the checks are done, do one of the four possible updates
76800 * outlined above:
76801 */
76802
76803 /*
76804 * Add metadata for a new VG to the cache.
76805 */
76806 if (new_name && new_vgid)
76807 return _update_metadata_add_new(s, new_name, new_vgid, new_meta);
76808
76809 /*
76810 * Update cached metadata for a VG with a new vgid.
76811 */
76812 if (new_vgid)
76813 return _update_metadata_new_vgid(s, arg_name, old_vgid, new_vgid, old_meta, new_meta);
76814
76815 /*
76816 * Update cached metadata for a renamed VG.
76817 */
76818 if (new_name)
76819 return _update_metadata_new_name(s, arg_vgid, old_name, new_name, old_meta, new_meta);
76820
76821 /*
76822 * If the old and new seqnos are the same, we've already compared the
76823 * old/new metadata and verified it's the same, so there's no reason
76824 * to replace old meta with new meta.
76825 */
76826 if (old_seq == new_seq) {
76827 DEBUGLOG(s, "update_metadata skipped for %s %s seqno %d is unchanged",
76828 arg_name, arg_vgid, old_seq);
76829 dm_config_destroy(new_meta);
76830 new_meta = NULL;
76831 retval = 1;
76832 goto out;
76833 }
76834
76835 /*
76836 * Update cached metdata for a VG with unchanged name and vgid.
76837 * Replace the old metadata with the new metadata.
76838 * old_meta is the old copy of the metadata from the cache.
76839 * new_meta is the new copy of the metadata from the command.
76840 */
76841 DEBUGLOG(s, "update_metadata for %s %s from %d to %d", arg_name, arg_vgid, old_seq, new_seq);
76842
76843 /*
76844 * The PVs in the VG may have changed in the new metadata, so
76845 * temporarily orphan all of the PVs in the existing VG.
76846 * The PVs that are still in the VG will be reassigned to this
76847 * VG below by the next call to _update_pvid_to_vgid().
76848 */
76849 if (!_update_pvid_to_vgid(s, old_meta, "#orphan", 0)) {
76850 ERROR(s, "update_metadata failed to move PVs for %s %s", arg_name, arg_vgid);
76851 abort_daemon = 1;
76852 retval = 0;
76853 goto out;
76854 }
76855
76856 /*
76857 * The only hash table update that is needed is the actual
76858 * metadata config tree in vgid_to_metadata. The VG name
76859 * and vgid are unchanged.
76860 */
76861
76862 dm_hash_remove(s->vgid_to_metadata, arg_vgid);
76863 dm_config_destroy(old_meta);
76864 old_meta = NULL;
76865
76866 if (!dm_hash_insert(s->vgid_to_metadata, arg_vgid, new_meta)) {
76867 ERROR(s, "update_metadata out of memory for hash insert for %s %s", arg_name, arg_vgid);
76868 abort_daemon = 1;
76869 retval = 0;
76870 goto out;
76871 }
76872
76873 /*
76874 * Map the PVs in the new metadata to the vgid.
76875 * All pre-existing PVs were temporarily orphaned above.
76876 * Previous PVs that were removed from the VG will not
76877 * be remapped. New PVs that were added to the VG will
76878 * be newly mapped to this vgid, and previous PVs that
76879 * remain in the VG will be remapped to the VG again.
76880 */
76881 if (!_update_pvid_to_vgid(s, new_meta, arg_vgid, 1)) {
76882 ERROR(s, "update_metadata failed to update PVs for %s %s", arg_name, arg_vgid);
76883 abort_daemon = 1;
76884 retval = 0;
76885 } else {
76886 DEBUGLOG(s, "update_metadata is done for %s %s", arg_name, arg_vgid);
76887 retval = 1;
76888 }
76889
76890out:
76891 if (abort_daemon) {
76892 ERROR(s, "lvmetad could not be updated is aborting.");
76893 exit(EXIT_FAILURE);
76894 }
76895
76896 if (!retval && new_meta)
76897 dm_config_destroy(new_meta);
76898 return retval;
76899}
76900
76901static response pv_gone(lvmetad_state *s, request r)
76902{
76903 const char *arg_pvid = NULL;
76904 char *old_pvid = NULL;
76905 const char *pvid;
76906 int64_t device;
76907 struct dm_config_tree *pvmeta;
76908 char *vgid;
76909
76910 arg_pvid = daemon_request_str(r, "uuid", NULL);
76911 device = daemon_request_int(r, "device", 0);
76912
76913 if (!arg_pvid && device > 0)
76914 old_pvid = dm_hash_lookup_binary(s->device_to_pvid, &device, sizeof(device));
76915
76916 if (!arg_pvid && !old_pvid) {
76917 DEBUGLOG(s, "pv_gone device %" PRIu64 " not found", device);
76918 return reply_unknown("device not in cache");
76919 }
76920
76921 pvid = arg_pvid ? arg_pvid : old_pvid;
76922
76923 DEBUGLOG(s, "pv_gone %s device %" PRIu64, pvid ?: "none", device);
76924
76925 if (!(pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, pvid))) {
76926 DEBUGLOG(s, "pv_gone %s device %" PRIu64 " has no PV metadata",
76927 pvid ?: "none", device);
76928 return reply_unknown("PVID does not exist");
76929 }
76930
76931 vgid = dm_hash_lookup(s->pvid_to_vgid, pvid);
76932
76933 dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device));
76934 dm_hash_remove(s->pvid_to_pvmeta, pvid);
76935
76936 if (vgid) {
76937 char *vgid_dup;
76938 /*
76939 * vg_remove_if_missing will clear and free the pvid_to_vgid
76940 * mappings for this vg, which will free the "vgid" string that
76941 * was returned above from the pvid_to_vgid lookup.
76942 */
76943 if (!(vgid_dup = dm_strdup(vgid)))
76944 return reply_fail("out of memory");
76945
76946 vg_remove_if_missing(s, vgid_dup, 1);
76947 dm_free(vgid_dup);
76948 vgid_dup = NULL;
76949 vgid = NULL;
76950 }
76951
76952 dm_config_destroy(pvmeta);
76953 if (old_pvid)
76954 dm_free(old_pvid);
76955
76956 return daemon_reply_simple("OK", NULL );
76957}
76958
76959static response pv_clear_all(lvmetad_state *s, request r)
76960{
76961 DEBUGLOG(s, "pv_clear_all");
76962
76963 destroy_metadata_hashes(s);
76964 create_metadata_hashes(s);
76965
76966 return daemon_reply_simple("OK", NULL);
76967}
76968
76969/*
76970 * Returns 1 if PV metadata exists for all PVs in a VG.
76971 */
76972static int _vg_is_complete(lvmetad_state *s, struct dm_config_tree *vgmeta)
76973{
76974 struct dm_config_node *vg = vgmeta->root;
76975 struct dm_config_node *pv;
76976 int complete = 1;
76977 const char *pvid;
76978
76979 for (pv = pvs(vg); pv; pv = pv->sib) {
76980 if (!(pvid = dm_config_find_str(pv->child, "id", NULL)))
76981 continue;
76982
76983 if (!dm_hash_lookup(s->pvid_to_pvmeta, pvid)) {
76984 complete = 0;
76985 break;
76986 }
76987 }
76988
76989 return complete;
76990}
76991
76992/*
76993 * pv_found: a PV has appeared and been scanned
76994 * It contains PV metadata, and optionally VG metadata.
76995 * Both kinds of metadata should be added to the cache
76996 * and hash table mappings related to the PV and device
76997 * should be updated.
76998 *
76999 * Input values from request:
77000 * . arg_pvmeta: PV metadata from the found pv
77001 * . arg_pvid: pvid from arg_pvmeta (pvmeta/id)
77002 * . arg_device: device from arg_pvmeta (pvmeta/device)
77003 * . arg_vgmeta: VG metadata from the found pv (optional)
77004 * . arg_name: VG name from found pv (optional)
77005 * . arg_vgid: VG vgid from arg_vgmeta (optional)
77006 *
77007 * Search for existing mappings in hash tables:
77008 * . pvid_to_pvmeta (which produces pvid to device)
77009 * . device_to_pvid
77010 * . pvid_to_vgid
77011 *
77012 * Existing data from cache:
77013 * . old_pvmeta: result of pvid_to_pvmeta(arg_pvid)
77014 * . arg_device_lookup: result of old_pvmeta:pvmeta/device using arg_pvid
77015 * . arg_pvid_lookup: result of device_to_pvid(arg_device)
77016 * . arg_vgid_lookup: result of pvid_to_vgid(arg_pvid)
77017 *
77018 * When arg_pvid doesn't match arg_pvid_lookup:
77019 * . a new PV replaces a previous PV on arg_device
77020 * . prev_pvid_on_dev: set to arg_pvid_lookup, pvid of the prev PV
77021 * . prev_pvmeta_on_dev: result pvid_to_pvmeta(prev_pvid_on_dev)
77022 * . prev_vgid_on_dev: result of pvid_to_vgid(prev_pvid_on_dev)
77023 *
77024 * Old PV on old device
77025 * . no PV/device mappings have changed
77026 * . arg_pvid_lookup == arg_pvid && arg_device_lookup == arg_device
77027 * . arg_device was used to look up a PV and found a PV with
77028 * the same pvid as arg_pvid
77029 * . arg_pvid was used to look up a PV and found a PV on the
77030 * same device as arg_device
77031 * . new_pvmeta may be more recent than old_pvmeta
77032 *
77033 * New PV on new device
77034 * . add new mappings in hash tables
77035 * . !arg_pvid_lookup && !arg_device_lookup
77036 * . arg_device was used to look up a PV and found nothing
77037 * . arg_pvid was used to look up a PV and found nothing
77038 *
77039 * New PV on old device
77040 * . a new PV replaces a previous PV on a device
77041 * . arg_pvid_lookup != arg_pvid
77042 * . arg_device was used to look up a PV and found a PV with
77043 * a different pvid than arg_pvid
77044 * . replace existing mappings for arg_device and arg_pvid
77045 * . replace existing old_pvmeta with new_pvmeta
77046 * . remove arg_device association with prev PV (prev_pvid_on_dev)
77047 * . possibly remove prev PV (if arg_device was previously a duplicate)
77048 *
77049 * Old PV on new device
77050 * . a duplicate PV
77051 * . arg_device_lookup != arg_device
77052 * . arg_pvid was used to look up a PV, and found that the PV
77053 * has a different device than arg_device.
77054 */
77055
77056static response pv_found(lvmetad_state *s, request r)
77057{
77058 struct dm_config_node *arg_vgmeta = NULL;
77059 struct dm_config_node *arg_pvmeta = NULL;
77060 struct dm_config_tree *old_pvmeta = NULL;
77061 struct dm_config_tree *new_pvmeta = NULL;
77062 struct dm_config_tree *prev_pvmeta_on_dev = NULL;
77063 struct dm_config_tree *vgmeta = NULL;
77064 const char *arg_pvid = NULL;
77065 const char *arg_pvid_lookup = NULL;
77066 const char *new_pvid = NULL;
77067 const char *new_pvid_dup = NULL;
77068 const char *arg_name = NULL;
77069 const char *arg_vgid = NULL;
77070 const char *arg_vgid_lookup = NULL;
77071 const char *prev_pvid_on_dev = NULL;
77072 const char *prev_vgid_on_dev = NULL;
77073 const char *vg_status = NULL;
77074 uint64_t arg_device = 0;
77075 uint64_t arg_device_lookup = 0;
77076 uint64_t new_device = 0;
77077 uint64_t old_device = 0;
77078 int arg_seqno = -1;
77079 int old_seqno = -1;
77080 int vg_status_seqno = -1;
77081 int changed = 0;
77082
77083 /*
77084 * New input values.
77085 */
77086
77087 if (!(arg_pvmeta = dm_config_find_node(r.cft->root, "pvmeta"))) {
77088 ERROR(s, "Ignore PV without PV metadata");
77089 return reply_fail("Ignore PV without PV metadata");
77090 }
77091
77092 if (!(arg_pvid = daemon_request_str(r, "pvmeta/id", NULL))) {
77093 ERROR(s, "Ignore PV without PV UUID");
77094 return reply_fail("Ignore PV without PV UUID");
77095 }
77096
77097 if (!dm_config_get_uint64(arg_pvmeta, "pvmeta/device", &arg_device)) {
77098 ERROR(s, "Ignore PV without device pvid %s", arg_pvid);
77099 return reply_fail("Ignore PV without device");
77100 }
77101
77102 if ((arg_vgmeta = dm_config_find_node(r.cft->root, "metadata"))) {
77103 arg_name = daemon_request_str(r, "vgname", NULL);
77104 arg_vgid = daemon_request_str(r, "metadata/id", NULL);
77105 arg_seqno = daemon_request_int(r, "metadata/seqno", -1);
77106
77107 if (!arg_name || !arg_vgid || (arg_seqno < 0))
77108 ERROR(s, "Ignore VG metadata from PV %s", arg_pvid);
77109 if (!arg_name)
77110 return reply_fail("Ignore VG metadata from PV without VG name");
77111 if (!arg_vgid)
77112 return reply_fail("Ignore VG metadata from PV without VG vgid");
77113 if (arg_seqno < 0)
77114 return reply_fail("Ignore VG metadata from PV without VG seqno");
77115 }
77116
77117 /* Make a copy of the new pvmeta that can be inserted into cache. */
77118 if (!(new_pvmeta = dm_config_create()) ||
77119 !(new_pvmeta->root = dm_config_clone_node(new_pvmeta, arg_pvmeta, 0))) {
77120 ERROR(s, "pv_found out of memory for new pvmeta %s", arg_pvid);
77121 goto nomem;
77122 }
77123
77124 /*
77125 * Existing (old) cache values.
77126 */
77127
77128 old_pvmeta = dm_hash_lookup(s->pvid_to_pvmeta, arg_pvid);
77129 if (old_pvmeta)
77130 dm_config_get_uint64(old_pvmeta->root, "pvmeta/device", &arg_device_lookup);
77131
77132 arg_pvid_lookup = dm_hash_lookup_binary(s->device_to_pvid, &arg_device, sizeof(arg_device));
77133
77134 /*
77135 * Determine which of the four possible changes is happening
77136 * by comparing the existing/old and new values:
77137 * old PV, old device
77138 * new PV, new device
77139 * new PV, old device
77140 * old PV, new device
77141 */
77142
77143 if (arg_pvid_lookup && arg_device_lookup &&
77144 (arg_device == arg_device_lookup) &&
77145 !strcmp(arg_pvid_lookup, arg_pvid)) {
77146 /*
77147 * Old PV on old device (existing values unchanged)
77148 */
77149 new_pvid = NULL;
77150 new_device = 0;
77151
77152 DEBUGLOG(s, "pv_found pvid %s on device %" PRIu64 " matches existing",
77153 arg_pvid, arg_device);
77154
77155 } else if (!arg_pvid_lookup && !arg_device_lookup) {
77156 /*
77157 * New PV on new device (no existing values)
77158 */
77159 new_pvid = arg_pvid;
77160 new_device = arg_device;
77161
77162 DEBUGLOG(s, "pv_found pvid %s on device %" PRIu64 " is new",
77163 arg_pvid, arg_device);
77164
77165 } else if (arg_pvid_lookup && strcmp(arg_pvid_lookup, arg_pvid)) {
77166 /*
77167 * New PV on old device (existing device reused for new PV)
77168 */
77169 new_pvid = arg_pvid;
77170 new_device = 0;
77171 prev_pvid_on_dev = arg_pvid_lookup;
77172 prev_pvmeta_on_dev = dm_hash_lookup(s->pvid_to_pvmeta, arg_pvid_lookup);
77173 prev_vgid_on_dev = dm_hash_lookup(s->pvid_to_vgid, arg_pvid_lookup);
77174
77175 DEBUGLOG(s, "pv_found pvid %s vgid %s on device %" PRIu64 " previous pvid %s vgid %s",
77176 arg_pvid, arg_vgid ?: "none", arg_device,
77177 prev_pvid_on_dev, prev_vgid_on_dev ?: "none");
77178
77179 } else if (arg_device_lookup && (arg_device_lookup != arg_device)) {
77180 /*
77181 * Old PV on new device (existing PV on a new device, i.e. duplicate)
77182 */
77183 new_device = arg_device;
77184 new_pvid = NULL;
77185 old_device = arg_device_lookup;
77186
77187 DEBUGLOG(s, "pv_found pvid %s vgid %s on device %" PRIu64 " duplicate %" PRIu64,
77188 arg_pvid, arg_vgid ?: "none", arg_device, arg_device_lookup);
77189
77190 } else {
77191 ERROR(s, "pv_found pvid %s vgid %s on device %" PRIu64 " unknown lookup %s %s %" PRIu64,
77192 arg_pvid,
77193 arg_vgid ?: "none",
77194 arg_device,
77195 arg_pvid_lookup ?: "none",
77196 arg_vgid_lookup ?: "none",
77197 arg_device_lookup);
77198 return reply_fail("Ignore PV for unknown state");
77199 }
77200
77201 /*
77202 * Make changes to hashes device_to_pvid and pvid_to_pvmeta for each case.
77203 */
77204
77205 if (!new_pvid && !new_device) {
77206 /*
77207 * Old PV on old device (unchanged)
77208 * . add new_pvmeta, replacing old_pvmeta
77209 */
77210 if (compare_config(old_pvmeta->root, new_pvmeta->root))
77211 changed |= 1;
77212
77213 if (!dm_hash_insert(s->pvid_to_pvmeta, arg_pvid, new_pvmeta))
77214 goto nomem_free1;
77215
77216 } else if (new_pvid && new_device) {
77217 /*
77218 * New PV on new device (new entry)
77219 * . add new_device/new_pvid mapping
77220 * . add new_pvmeta
77221 */
77222 changed |= 1;
77223
77224 DEBUGLOG(s, "pv_found new entry device_to_pvid %" PRIu64 " to %s",
77225 new_device, new_pvid);
77226
77227 if (!(new_pvid_dup = dm_strdup(new_pvid)))
77228 goto nomem_free1;
77229
77230 if (!dm_hash_insert_binary(s->device_to_pvid, &new_device, sizeof(new_device), (char *)new_pvid_dup))
77231 goto nomem_free2;
77232
77233 if (!dm_hash_insert(s->pvid_to_pvmeta, new_pvid, new_pvmeta))
77234 goto nomem_free1;
77235
77236 } else if (new_pvid && !new_device) {
77237 /*
77238 * New PV on old device (existing device reused for new PV).
77239 * The previous PV on arg_device is replaced by the new one.
77240 *
77241 * Don't free prev_pvid or prev_vgid strings because they are
77242 * used at the end to check the VG metadata.
77243 */
77244 changed |= 1;
77245
77246 if (prev_pvmeta_on_dev) {
77247 DEBUGLOG(s, "pv_found new pvid device_to_pvid %" PRIu64 " to %s removes prev pvid %s",
77248 arg_device, new_pvid, prev_pvid_on_dev);
77249
77250 dm_hash_remove(s->pvid_to_pvmeta, prev_pvid_on_dev);
77251 dm_config_destroy(prev_pvmeta_on_dev);
77252 prev_pvmeta_on_dev = NULL;
77253
77254 /* removes arg_device/prev_pvid_on_dev mapping */
77255 dm_hash_remove_binary(s->device_to_pvid, &arg_device, sizeof(arg_device));
77256
77257 /*
77258 * The new PV replacing the prev PV was copied from
77259 * another existing PV, creating a duplicate PV which
77260 * we ignore.
77261 */
77262 if (dm_hash_lookup(s->pvid_to_pvmeta, new_pvid)) {
77263 DEBUGLOG(s, "pv_found ignore duplicate device %" PRIu64 " of existing PV for pvid %s",
77264 arg_device, arg_pvid);
77265 dm_config_destroy(new_pvmeta);
77266 s->flags |= GLFL_DISABLE;
77267 s->flags |= GLFL_DISABLE_REASON_DUPLICATES;
77268 return reply_fail("Ignore duplicate PV");
77269 }
77270 }
77271
77272
77273 if (!(new_pvid_dup = dm_strdup(new_pvid)))
77274 goto nomem_free1;
77275
77276 if (!dm_hash_insert_binary(s->device_to_pvid, &arg_device, sizeof(arg_device), (char *)new_pvid_dup))
77277 goto nomem_free2;
77278
77279 if (!dm_hash_insert(s->pvid_to_pvmeta, new_pvid, new_pvmeta))
77280 goto nomem_free1;
77281
77282 } else if (new_device && !new_pvid) {
77283 /*
77284 * Old PV on new device (duplicate)
77285 * Ignore it.
77286 */
77287 DEBUGLOG(s, "pv_found ignore duplicate device %" PRIu64 " of existing device %" PRIu64 " for pvid %s",
77288 new_device, old_device, arg_pvid);
77289 dm_config_destroy(new_pvmeta);
77290 s->flags |= GLFL_DISABLE;
77291 s->flags |= GLFL_DISABLE_REASON_DUPLICATES;
77292 return reply_fail("Ignore duplicate PV");
77293 }
77294
77295 if (old_pvmeta)
77296 dm_config_destroy(old_pvmeta);
77297
77298 /*
77299 * Update VG metadata cache with arg_vgmeta from the PV, or
77300 * if the PV holds no VG metadata, then look up the vgid and
77301 * name of the VG so we can check if the VG is complete.
77302 */
77303 if (arg_vgmeta) {
77304 DEBUGLOG(s, "pv_found pvid %s has VG %s %s seqno %d", arg_pvid, arg_name, arg_vgid, arg_seqno);
77305
77306 if (!_update_metadata(s, arg_name, arg_vgid, arg_vgmeta, &old_seqno, arg_pvid)) {
77307 ERROR(s, "Cannot use VG metadata for %s %s from PV %s on %" PRIu64,
77308 arg_name, arg_vgid, arg_pvid, arg_device);
77309 }
77310
77311 changed |= (old_seqno != arg_seqno);
77312 } else {
77313 arg_vgid = dm_hash_lookup(s->pvid_to_vgid, arg_pvid);
77314
77315 if (arg_vgid) {
77316 arg_name = dm_hash_lookup(s->vgid_to_vgname, arg_vgid);
77317 }
77318 }
77319
77320 /*
77321 * Check if the VG is complete (all PVs have been found) because
77322 * the reply indicates if the the VG is complete or partial.
77323 * The "vgmeta" from dm_hash_lookup will be a copy of arg_vgmeta that
77324 * was cloned and added to the cache by update_metadata.
77325 */
77326 if (!arg_vgid || !strcmp(arg_vgid, "#orphan")) {
77327 DEBUGLOG(s, "pv_found pvid %s on %" PRIu64 " not in VG %s",
77328 arg_pvid, arg_device, arg_vgid ?: "");
77329 vg_status = "orphan";
77330 goto prev_vals;
77331 }
77332
77333 if (!(vgmeta = dm_hash_lookup(s->vgid_to_metadata, arg_vgid))) {
77334 ERROR(s, "pv_found %s on %" PRIu64 " vgid %s no VG metadata found",
77335 arg_pvid, arg_device, arg_vgid);
77336 } else {
77337 vg_status = _vg_is_complete(s, vgmeta) ? "complete" : "partial";
77338 vg_status_seqno = dm_config_find_int(vgmeta->root, "metadata/seqno", -1);
77339 }
77340
77341 prev_vals:
77342 /*
77343 * If the device previously held a different VG (prev_vgid_on_dev),
77344 * then that VG should be removed if no devices are left for it.
77345 *
77346 * The mapping from the device's previous pvid to the previous vgid
77347 * is removed.
77348 */
77349
77350 if (prev_pvid_on_dev || prev_vgid_on_dev) {
77351 DEBUGLOG(s, "pv_found pvid %s on %" PRIu64 " had prev pvid %s prev vgid %s",
77352 arg_pvid, arg_device,
77353 prev_pvid_on_dev ?: "none",
77354 prev_vgid_on_dev ?: "none");
77355 }
77356
77357 if (prev_vgid_on_dev) {
77358 char *tmp_vgid;
77359
77360 if (!arg_vgid || strcmp(arg_vgid, prev_vgid_on_dev)) {
77361 tmp_vgid = dm_strdup(prev_vgid_on_dev);
77362 /* vg_remove_if_missing will clear and free
77363 the string pointed to by prev_vgid_on_dev. */
77364 vg_remove_if_missing(s, tmp_vgid, 1);
77365 dm_free(tmp_vgid);
77366 }
77367
77368 /* vg_remove_if_missing may have remapped prev_pvid_on_dev to orphan */
77369 if ((tmp_vgid = dm_hash_lookup(s->pvid_to_vgid, prev_pvid_on_dev))) {
77370 dm_hash_remove(s->pvid_to_vgid, prev_pvid_on_dev);
77371 dm_free(tmp_vgid);
77372 }
77373 }
77374
77375 /* This was unhashed from device_to_pvid above. */
77376 if (prev_pvid_on_dev)
77377 dm_free((void *)prev_pvid_on_dev);
77378
77379 return daemon_reply_simple("OK",
77380 "status = %s", vg_status,
77381 "changed = " FMTd64, (int64_t) changed,
77382 "vgid = %s", arg_vgid ? arg_vgid : "#orphan",
77383 "vgname = %s", arg_name ? arg_name : "#orphan",
77384 "seqno_before = " FMTd64, (int64_t) old_seqno,
77385 "seqno_after = " FMTd64, (int64_t) vg_status_seqno,
77386 NULL);
77387
77388 nomem_free2:
77389 dm_free((char *)new_pvid_dup);
77390 nomem_free1:
77391 dm_config_destroy(new_pvmeta);
77392 nomem:
77393 ERROR(s, "pv_found %s is out of memory.", arg_pvid);
77394 ERROR(s, "lvmetad could not be updated is aborting.");
77395 reply_fail("out of memory");
77396 exit(EXIT_FAILURE);
77397}
77398
77399static response vg_clear_outdated_pvs(lvmetad_state *s, request r)
77400{
77401 struct dm_config_tree *outdated_pvs;
77402 const char *vgid = daemon_request_str(r, "vgid", NULL);
77403
77404 if (!vgid)
77405 return reply_fail("need VG UUID");
77406
77407 DEBUGLOG(s, "vg_clear_outdated_pvs vgid %s", vgid);
77408
77409 if ((outdated_pvs = dm_hash_lookup(s->vgid_to_outdated_pvs, vgid))) {
77410 dm_config_destroy(outdated_pvs);
77411 dm_hash_remove(s->vgid_to_outdated_pvs, vgid);
77412 }
77413 return daemon_reply_simple("OK", NULL);
77414}
77415
77416static void vg_info_update(lvmetad_state *s, const char *uuid,
77417 struct dm_config_node *metadata)
77418{
77419 struct vg_info *info;
77420 int64_t cache_version;
77421
77422 cache_version = dm_config_find_int64(metadata, "metadata/seqno", -1);
77423 if (cache_version == -1)
77424 return;
77425
77426 info = (struct vg_info *) dm_hash_lookup(s->vgid_to_info, uuid);
77427 if (!info)
77428 return;
77429
77430 if (cache_version >= info->external_version)
77431 info->flags &= ~VGFL_INVALID;
77432}
77433
77434static response vg_update(lvmetad_state *s, request r)
77435{
77436 struct dm_config_node *metadata = dm_config_find_node(r.cft->root, "metadata");
77437 const char *vgid = daemon_request_str(r, "metadata/id", NULL);
77438 const char *vgname = daemon_request_str(r, "vgname", NULL);
77439
77440 DEBUGLOG(s, "vg_update vgid %s name %s", vgid ?: "none", vgname ?: "none");
77441
77442 if (metadata) {
77443 if (!vgid) {
77444 ERROR(s, "vg_update failed: need VG UUID");
77445 reply_fail("vg_update: need VG UUID");
77446 goto fail;
77447 }
77448 if (!vgname) {
77449 ERROR(s, "vg_update failed: need VG name");
77450 reply_fail("vg_update: need VG name");
77451 goto fail;
77452 }
77453 if (daemon_request_int(r, "metadata/seqno", -1) < 0) {
77454 ERROR(s, "vg_update failed: need VG seqno");
77455 reply_fail("vg_update: need VG seqno");
77456 goto fail;
77457 }
77458
77459 /* TODO defer metadata update here; add a separate vg_commit
77460 * call; if client does not commit, die */
77461
77462 if (!_update_metadata(s, vgname, vgid, metadata, NULL, NULL)) {
77463 ERROR(s, "vg_update failed: metadata update failed");
77464 reply_fail("vg_update: failed metadata update");
77465 goto fail;
77466 }
77467
77468 vg_info_update(s, vgid, metadata);
77469 }
77470 return daemon_reply_simple("OK", NULL);
77471
77472fail:
77473 ERROR(s, "lvmetad could not be updated is aborting.");
77474 exit(EXIT_FAILURE);
77475}
77476
77477static response vg_remove(lvmetad_state *s, request r)
77478{
77479 const char *vgid = daemon_request_str(r, "uuid", NULL);
77480
77481 if (!vgid)
77482 return reply_fail("need VG UUID");
77483
77484 DEBUGLOG(s, "vg_remove: %s", vgid);
77485
77486 remove_metadata(s, vgid, 1);
77487
77488 return daemon_reply_simple("OK", NULL);
77489}
77490
77491/*
77492 * Whether lvmetad is disabled is determined only by the single
77493 * flag GLFL_DISABLE. The REASON flags are only explanatory
77494 * additions to GLFL_DISABLE, and do not control the disabled state.
77495 * The REASON flags can accumulate if multiple reasons exist for
77496 * the disabled flag. When clearing GLFL_DISABLE, all REASON flags
77497 * are cleared. The caller clearing GLFL_DISABLE should only do so
77498 * when all the reasons for it have gone.
77499 */
77500
77501static response set_global_info(lvmetad_state *s, request r)
77502{
77503 const int global_invalid = daemon_request_int(r, "global_invalid", -1);
77504 const int global_disable = daemon_request_int(r, "global_disable", -1);
77505 const char *reason;
77506 uint32_t reason_flags = 0;
77507
77508 if ((reason = daemon_request_str(r, "disable_reason", NULL))) {
77509 if (strstr(reason, LVMETAD_DISABLE_REASON_DIRECT))
77510 reason_flags |= GLFL_DISABLE_REASON_DIRECT;
77511 if (strstr(reason, LVMETAD_DISABLE_REASON_LVM1))
77512 reason_flags |= GLFL_DISABLE_REASON_LVM1;
77513 if (strstr(reason, LVMETAD_DISABLE_REASON_DUPLICATES))
77514 reason_flags |= GLFL_DISABLE_REASON_DUPLICATES;
77515 if (strstr(reason, LVMETAD_DISABLE_REASON_VGRESTORE))
77516 reason_flags |= GLFL_DISABLE_REASON_VGRESTORE;
77517 }
77518
77519 if (global_invalid != -1) {
77520 DEBUGLOG(s, "set global info invalid from %d to %d",
77521 (s->flags & GLFL_INVALID) ? 1 : 0, global_invalid);
77522 }
77523
77524 if (global_disable != -1) {
77525 DEBUGLOG(s, "set global info disable from %d to %d %s",
77526 (s->flags & GLFL_DISABLE) ? 1 : 0, global_disable,
77527 reason ? reason : "");
77528 }
77529
77530 if (global_invalid == 1)
77531 s->flags |= GLFL_INVALID;
77532
77533 else if (global_invalid == 0)
77534 s->flags &= ~GLFL_INVALID;
77535
77536 if (global_disable == 1) {
77537 s->flags |= GLFL_DISABLE;
77538 s->flags |= reason_flags;
77539
77540 } else if (global_disable == 0) {
77541 s->flags &= ~GLFL_DISABLE;
77542 s->flags &= ~GLFL_DISABLE_REASON_ALL;
77543 }
77544
77545 return daemon_reply_simple("OK", NULL);
77546}
77547
77548#define REASON_BUF_SIZE 64
77549
77550/*
77551 * Save the time when "updating" begins, and the config setting for how long
77552 * the update is allowed to take. Before returning "updating" as the token
77553 * value in get_global_info, check if the update has exceeded the max allowed
77554 * time. If so, then return "none" as the current token value (i.e.
77555 * uninitialized), so that the command will repopulate our cache.
77556 *
77557 * This automatically clears a stuck update, where a command started to update
77558 * the cache and then failed, leaving the token set to "update in progress".
77559 */
77560
77561static response get_global_info(lvmetad_state *s, request r)
77562{
77563 char reason[REASON_BUF_SIZE];
77564 char flag_str[64];
77565 int pid;
77566
77567 /* This buffer should be large enough to hold all the possible reasons. */
77568
77569 memset(reason, 0, sizeof(reason));
77570
77571 pid = (int)daemon_request_int(r, "pid", 0);
77572
77573 if (s->flags & GLFL_DISABLE) {
77574 snprintf(reason, REASON_BUF_SIZE - 1, "%s%s%s%s",
77575 (s->flags & GLFL_DISABLE_REASON_DIRECT) ? LVMETAD_DISABLE_REASON_DIRECT "," : "",
77576 (s->flags & GLFL_DISABLE_REASON_LVM1) ? LVMETAD_DISABLE_REASON_LVM1 "," : "",
77577 (s->flags & GLFL_DISABLE_REASON_DUPLICATES) ? LVMETAD_DISABLE_REASON_DUPLICATES "," : "",
77578 (s->flags & GLFL_DISABLE_REASON_VGRESTORE) ? LVMETAD_DISABLE_REASON_VGRESTORE "," : "");
77579 }
77580
77581 if (!reason[0])
77582 strcpy(reason, "none");
77583
77584 /*
77585 * If the current update has timed out, then return
77586 * token of "none" which means "uninitialized" so that
77587 * the caller will repopulate lvmetad.
77588 */
77589 if (s->update_begin && s->update_timeout) {
77590 if (_monotonic_seconds() - s->update_begin >= s->update_timeout) {
77591 DEBUGLOG(s, "global info cancel update after timeout %d len %d begin %llu pid %d cmd %s",
77592 s->update_timeout,
77593 (int)(_monotonic_seconds() - s->update_begin),
77594 (unsigned long long)s->update_begin,
77595 s->update_pid, s->update_cmd);
77596 memset(s->token, 0, sizeof(s->token));
77597 s->update_begin = 0;
77598 s->update_timeout = 0;
77599 s->update_pid = 0;
77600 memset(s->update_cmd, 0, CMD_NAME_SIZE);
77601 }
77602 }
77603
77604 memset(flag_str, 0, sizeof(flag_str));
77605 if (s->flags & GLFL_INVALID)
77606 strcat(flag_str, "Invalid");
77607 if (s->flags & GLFL_DISABLE)
77608 strcat(flag_str, "Disable");
77609 if (!flag_str[0])
77610 strcat(flag_str, "none");
77611
77612 DEBUGLOG(s, "%d global info flags %s reason %s token %s update_pid %d",
77613 pid, flag_str, reason, s->token[0] ? s->token : "none", s->update_pid);
77614
77615 return daemon_reply_simple("OK", "global_invalid = " FMTd64, (int64_t)((s->flags & GLFL_INVALID) ? 1 : 0),
77616 "global_disable = " FMTd64, (int64_t)((s->flags & GLFL_DISABLE) ? 1 : 0),
77617 "disable_reason = %s", reason,
77618 "daemon_pid = " FMTd64, (int64_t)getpid(),
77619 "token = %s", s->token[0] ? s->token : "none",
77620 "update_cmd = %s", s->update_cmd,
77621 "update_pid = " FMTd64, (int64_t)s->update_pid,
77622 "update_begin = " FMTd64, (int64_t)s->update_begin,
77623 "update_timeout = " FMTd64, (int64_t)s->update_timeout,
77624 NULL);
77625}
77626
77627static response set_vg_info(lvmetad_state *s, request r)
77628{
77629 struct dm_config_tree *vg;
77630 struct vg_info *info;
77631 const char *name = NULL;
77632 const char *uuid = NULL;
77633 const int64_t new_version = daemon_request_int(r, "version", -1);
77634 int64_t cache_version = -1;
77635
77636 if (new_version == -1)
77637 goto out;
77638
77639 if (!(uuid = daemon_request_str(r, "uuid", NULL)))
77640 goto use_name;
77641
77642 if ((vg = dm_hash_lookup(s->vgid_to_metadata, uuid)))
77643 goto vers;
77644use_name:
77645 if (!(name = daemon_request_str(r, "name", NULL)))
77646 goto out;
77647
77648 if (!(uuid = dm_hash_lookup(s->vgname_to_vgid, name)))
77649 goto out;
77650
77651 /*
77652 * FIXME: if we only have the name and multiple VGs have that name,
77653 * then invalidate each of them.
77654 */
77655
77656 if (!(vg = dm_hash_lookup(s->vgid_to_metadata, uuid)))
77657 goto out;
77658vers:
77659 if (!new_version)
77660 goto inval;
77661
77662 cache_version = dm_config_find_int64(vg->root, "metadata/seqno", -1);
77663
77664 if (cache_version != -1 && new_version != -1 && cache_version >= new_version)
77665 goto out;
77666inval:
77667 DEBUGLOG(s, "set info VG name %s uuid %s cache_version %d new_version %d",
77668 name ?: "none", uuid ?: "none", (int)cache_version, (int)new_version);
77669
77670 info = dm_hash_lookup(s->vgid_to_info, uuid);
77671 if (!info) {
77672 info = malloc(sizeof(struct vg_info));
77673 if (!info)
77674 goto bad;
77675 memset(info, 0, sizeof(struct vg_info));
77676 if (!dm_hash_insert(s->vgid_to_info, uuid, (void*)info))
77677 goto bad;
77678 }
77679
77680 info->external_version = new_version;
77681 info->flags |= VGFL_INVALID;
77682
77683out:
77684 return daemon_reply_simple("OK", NULL);
77685bad:
77686 return reply_fail("out of memory");
77687}
77688
77689static void _dump_cft(struct buffer *buf, struct dm_hash_table *ht, const char *key_addr)
77690{
77691 struct dm_hash_node *n;
77692
77693 dm_hash_iterate(n, ht) {
77694 struct dm_config_tree *cft = dm_hash_get_data(ht, n);
77695 const char *key_backup = cft->root->key;
77696 cft->root->key = dm_config_find_str(cft->root, key_addr, "unknown");
77697 (void) dm_config_write_node(cft->root, buffer_line, buf);
77698 cft->root->key = key_backup;
77699 }
77700}
77701
77702static void _dump_pairs(struct buffer *buf, struct dm_hash_table *ht, const char *name, int int_key)
77703{
77704 char *append;
77705 struct dm_hash_node *n;
77706
77707 buffer_append(buf, name);
77708 buffer_append(buf, " {\n");
77709
77710 dm_hash_iterate(n, ht) {
77711 const char *key = dm_hash_get_key(ht, n),
77712 *val = dm_hash_get_data(ht, n);
77713 buffer_append(buf, " ");
77714 if (int_key)
77715 (void) dm_asprintf(&append, "%d = \"%s\"", *(const int*)key, val);
77716 else
77717 (void) dm_asprintf(&append, "%s = \"%s\"", key, val);
77718 if (append)
77719 buffer_append(buf, append);
77720 buffer_append(buf, "\n");
77721 dm_free(append);
77722 }
77723 buffer_append(buf, "}\n");
77724}
77725
77726static void _dump_info_version(struct buffer *buf, struct dm_hash_table *ht, const char *name, int int_key)
77727{
77728 char *append;
77729 struct dm_hash_node *n = dm_hash_get_first(ht);
77730 struct vg_info *info;
77731
77732 buffer_append(buf, name);
77733 buffer_append(buf, " {\n");
77734
77735 while (n) {
77736 const char *key = dm_hash_get_key(ht, n);
77737 info = dm_hash_get_data(ht, n);
77738 buffer_append(buf, " ");
77739 (void) dm_asprintf(&append, "%s = %lld", key, (long long)info->external_version);
77740 if (append)
77741 buffer_append(buf, append);
77742 buffer_append(buf, "\n");
77743 dm_free(append);
77744 n = dm_hash_get_next(ht, n);
77745 }
77746 buffer_append(buf, "}\n");
77747}
77748
77749static void _dump_info_flags(struct buffer *buf, struct dm_hash_table *ht, const char *name, int int_key)
77750{
77751 char *append;
77752 struct dm_hash_node *n = dm_hash_get_first(ht);
77753 struct vg_info *info;
77754
77755 buffer_append(buf, name);
77756 buffer_append(buf, " {\n");
77757
77758 while (n) {
77759 const char *key = dm_hash_get_key(ht, n);
77760 info = dm_hash_get_data(ht, n);
77761 buffer_append(buf, " ");
77762 (void) dm_asprintf(&append, "%s = %llx", key, (long long)info->flags);
77763 if (append)
77764 buffer_append(buf, append);
77765 buffer_append(buf, "\n");
77766 dm_free(append);
77767 n = dm_hash_get_next(ht, n);
77768 }
77769 buffer_append(buf, "}\n");
77770}
77771
77772static response dump(lvmetad_state *s)
77773{
77774 response res = { 0 };
77775 struct buffer *b = &res.buffer;
77776
77777 buffer_init(b);
77778
77779 /* Lock everything so that we get a consistent dump. */
77780
77781 buffer_append(b, "# VG METADATA\n\n");
77782 _dump_cft(b, s->vgid_to_metadata, "metadata/id");
77783
77784 buffer_append(b, "\n# PV METADATA\n\n");
77785 _dump_cft(b, s->pvid_to_pvmeta, "pvmeta/id");
77786
77787 buffer_append(b, "\n# VGID to VGNAME mapping\n\n");
77788 _dump_pairs(b, s->vgid_to_vgname, "vgid_to_vgname", 0);
77789
77790 buffer_append(b, "\n# VGID to outdated PVs mapping\n\n");
77791 _dump_cft(b, s->vgid_to_outdated_pvs, "outdated_pvs/vgid");
77792
77793 buffer_append(b, "\n# VGNAME to VGID mapping\n\n");
77794 _dump_pairs(b, s->vgname_to_vgid, "vgname_to_vgid", 0);
77795
77796 buffer_append(b, "\n# PVID to VGID mapping\n\n");
77797 _dump_pairs(b, s->pvid_to_vgid, "pvid_to_vgid", 0);
77798
77799 buffer_append(b, "\n# DEVICE to PVID mapping\n\n");
77800 _dump_pairs(b, s->device_to_pvid, "device_to_pvid", 1);
77801
77802 buffer_append(b, "\n# VGID to INFO version mapping\n\n");
77803 _dump_info_version(b, s->vgid_to_info, "vgid_to_info", 0);
77804
77805 buffer_append(b, "\n# VGID to INFO flags mapping\n\n");
77806 _dump_info_flags(b, s->vgid_to_info, "vgid_to_info", 0);
77807
77808 return res;
77809}
77810
77811static response handler(daemon_state s, client_handle h, request r)
77812{
77813 response res;
77814 lvmetad_state *state = s.private;
77815 char prev_token[128] = { 0 };
77816 const char *rq;
77817 const char *token;
77818 const char *cmd;
77819 int prev_in_progress, this_in_progress;
77820 int update_timeout;
77821 int pid;
77822 int cache_lock = 0;
77823 int info_lock = 0;
77824
77825 rq = daemon_request_str(r, "request", "NONE");
77826 token = daemon_request_str(r, "token", "NONE");
77827 pid = (int)daemon_request_int(r, "pid", 0);
77828 cmd = daemon_request_str(r, "cmd", "NONE");
77829 update_timeout = (int)daemon_request_int(r, "update_timeout", 0);
77830
77831 pthread_mutex_lock(&state->token_lock);
77832
77833 /*
77834 * token_update: start populating the cache, i.e. a full update.
77835 * To populate the lvmetad cache, a command does:
77836 *
77837 * - token_update, setting token to "update in progress"
77838 * (further requests during the update continue using
77839 * this same "update in progress" token)
77840 * - pv_clear_all, to clear the current cache
77841 * - pv_gone, for each PV
77842 * - pv_found, for each PV to populate the cache
77843 * - token_update, setting token to filter hash
77844 */
77845 if (!strcmp(rq, "token_update")) {
77846 prev_in_progress = !strcmp(state->token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
77847 this_in_progress = !strcmp(token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS);
77848
77849 if (!prev_in_progress && this_in_progress) {
77850 /* New update is starting (filter token is replaced by update token) */
77851
77852 memcpy(prev_token, state->token, 128);
77853 strncpy(state->token, token, 128);
77854 state->token[127] = 0;
77855 state->update_begin = _monotonic_seconds();
77856 state->update_timeout = update_timeout;
77857 state->update_pid = pid;
77858 strncpy(state->update_cmd, cmd, CMD_NAME_SIZE - 1);
77859
77860 DEBUGLOG(state, "token_update begin %llu timeout %d pid %d cmd %s",
77861 (unsigned long long)state->update_begin,
77862 state->update_timeout,
77863 state->update_pid,
77864 state->update_cmd);
77865
77866 } else if (prev_in_progress && this_in_progress) {
77867 /* Current update is cancelled and replaced by a new update */
77868
77869 DEBUGLOG(state, "token_update replacing pid %d begin %llu len %d cmd %s",
77870 state->update_pid,
77871 (unsigned long long)state->update_begin,
77872 (int)(_monotonic_seconds() - state->update_begin),
77873 state->update_cmd);
77874
77875 memcpy(prev_token, state->token, 128);
77876 strncpy(state->token, token, 128);
77877 state->token[127] = 0;
77878 state->update_begin = _monotonic_seconds();
77879 state->update_timeout = update_timeout;
77880 state->update_pid = pid;
77881 strncpy(state->update_cmd, cmd, CMD_NAME_SIZE - 1);
77882
77883 DEBUGLOG(state, "token_update begin %llu timeout %d pid %d cmd %s",
77884 (unsigned long long)state->update_begin,
77885 state->update_timeout,
77886 state->update_pid,
77887 state->update_cmd);
77888
77889 } else if (prev_in_progress && !this_in_progress) {
77890 /* Update is finished, update token is replaced by filter token */
77891
77892 if (state->update_pid != pid) {
77893 /* If a pid doing update was cancelled, ignore its token update at the end. */
77894 DEBUGLOG(state, "token_update ignored from cancelled update pid %d", pid);
77895 pthread_mutex_unlock(&state->token_lock);
77896
77897 return daemon_reply_simple("token_mismatch",
77898 "expected = %s", state->token,
77899 "received = %s", token,
77900 "update_pid = " FMTd64, (int64_t)state->update_pid,
77901 "reason = %s", "another command has populated the cache");
77902 }
77903
77904 DEBUGLOG(state, "token_update end len %d pid %d new token %s",
77905 (int)(_monotonic_seconds() - state->update_begin),
77906 state->update_pid, token);
77907
77908 memcpy(prev_token, state->token, 128);
77909 strncpy(state->token, token, 128);
77910 state->token[127] = 0;
77911 state->update_begin = 0;
77912 state->update_timeout = 0;
77913 state->update_pid = 0;
77914 memset(state->update_cmd, 0, CMD_NAME_SIZE);
77915 }
77916 pthread_mutex_unlock(&state->token_lock);
77917
77918 return daemon_reply_simple("OK",
77919 "prev_token = %s", prev_token,
77920 "update_pid = " FMTd64, (int64_t)state->update_pid,
77921 NULL);
77922 }
77923
77924 if (strcmp(token, state->token) && strcmp(rq, "dump") && strcmp(token, "skip")) {
77925 pthread_mutex_unlock(&state->token_lock);
77926
77927 DEBUGLOG(state, "token_mismatch current \"%s\" got \"%s\" from pid %d cmd %s",
77928 state->token, token, pid, cmd ?: "none");
77929
77930 return daemon_reply_simple("token_mismatch",
77931 "expected = %s", state->token,
77932 "received = %s", token,
77933 "update_pid = " FMTd64, (int64_t)state->update_pid,
77934 "reason = %s", "another command has populated the cache");
77935 }
77936
77937 /* If a pid doing update was cancelled, ignore its update messages. */
77938 if (!strcmp(token, LVMETAD_TOKEN_UPDATE_IN_PROGRESS) &&
77939 state->update_pid && pid && (state->update_pid != pid)) {
77940 pthread_mutex_unlock(&state->token_lock);
77941
77942 DEBUGLOG(state, "token_mismatch ignore update from pid %d current update pid %d",
77943 pid, state->update_pid);
77944
77945 return daemon_reply_simple("token_mismatch",
77946 "expected = %s", state->token,
77947 "received = %s", token,
77948 "update_pid = " FMTd64, (int64_t)state->update_pid,
77949 "reason = %s", "another command has populated the lvmetad cache");
77950 }
77951
77952 pthread_mutex_unlock(&state->token_lock);
77953
77954
77955 if (!strcmp(rq, "pv_found") ||
77956 !strcmp(rq, "pv_gone") ||
77957 !strcmp(rq, "vg_update") ||
77958 !strcmp(rq, "vg_remove") ||
77959 !strcmp(rq, "set_vg_info") ||
77960 !strcmp(rq, "pv_clear_all") ||
77961 !strcmp(rq, "vg_clear_outdated_pvs")) {
77962 pthread_rwlock_wrlock(&state->cache_lock);
77963 cache_lock = 1;
77964 goto do_rq;
77965 }
77966
77967 if (!strcmp(rq, "pv_lookup") ||
77968 !strcmp(rq, "vg_lookup") ||
77969 !strcmp(rq, "pv_list") ||
77970 !strcmp(rq, "vg_list") ||
77971 !strcmp(rq, "dump")) {
77972 pthread_rwlock_rdlock(&state->cache_lock);
77973 cache_lock = 1;
77974 goto do_rq;
77975 }
77976
77977 if (!strcmp(rq, "set_global_info") ||
77978 !strcmp(rq, "get_global_info")) {
77979 pthread_mutex_lock(&state->info_lock);
77980 info_lock = 1;
77981 goto do_rq;
77982 }
77983
77984 do_rq:
77985
77986 if (!strcmp(rq, "pv_found"))
77987 res = pv_found(state, r);
77988
77989 else if (!strcmp(rq, "pv_gone"))
77990 res = pv_gone(state, r);
77991
77992 else if (!strcmp(rq, "pv_clear_all"))
77993 res = pv_clear_all(state, r);
77994
77995 else if (!strcmp(rq, "pv_lookup"))
77996 res = pv_lookup(state, r);
77997
77998 else if (!strcmp(rq, "vg_update"))
77999 res = vg_update(state, r);
78000
78001 else if (!strcmp(rq, "vg_clear_outdated_pvs"))
78002 res = vg_clear_outdated_pvs(state, r);
78003
78004 else if (!strcmp(rq, "vg_remove"))
78005 res = vg_remove(state, r);
78006
78007 else if (!strcmp(rq, "vg_lookup"))
78008 res = vg_lookup(state, r);
78009
78010 else if (!strcmp(rq, "pv_list"))
78011 res = pv_list(state, r);
78012
78013 else if (!strcmp(rq, "vg_list"))
78014 res = vg_list(state, r);
78015
78016 else if (!strcmp(rq, "set_global_info"))
78017 res = set_global_info(state, r);
78018
78019 else if (!strcmp(rq, "get_global_info"))
78020 res = get_global_info(state, r);
78021
78022 else if (!strcmp(rq, "set_vg_info"))
78023 res = set_vg_info(state, r);
78024
78025 else if (!strcmp(rq, "dump"))
78026 res = dump(state);
78027
78028 else
78029 res = reply_fail("request not implemented");
78030
78031 if (cache_lock)
78032 pthread_rwlock_unlock(&state->cache_lock);
78033 if (info_lock)
78034 pthread_mutex_unlock(&state->info_lock);
78035
78036 return res;
78037}
78038
78039static int init(daemon_state *s)
78040{
78041 lvmetad_state *ls = s->private;
78042 ls->log = s->log;
78043
78044 pthread_mutex_init(&ls->token_lock, NULL);
78045 pthread_mutex_init(&ls->info_lock, NULL);
78046 pthread_rwlock_init(&ls->cache_lock, NULL);
78047 create_metadata_hashes(ls);
78048
78049 ls->token[0] = 0;
78050
78051 /* Set up stderr logging depending on the -l option. */
78052 if (!daemon_log_parse(ls->log, DAEMON_LOG_OUTLET_STDERR, ls->log_config, 1))
78053 return 0;
78054
78055 DEBUGLOG(s, "initialised state: vgid_to_metadata = %p", ls->vgid_to_metadata);
78056 if (!ls->pvid_to_vgid || !ls->vgid_to_metadata)
78057 return 0;
78058
78059 /* if (ls->initial_registrations)
78060 _process_initial_registrations(ds->initial_registrations); */
78061
78062 if (ls->idle)
78063 ls->idle->is_idle = 1;
78064
78065 return 1;
78066}
78067
78068static int fini(daemon_state *s)
78069{
78070 lvmetad_state *ls = s->private;
78071
78072 DEBUGLOG(s, "fini");
78073 destroy_metadata_hashes(ls);
78074 return 1;
78075}
78076
78077static int process_timeout_arg(const char *str, unsigned *max_timeouts)
78078{
78079 char *endptr;
78080 unsigned long l;
78081
78082 errno = 0;
78083 l = strtoul(str, &endptr, 10);
78084 if (errno || *endptr || l >= UINT_MAX)
78085 return 0;
78086
78087 *max_timeouts = (unsigned) l;
78088
78089 return 1;
78090}
78091
78092static void usage(const char *prog, FILE *file)
78093{
78094 fprintf(file, "Usage:\n"
78095 "%s [-V] [-h] [-f] [-l level[,level ...]] [-s path] [-t secs]\n\n"
78096 " -V Show version of lvmetad\n"
78097 " -h Show this help information\n"
78098 " -f Don't fork, run in the foreground\n"
78099 " -l Logging message levels (all,fatal,error,warn,info,wire,debug)\n"
78100 " -p Set path to the pidfile\n"
78101 " -s Set path to the socket to listen on\n"
78102 " -t Time to wait in seconds before shutdown on idle (missing or 0 = inifinite)\n\n", prog);
78103}
78104
78105int main(int argc, char *argv[])
78106{
78107 signed char opt;
78108 struct timeval timeout;
78109 daemon_idle di = { .ptimeout = &timeout };
78110 lvmetad_state ls = { .log_config = "" };
78111 daemon_state s = {
78112 .daemon_fini = fini,
78113 .daemon_init = init,
78114 .handler = handler,
78115 .name = "lvmetad",
78116 .pidfile = getenv("LVM_LVMETAD_PIDFILE") ? : LVMETAD_PIDFILE,
78117 .private = &ls,
78118 .protocol = "lvmetad",
78119 .protocol_version = 1,
78120 .socket_path = getenv("LVM_LVMETAD_SOCKET") ? : LVMETAD_SOCKET,
78121 };
78122
78123 // use getopt_long
78124 while ((opt = getopt(argc, argv, "?fhVl:p:s:t:")) != EOF) {
78125 switch (opt) {
78126 case 'h':
78127 usage(argv[0], stdout);
78128 exit(0);
78129 case '?':
78130 usage(argv[0], stderr);
78131 exit(0);
78132 case 'f':
78133 s.foreground = 1;
78134 break;
78135 case 'l':
78136 ls.log_config = optarg;
78137 break;
78138 case 'p':
78139 s.pidfile = optarg;
78140 break;
78141 case 's': // --socket
78142 s.socket_path = optarg;
78143 break;
78144 case 't':
78145 if (!process_timeout_arg(optarg, &di.max_timeouts)) {
78146 fprintf(stderr, "Invalid value of timeout parameter.\n");
78147 exit(EXIT_FAILURE);
78148 }
78149 /* 0 equals to wait indefinitely */
78150 if (di.max_timeouts)
78151 s.idle = ls.idle = &di;
78152 break;
78153 case 'V':
78154 printf("lvmetad version: " LVM_VERSION "\n");
78155 exit(1);
78156 }
78157 }
78158
78159 daemon_start(s);
78160
78161 return 0;
78162}
78163\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/test.sh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000360\013062740170\0021446\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/bin/bash
78164
78165export LD_LIBRARY_PATH="$1"
78166
78167test -n "$2" && {
78168 rm -f /var/run/lvmetad.{socket,pid}
78169 chmod +rx lvmetad
78170 valgrind ./lvmetad -f &
78171 PID=$!
78172 sleep 1
78173 ./testclient
78174 kill $PID
78175 exit 0
78176}
78177
78178sudo ./test.sh "$1" .
78179\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/lvmetad/lvmetactl.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000014375\013062740170\0022302\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
78180 * Copyright (C) 2014 Red Hat, Inc.
78181 *
78182 * This file is part of LVM2.
78183 *
78184 * This copyrighted material is made available to anyone wishing to use,
78185 * modify, copy, or redistribute it subject to the terms and conditions
78186 * of the GNU Lesser General Public License v.2.1.
78187 */
78188
78189#include "tool.h"
78190
78191#include "lvmetad-client.h"
78192
78193daemon_handle h;
78194
78195static void print_reply(daemon_reply reply)
78196{
78197 const char *a = daemon_reply_str(reply, "response", NULL);
78198 const char *b = daemon_reply_str(reply, "status", NULL);
78199 const char *c = daemon_reply_str(reply, "reason", NULL);
78200
78201 printf("response \"%s\" status \"%s\" reason \"%s\"\n",
78202 a ? a : "", b ? b : "", c ? c : "");
78203}
78204
78205int main(int argc, char **argv)
78206{
78207 daemon_reply reply;
78208 char *cmd;
78209 char *uuid;
78210 char *name;
78211 int val;
78212 int ver;
78213
78214 if (argc < 2) {
78215 printf("lvmetactl dump\n");
78216 printf("lvmetactl pv_list\n");
78217 printf("lvmetactl vg_list\n");
78218 printf("lvmetactl get_global_info\n");
78219 printf("lvmetactl vg_lookup_name <name>\n");
78220 printf("lvmetactl vg_lookup_uuid <uuid>\n");
78221 printf("lvmetactl pv_lookup_uuid <uuid>\n");
78222 printf("lvmetactl set_global_invalid 0|1\n");
78223 printf("lvmetactl set_global_disable 0|1\n");
78224 printf("lvmetactl set_vg_version <uuid> <name> <version>\n");
78225 printf("lvmetactl vg_lock_type <uuid>\n");
78226 return -1;
78227 }
78228
78229 cmd = argv[1];
78230
78231 h = lvmetad_open(NULL);
78232
78233 if (!strcmp(cmd, "dump")) {
78234 reply = daemon_send_simple(h, "dump",
78235 "token = %s", "skip",
78236 "pid = " FMTd64, (int64_t)getpid(),
78237 "cmd = %s", "lvmetactl",
78238 NULL);
78239 printf("%s\n", reply.buffer.mem);
78240
78241 } else if (!strcmp(cmd, "pv_list")) {
78242 reply = daemon_send_simple(h, "pv_list",
78243 "token = %s", "skip",
78244 "pid = " FMTd64, (int64_t)getpid(),
78245 "cmd = %s", "lvmetactl",
78246 NULL);
78247 printf("%s\n", reply.buffer.mem);
78248
78249 } else if (!strcmp(cmd, "vg_list")) {
78250 reply = daemon_send_simple(h, "vg_list",
78251 "token = %s", "skip",
78252 "pid = " FMTd64, (int64_t)getpid(),
78253 "cmd = %s", "lvmetactl",
78254 NULL);
78255 printf("%s\n", reply.buffer.mem);
78256
78257 } else if (!strcmp(cmd, "get_global_info")) {
78258 reply = daemon_send_simple(h, "get_global_info",
78259 "token = %s", "skip",
78260 "pid = " FMTd64, (int64_t)getpid(),
78261 "cmd = %s", "lvmetactl",
78262 NULL);
78263 printf("%s\n", reply.buffer.mem);
78264
78265 } else if (!strcmp(cmd, "set_global_invalid")) {
78266 if (argc < 3) {
78267 printf("set_global_invalid 0|1\n");
78268 return -1;
78269 }
78270 val = atoi(argv[2]);
78271
78272 reply = daemon_send_simple(h, "set_global_info",
78273 "global_invalid = " FMTd64, (int64_t) val,
78274 "token = %s", "skip",
78275 "pid = " FMTd64, (int64_t)getpid(),
78276 "cmd = %s", "lvmetactl",
78277 NULL);
78278 print_reply(reply);
78279
78280 } else if (!strcmp(cmd, "set_global_disable")) {
78281 if (argc < 3) {
78282 printf("set_global_disable 0|1\n");
78283 return -1;
78284 }
78285 val = atoi(argv[2]);
78286
78287 reply = daemon_send_simple(h, "set_global_info",
78288 "global_disable = " FMTd64, (int64_t) val,
78289 "disable_reason = %s", LVMETAD_DISABLE_REASON_DIRECT,
78290 "token = %s", "skip",
78291 "pid = " FMTd64, (int64_t)getpid(),
78292 "cmd = %s", "lvmetactl",
78293 NULL);
78294 print_reply(reply);
78295
78296 } else if (!strcmp(cmd, "set_vg_version")) {
78297 if (argc < 5) {
78298 printf("set_vg_version <uuid> <name> <ver>\n");
78299 return -1;
78300 }
78301 uuid = argv[2];
78302 name = argv[3];
78303 ver = atoi(argv[4]);
78304
78305 if ((strlen(uuid) == 1) && (uuid[0] == '-'))
78306 uuid = NULL;
78307 if ((strlen(name) == 1) && (name[0] == '-'))
78308 name = NULL;
78309
78310 if (uuid && name) {
78311 reply = daemon_send_simple(h, "set_vg_info",
78312 "uuid = %s", uuid,
78313 "name = %s", name,
78314 "version = " FMTd64, (int64_t) ver,
78315 "token = %s", "skip",
78316 "pid = " FMTd64, (int64_t)getpid(),
78317 "cmd = %s", "lvmetactl",
78318 NULL);
78319 } else if (uuid) {
78320 reply = daemon_send_simple(h, "set_vg_info",
78321 "uuid = %s", uuid,
78322 "version = " FMTd64, (int64_t) ver,
78323 "token = %s", "skip",
78324 "pid = " FMTd64, (int64_t)getpid(),
78325 "cmd = %s", "lvmetactl",
78326 NULL);
78327 } else if (name) {
78328 reply = daemon_send_simple(h, "set_vg_info",
78329 "name = %s", name,
78330 "version = " FMTd64, (int64_t) ver,
78331 "token = %s", "skip",
78332 "pid = " FMTd64, (int64_t)getpid(),
78333 "cmd = %s", "lvmetactl",
78334 NULL);
78335 } else {
78336 printf("name or uuid required\n");
78337 return -1;
78338 }
78339
78340 print_reply(reply);
78341
78342 } else if (!strcmp(cmd, "vg_lookup_name")) {
78343 if (argc < 3) {
78344 printf("vg_lookup_name <name>\n");
78345 return -1;
78346 }
78347 name = argv[2];
78348
78349 reply = daemon_send_simple(h, "vg_lookup",
78350 "name = %s", name,
78351 "token = %s", "skip",
78352 "pid = " FMTd64, (int64_t)getpid(),
78353 "cmd = %s", "lvmetactl",
78354 NULL);
78355 printf("%s\n", reply.buffer.mem);
78356
78357 } else if (!strcmp(cmd, "vg_lookup_uuid")) {
78358 if (argc < 3) {
78359 printf("vg_lookup_uuid <uuid>\n");
78360 return -1;
78361 }
78362 uuid = argv[2];
78363
78364 reply = daemon_send_simple(h, "vg_lookup",
78365 "uuid = %s", uuid,
78366 "token = %s", "skip",
78367 "pid = " FMTd64, (int64_t)getpid(),
78368 "cmd = %s", "lvmetactl",
78369 NULL);
78370 printf("%s\n", reply.buffer.mem);
78371
78372 } else if (!strcmp(cmd, "vg_lock_type")) {
78373 struct dm_config_node *metadata;
78374 const char *lock_type;
78375
78376 if (argc < 3) {
78377 printf("vg_lock_type <uuid>\n");
78378 return -1;
78379 }
78380 uuid = argv[2];
78381
78382 reply = daemon_send_simple(h, "vg_lookup",
78383 "uuid = %s", uuid,
78384 "token = %s", "skip",
78385 "pid = " FMTd64, (int64_t)getpid(),
78386 "cmd = %s", "lvmetactl",
78387 NULL);
78388 /* printf("%s\n", reply.buffer.mem); */
78389
78390 metadata = dm_config_find_node(reply.cft->root, "metadata");
78391 if (!metadata) {
78392 printf("no metadata\n");
78393 goto out;
78394 }
78395
78396 lock_type = dm_config_find_str(metadata, "metadata/lock_type", NULL);
78397 if (!lock_type) {
78398 printf("no lock_type\n");
78399 goto out;
78400 }
78401 printf("lock_type %s\n", lock_type);
78402
78403 } else if (!strcmp(cmd, "pv_lookup_uuid")) {
78404 if (argc < 3) {
78405 printf("pv_lookup_uuid <uuid>\n");
78406 return -1;
78407 }
78408 uuid = argv[2];
78409
78410 reply = daemon_send_simple(h, "pv_lookup",
78411 "uuid = %s", uuid,
78412 "token = %s", "skip",
78413 "pid = " FMTd64, (int64_t)getpid(),
78414 "cmd = %s", "lvmetactl",
78415 NULL);
78416 printf("%s\n", reply.buffer.mem);
78417
78418 } else {
78419 printf("unknown command\n");
78420 goto out_close;
78421 }
78422out:
78423 daemon_reply_destroy(reply);
78424out_close:
78425 daemon_close(h);
78426 return 0;
78427}
78428\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/daemons/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000002466\013062740170\0020552\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
78429# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
78430#
78431# This file is part of LVM2.
78432#
78433# This copyrighted material is made available to anyone wishing to use,
78434# modify, copy, or redistribute it subject to the terms and conditions
78435# of the GNU General Public License v.2.
78436#
78437# You should have received a copy of the GNU General Public License
78438# along with this program; if not, write to the Free Software Foundation,
78439# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
78440
78441srcdir = @srcdir@
78442top_srcdir = @top_srcdir@
78443top_builddir = @top_builddir@
78444
78445.PHONY: dmeventd clvmd cmirrord lvmetad lvmpolld lvmlockd
78446
78447ifneq ("@CLVMD@", "none")
78448 SUBDIRS += clvmd
78449endif
78450
78451ifeq ("@BUILD_CMIRRORD@", "yes")
78452 SUBDIRS += cmirrord
78453endif
78454
78455ifeq ("@BUILD_DMEVENTD@", "yes")
78456 SUBDIRS += dmeventd
78457ifneq ("$(CFLOW_CMD)", "")
78458daemons.cflow: dmeventd.cflow
78459endif
78460endif
78461
78462ifeq ("@BUILD_LVMETAD@", "yes")
78463 SUBDIRS += lvmetad
78464endif
78465
78466ifeq ("@BUILD_LVMPOLLD@", "yes")
78467 SUBDIRS += lvmpolld
78468endif
78469
78470ifeq ("@BUILD_LVMLOCKD@", "yes")
78471 SUBDIRS += lvmlockd
78472endif
78473
78474ifeq ("@BUILD_LVMDBUSD@", "yes")
78475 SUBDIRS += lvmdbusd
78476endif
78477
78478ifeq ($(MAKECMDGOALS),distclean)
78479 SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd
78480endif
78481
78482include $(top_builddir)/make.tmpl
78483
78484ifeq ("@BUILD_DMEVENTD@", "yes")
78485device-mapper: dmeventd.device-mapper
78486endif
78487\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0017166\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/mm/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0017577\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/mm/pool_valgrind_t.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000011316\013062740170\0023127\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#include "libdevmapper.h"
78488
78489#include <assert.h>
78490
78491/*
78492 * Checks that valgrind is picking up unallocated pool memory as
78493 * uninitialised, even if the chunk has been recycled.
78494 *
78495 * $ valgrind --track-origins=yes ./pool_valgrind_t
78496 *
78497 * ==7023== Memcheck, a memory error detector
78498 * ==7023== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
78499 * ==7023== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
78500 * ==7023== Command: ./pool_valgrind_t
78501 * ==7023==
78502 * first branch worked (as expected)
78503 * ==7023== Conditional jump or move depends on uninitialised value(s)
78504 * ==7023== at 0x4009AC: main (in /home/ejt/work/lvm2/unit-tests/mm/pool_valgrind_t)
78505 * ==7023== Uninitialised value was created by a client request
78506 * ==7023== at 0x4E40CB8: dm_pool_free (in /home/ejt/work/lvm2/libdm/ioctl/libdevmapper.so.1.02)
78507 * ==7023== by 0x4009A8: main (in /home/ejt/work/lvm2/unit-tests/mm/pool_valgrind_t)
78508 * ==7023==
78509 * second branch worked (valgrind should have flagged this as an error)
78510 * ==7023==
78511 * ==7023== HEAP SUMMARY:
78512 * ==7023== in use at exit: 0 bytes in 0 blocks
78513 * ==7023== total heap usage: 2 allocs, 2 frees, 2,104 bytes allocated
78514 * ==7023==
78515 * ==7023== All heap blocks were freed -- no leaks are possible
78516 * ==7023==
78517 * ==7023== For counts of detected and suppressed errors, rerun with: -v
78518 * ==7023== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
78519 */
78520
78521#define COUNT 10
78522
78523static void check_free()
78524{
78525 int i;
78526 char *blocks[COUNT];
78527 struct dm_pool *p = dm_pool_create("blah", 1024);
78528
78529 for (i = 0; i < COUNT; i++)
78530 blocks[i] = dm_pool_alloc(p, 37);
78531
78532 /* check we can access the last block */
78533 blocks[COUNT - 1][0] = 'E';
78534 if (blocks[COUNT - 1][0] == 'E')
78535 printf("first branch worked (as expected)\n");
78536
78537 dm_pool_free(p, blocks[5]);
78538
78539 if (blocks[COUNT - 1][0] == 'E')
78540 printf("second branch worked (valgrind should have flagged this as an error)\n");
78541
78542 dm_pool_destroy(p);
78543}
78544
78545/* Checks that freed chunks are marked NOACCESS */
78546static void check_free2()
78547{
78548 struct dm_pool *p = dm_pool_create("", 900); /* 900 will get
78549 * rounded up to 1024,
78550 * 1024 would have got
78551 * rounded up to
78552 * 2048 */
78553 char *data1, *data2;
78554
78555 assert(p);
78556 data1 = dm_pool_alloc(p, 123);
78557 assert(data1);
78558
78559 data1 = dm_pool_alloc(p, 1024);
78560 assert(data1);
78561
78562 data2 = dm_pool_alloc(p, 123);
78563 assert(data2);
78564
78565 data2[0] = 'A'; /* should work fine */
78566
78567 dm_pool_free(p, data1);
78568
78569 /*
78570 * so now the first chunk is active, the second chunk has become
78571 * the free one.
78572 */
78573 data2[0] = 'B'; /* should prompt an invalid write error */
78574
78575 dm_pool_destroy(p);
78576}
78577
78578static void check_alignment()
78579{
78580 /*
78581 * Pool always tries to allocate blocks with particular alignment.
78582 * So there are potentially small gaps between allocations. This
78583 * test checks that valgrind is spotting illegal accesses to these
78584 * gaps.
78585 */
78586
78587 int i, sum;
78588 struct dm_pool *p = dm_pool_create("blah", 1024);
78589 char *data1, *data2;
78590 char buffer[16];
78591
78592
78593 data1 = dm_pool_alloc_aligned(p, 1, 4);
78594 assert(data1);
78595 data2 = dm_pool_alloc_aligned(p, 1, 4);
78596 assert(data1);
78597
78598 snprintf(buffer, sizeof(buffer), "%c", *(data1 + 1)); /* invalid read size 1 */
78599 dm_pool_destroy(p);
78600}
78601
78602/*
78603 * Looking at the code I'm not sure allocations that are near the chunk
78604 * size are working. So this test is trying to exhibit a specific problem.
78605 */
78606static void check_allocation_near_chunk_size()
78607{
78608 int i;
78609 char *data;
78610 struct dm_pool *p = dm_pool_create("", 900);
78611
78612 /*
78613 * allocate a lot and then free everything so we know there
78614 * is a spare chunk.
78615 */
78616 for (i = 0; i < 1000; i++) {
78617 data = dm_pool_alloc(p, 37);
78618 memset(data, 0, 37);
78619 assert(data);
78620 }
78621
78622 dm_pool_empty(p);
78623
78624 /* now we allocate something close to the chunk size ... */
78625 data = dm_pool_alloc(p, 1020);
78626 assert(data);
78627 memset(data, 0, 1020);
78628
78629 dm_pool_destroy(p);
78630}
78631
78632/* FIXME: test the dbg_malloc at exit (this test should be in dbg_malloc) */
78633static void check_leak_detection()
78634{
78635 int i;
78636 struct dm_pool *p = dm_pool_create("", 1024);
78637
78638 for (i = 0; i < 10; i++)
78639 dm_pool_alloc(p, (i + 1) * 37);
78640}
78641
78642/* we shouldn't get any errors from this one */
78643static void check_object_growth()
78644{
78645 int i;
78646 struct dm_pool *p = dm_pool_create("", 32);
78647 char data[100] = { 0 };
78648 void *obj;
78649
78650 dm_pool_begin_object(p, 43);
78651 for (i = 1; i < 100; i++)
78652 dm_pool_grow_object(p, data, i);
78653 obj = dm_pool_end_object(p);
78654
78655 dm_pool_destroy(p);
78656}
78657
78658int main(int argc, char **argv)
78659{
78660 check_free();
78661 check_free2();
78662 check_alignment();
78663 check_allocation_near_chunk_size();
78664 check_leak_detection();
78665 check_object_growth();
78666 return 0;
78667}
78668\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/mm/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001547\013062740170\0021653\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
78669# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
78670# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
78671#
78672# This file is part of LVM2.
78673#
78674# This copyrighted material is made available to anyone wishing to use,
78675# modify, copy, or redistribute it subject to the terms and conditions
78676# of the GNU General Public License v.2.
78677#
78678# You should have received a copy of the GNU General Public License
78679# along with this program; if not, write to the Free Software Foundation,
78680# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
78681
78682srcdir = @srcdir@
78683top_srcdir = @top_srcdir@
78684top_builddir = @top_builddir@
78685VPATH = @srcdir@
78686
78687SOURCES=\
78688 pool_valgrind_t.c
78689
78690TARGETS=\
78691 pool_valgrind_t
78692
78693include $(top_builddir)/make.tmpl
78694DM_LIBS = -ldevmapper $(LIBS)
78695
78696pool_valgrind_t: pool_valgrind_t.o
78697 $(CC) $(CFLAGS) -o $@ pool_valgrind_t.o $(LDFLAGS) $(DM_LIBS)
78698
78699\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/mm/check_results\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000001045\013062740170\0022363\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#!/usr/bin/env ruby1.9
78700
78701require 'pp'
78702
78703patterns = [
78704 /Invalid read of size 1/,
78705 /Invalid write of size 1/,
78706 /Invalid read of size 1/,
78707 /still reachable: [0-9,]+ bytes in 3 blocks/
78708 ]
78709
78710lines = STDIN.readlines
78711pp lines
78712
78713result = catch(:done) do
78714 patterns.each do |pat|
78715 loop do
78716 throw(:done, false) if lines.size == 0
78717
78718 line = lines.shift
78719 if line =~ pat
78720 STDERR.puts "matched #{pat}"
78721 break;
78722 end
78723 end
78724 end
78725
78726 throw(:done, true)
78727end
78728
78729exit(result ? 0 : 1)
78730\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/mm/TESTS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000112\013062740170\0020416\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0valgrind pool awareness:valgrind ./pool_valgrind_t 2>&1 | ./check_results
78731\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/datastruct/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0021344\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/datastruct/TESTS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000046\013062740170\0022171\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0bitset iteration:$TEST_TOOL ./bitset_t\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/datastruct/Makefile.in\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000001625\013062740170\0023415\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#
78732# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
78733# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
78734#
78735# This file is part of LVM2.
78736#
78737# This copyrighted material is made available to anyone wishing to use,
78738# modify, copy, or redistribute it subject to the terms and conditions
78739# of the GNU General Public License v.2.
78740#
78741# You should have received a copy of the GNU General Public License
78742# along with this program; if not, write to the Free Software Foundation,
78743# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
78744
78745srcdir = @srcdir@
78746top_srcdir = @top_srcdir@
78747top_builddir = @top_builddir@
78748
78749SOURCES=\
78750 bitset_t.c
78751
78752TARGETS=\
78753 bitset_t
78754
78755include $(top_builddir)/make.tmpl
78756
78757INCLUDES += -I$(top_srcdir)/libdm
78758DM_DEPS = $(top_builddir)/libdm/libdevmapper.so
78759DM_LIBS = -ldevmapper $(LIBS)
78760
78761bitset_t: bitset_t.o $(DM_DEPS)
78762 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ bitset_t.o $(DM_LIBS)
78763\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/datastruct/bitset_t.c\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000006747\013062740170\0023343\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0/*
78764 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
78765 *
78766 * This file is part of LVM2.
78767 *
78768 * This copyrighted material is made available to anyone wishing to use,
78769 * modify, copy, or redistribute it subject to the terms and conditions
78770 * of the GNU General Public License v.2.
78771 *
78772 * You should have received a copy of the GNU General Public License
78773 * along with this program; if not, write to the Free Software Foundation,
78774 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
78775 */
78776
78777#include "libdevmapper.h"
78778
78779#include <assert.h>
78780
78781enum {
78782 NR_BITS = 137
78783};
78784
78785static void test_get_next(struct dm_pool *mem)
78786{
78787 int i, j, last, first;
78788 dm_bitset_t bs = dm_bitset_create(mem, NR_BITS);
78789
78790 for (i = 0; i < NR_BITS; i++)
78791 assert(!dm_bit(bs, i));
78792
78793 for (i = 0, j = 1; i < NR_BITS; i += j, j++)
78794 dm_bit_set(bs, i);
78795
78796 first = 1;
78797 for (i = 0, j = 1; i < NR_BITS; i += j, j++) {
78798 if (first) {
78799 last = dm_bit_get_first(bs);
78800 first = 0;
78801 } else
78802 last = dm_bit_get_next(bs, last);
78803
78804 assert(last == i);
78805 }
78806
78807 assert(dm_bit_get_next(bs, last) == -1);
78808}
78809
78810static void bit_flip(dm_bitset_t bs, int bit)
78811{
78812 int old = dm_bit(bs, bit);
78813 if (old)
78814 dm_bit_clear(bs, bit);
78815 else
78816 dm_bit_set(bs, bit);
78817}
78818
78819static void test_equal(struct dm_pool *mem)
78820{
78821 dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
78822 dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
78823
78824 int i, j;
78825 for (i = 0, j = 1; i < NR_BITS; i += j, j++) {
78826 dm_bit_set(bs1, i);
78827 dm_bit_set(bs2, i);
78828 }
78829
78830 assert(dm_bitset_equal(bs1, bs2));
78831 assert(dm_bitset_equal(bs2, bs1));
78832
78833 for (i = 0; i < NR_BITS; i++) {
78834 bit_flip(bs1, i);
78835 assert(!dm_bitset_equal(bs1, bs2));
78836 assert(!dm_bitset_equal(bs2, bs1));
78837
78838 assert(dm_bitset_equal(bs1, bs1)); /* comparing with self */
78839 bit_flip(bs1, i);
78840 }
78841}
78842
78843static void test_and(struct dm_pool *mem)
78844{
78845 dm_bitset_t bs1 = dm_bitset_create(mem, NR_BITS);
78846 dm_bitset_t bs2 = dm_bitset_create(mem, NR_BITS);
78847 dm_bitset_t bs3 = dm_bitset_create(mem, NR_BITS);
78848
78849 int i, j;
78850 for (i = 0, j = 1; i < NR_BITS; i += j, j++) {
78851 dm_bit_set(bs1, i);
78852 dm_bit_set(bs2, i);
78853 }
78854
78855 dm_bit_and(bs3, bs1, bs2);
78856
78857 assert(dm_bitset_equal(bs1, bs2));
78858 assert(dm_bitset_equal(bs1, bs3));
78859 assert(dm_bitset_equal(bs2, bs3));
78860
78861 dm_bit_clear_all(bs1);
78862 dm_bit_clear_all(bs2);
78863
78864 for (i = 0; i < NR_BITS; i++) {
78865 if (i % 2)
78866 dm_bit_set(bs1, i);
78867 else
78868 dm_bit_set(bs2, i);
78869 }
78870
78871 dm_bit_and(bs3, bs1, bs2);
78872 for (i = 0; i < NR_BITS; i++)
78873 assert(!dm_bit(bs3, i));
78874}
78875
78876int main(int argc, char **argv)
78877{
78878 typedef void (*test_fn)(struct dm_pool *);
78879 static test_fn tests[] = {
78880 test_get_next,
78881 test_equal,
78882 test_and
78883 };
78884
78885 int i;
78886 for (i = 0; i < DM_ARRAY_SIZE(tests); ++i) {
78887 struct dm_pool *mem = dm_pool_create("bitset test", 1024);
78888 assert(mem);
78889 tests[i](mem);
78890 dm_pool_destroy(mem);
78891 }
78892
78893 return 0;
78894}
78895
78896\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/regex/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000755\00001750\00001750\000000000000\013062740170\0020300\0 5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0LVM2.2.02.168/unit-tests/regex/TESTS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\00000644\00001750\00001750\000000000672\013062740170\0021132\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ustar \0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f.gruenbichler\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0dfa matching:$TEST_TOOL ./matcher_t --fingerprint dev_patterns < devices.list > matcher_t.output && diff -u matcher_t.expected matcher_t.output
78897dfa matching:$TEST_TOOL ./matcher_t --fingerprint random_regexes < /dev/null > matcher_t.output && diff -u matcher_t.expected2 matcher_t.output
78898