1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-08-18 13:49:28 +03:00

Compare commits

..

887 Commits

Author SHA1 Message Date
34dd8d0a91 Some new features. 2002-11-18 14:04:08 +00:00
81c44790d5 Refactoring. 2002-11-18 14:01:16 +00:00
d557b335cf A new cache. 2002-11-18 13:53:58 +00:00
e2adc28cff Only functions listed in libdevmapper.h should get exported. 2002-11-14 19:26:28 +00:00
0fef6a6ecc Fix includes after DM_DIR definition move. 2002-11-14 14:44:42 +00:00
f2fd4b8a1f Don't let LVM2 access a VG if the original LVM driver appears to be using it. 2002-11-01 19:57:25 +00:00
95bd5605a8 Improve missing-kernel-driver error message. 2002-11-01 16:16:42 +00:00
497cca7eca agk, I recall you saying you had a massive commit pending; if you need me
to back this out so you can do that commit, let me know.  Also, if there's
an issue with the error message that's displayed, just change it in tools.h.

This causes a "device-mapper driver/module not loaded?" error message to
be displayed for the commands that require dm-mod, if the tools can't get
the driver version.  It's not done for commands that don't require dm-mod.
This should clear up some problems people have had attempting to use lvm2
without rtfm'ing.
2002-10-27 21:04:03 +00:00
54f78feedd synch w/ debian 2002-10-27 18:40:35 +00:00
76408e53ae Wow, learn something new every day. Apparently, the signed-ness of char is
implementation-dependent; some archs (s390, arm, and ppc) default to
an unsigned char.
2002-10-08 20:16:44 +00:00
be19e74d30 Support alternative lvrename syntax. 2002-09-05 12:49:23 +00:00
dac578a775 update, synch w/ debian 2002-09-01 23:08:17 +00:00
04732ce74b o inline _step_matcher 2002-08-29 15:05:16 +00:00
a6c95a2374 o Give an example filter that uses anchors. 2002-08-29 14:47:06 +00:00
f68622abe9 o Anchor support for the regex engine. 2002-08-29 14:46:30 +00:00
83a9a7bdb2 o This resolves bug #79
o added -D_REENTRANT to the CFLAGS so clvmd works properly with liblvm
   (I saw this problem with Redhat 7.3)
2002-08-15 15:31:33 +00:00
6500afc0ca Remove O_DIRECT as it causes problems with some systems.
Harumph.
2002-08-14 14:58:00 +00:00
c69b7ecc96 o Remove e2fsadm to stop people waiting expectantly for something that isn't going
to arrive.
2002-08-08 07:54:57 +00:00
615ef1e2d2 o Make sure the status parsing code can deal with an empty array. 2002-08-01 12:51:48 +00:00
cf69a0cd7f o Added new value type CFG_EMPTY_ARRAY, to indicate '[]', useful since we use
the arrays to hold a symbolic set of flags.
2002-08-01 12:46:52 +00:00
06e892fb33 o 0 was used rather than NULL in a couple of places.
o  Indent output with tabs rather than single spaces.
2002-08-01 08:22:09 +00:00
e6c5dd6865 o Test program for the config unit. Just reads a config and then writes it
out again.
2002-08-01 08:18:54 +00:00
247efdebdb Rename lock_resource to file_lock_resource to avoid name clashes 2002-07-25 09:04:30 +00:00
76f3792287 Use O_DIRECT for writing to devices.
Doesn't work on HPPA due to a kernel bug but other archs shuld be OK.
2002-07-22 08:10:54 +00:00
64d8e2c727 Remove hard-coded extent_size from snapshot target (field no longer used). 2002-07-17 17:00:54 +00:00
ead0bd9cb0 Improved snapshot-related arg validation 2002-07-17 16:04:05 +00:00
66fc13b2ec i) Add the VISIBLE flag to the text format. (Other changes are pending
for lib/activate.)
2002-07-11 15:28:49 +00:00
f3af4128b0 i) Added a little macro to aid defining the status flags. 2002-07-11 14:36:45 +00:00
0e43107c87 i) There's now a seperate field in struct logical_volume that stores the
allocation policy.  This can currently take one of three values:

   typedef enum {
        ALLOC_NEXT_FREE,
        ALLOC_STRICT,
        ALLOC_CONTIGUOUS
   } alloc_policy_t;

    Notice that 'SIMPLE' has turned into the slightly more meaningful NEXT_FREE.

ii) Put code into display.[hc] for converting one of these enums to a
    text representation and back again.

ii) Updated the text format so this also has the alloc_policy field.
2002-07-11 14:21:49 +00:00
1ee3e7997e tidy 2002-07-11 14:09:26 +00:00
50fd61d91f Add get_config_str 2002-07-11 14:07:43 +00:00
e4cdc051a9 Don't log an error if we can't write the cache file because the FS is read-only.
Gets rid of that annoying error at shutdown.
2002-07-11 09:23:29 +00:00
778e846e96 Add --ignorelockingfailure 2002-07-10 20:43:32 +00:00
a27759b647 Merge adjacent "Missing" segments. 2002-07-10 13:54:17 +00:00
b75eceab41 o Add version number to text format. 2002-07-02 18:47:43 +00:00
e748a5d5f4 Tidy up for another release: updated documentation; removed old files;
module build fix.
2002-06-26 21:50:53 +00:00
99c5a3ae46 Flush on open as well as close. 2002-06-25 14:02:28 +00:00
51da710f5a o Long-awaited ioctl interface clean-up. *** Not backwardly compatible ***
o Various other kernel side tidy-ups.
o Version number changes so we have the option of adding new ioctl commands
  in future without affecting the use of existing ones should you later
  revert to an older kernel but not revert the userspace library/tools.
o Better separation of kernel/userspace elements in the build process to
  prepare for independent distribution of the kernel driver.
2002-06-19 13:07:05 +00:00
569d69b3d2 o Knock the version check out of the makefile, Alasdair will no doubt put it back :)
o  Change to new ioctl names.
2002-06-17 15:50:17 +00:00
059a6b1d90 Get rid of compile warnings on 64bit platforms. 2002-06-07 08:37:07 +00:00
990af7548a Increment version. 2002-05-31 19:33:30 +00:00
a38aefdfc8 Add vgsplit. 2002-05-31 19:30:51 +00:00
3bcb12e7d1 Tidy/fix segment rounding. 2002-05-31 19:29:43 +00:00
7904ecb462 Tidy 2002-05-31 19:28:37 +00:00
9ba4d45109 Remember to update VG free_count when reducing size of an LV. 2002-05-30 16:08:19 +00:00
56b8afe19d Fix vgcfgrestore segfault (wrong variable used). 2002-05-30 16:03:26 +00:00
f7aed9a94c update 2002-05-27 13:00:18 +00:00
e12a7e881d o fix changed function names 2002-05-23 14:13:21 +00:00
5afb65325d Fix LVM1 backwards compatibility issue when LV with a low LV number is deleted. 2002-05-23 11:37:51 +00:00
135f520f32 o Remove ext3 incompatibility bug
o	Mention 2.4.18 VM problem
2002-05-23 08:20:44 +00:00
bc251f4ff6 update for .08 2002-05-23 07:49:25 +00:00
b8769751f6 Rename; add some FIXMEs. 2002-05-22 14:03:45 +00:00
eff96d839e Revert to standard linux macros (for correct behaviour on rare architectures). 2002-05-21 12:37:07 +00:00
aa34c23807 Update version. 2002-05-21 12:14:05 +00:00
195acdac8c ack, missing include 2002-05-19 04:11:34 +00:00
903e03c56c update create_dir() comment 2002-05-19 03:52:38 +00:00
0892767b8a support recursive mkdir in create_dir() 2002-05-19 03:46:34 +00:00
83ebfa772c synch w/ -3 "oh shit" release 2002-05-14 03:56:40 +00:00
1583641322 Drop the default chunk size for snapshots down to 8k 2002-05-13 15:14:21 +00:00
9510e2c256 Rewrite missing/corrupt metadata in more cases. 2002-05-13 12:38:54 +00:00
a9dbabe07e o the _status fxns now take more arguments - this way i don't get the
preparsed status info, shove it all into a string, and then parse it
   again to get the info back out (which is what i was doing before)
 o basically that's it...i like this *much* better than the previous
   method and i think it makes the _status fxn more flexible if we need
   to use it to get other info out.
2002-05-10 16:06:06 +00:00
12884008fa Import snapshot status & persistence + indent etc. 2002-05-10 15:25:38 +00:00
02543bad1c o Actually read snapshot percentage from the kernel - what a pain! :)
o Not sure if the code in dev_manager is really optimal, but it works..
   will look at adjusting it a bit now.
 o I *think* it works right when one snapshot if full but others aren't,
   but I haven't really been able to test it because the full snapshot
   somehow resets itself and weird things start happening to the system...
2002-05-09 21:17:57 +00:00
a8c56a5251 Remove a no-op. 2002-05-09 12:03:55 +00:00
4e5a855f3f o header should only be printed once... 2002-05-08 17:58:52 +00:00
7e497a951e o Added function find_snapshots to snapshot_manip.c that returns a list
of snapshots whose origin is the lv passed in.
 o Used this new function to make lvdisplay properly display all snapshots
   attached to a origin.
2002-05-08 16:57:46 +00:00
cd08eabbfa i) Put back chunksize_ARG for lvcreate. 2002-05-08 14:36:10 +00:00
f7e62d9f81 Always call init_log() to initialise logging defaults. 2002-05-08 12:26:45 +00:00
9a3761e86e implement our own swabbing functions, instead of relying on the kernel's. 2002-05-07 15:28:59 +00:00
3619a68693 log/{prefix,command_names} use defaults.h & reset between shell cmds 2002-05-07 13:00:01 +00:00
efaf3c3bf9 Default values for some display output settings 2002-05-07 12:50:01 +00:00
0e4e6a6f67 Tweaks 2002-05-07 12:47:11 +00:00
42458e6278 updated. 2002-05-07 06:13:03 +00:00
41ec995377 Make lvm2 compile on big endian archs; use the kernel/glibc's endian
conversion stuff, instead of implementing our own.  Tested on a little
endian system (x86); I'll let the debian handle big endian testing.  :)
2002-05-07 05:54:14 +00:00
4f37599326 o Will now correctly remove expired achive files from the system when
archive_vg is called.
 o Added a #define to the top of the file - not sure if this is the
   appropriate place for it though
2002-05-03 19:28:07 +00:00
4144520e5c Add features to get table/status & wait for next event. 2002-05-03 11:55:58 +00:00
6c4800546c forgot to add Conflicts against lvm1 packages 2002-05-03 04:57:49 +00:00
733733c8a7 updated for 0.95.05-2. 2002-05-03 04:43:46 +00:00
2aa67cc946 ditto 2002-05-03 04:43:24 +00:00
9385981a9d dh_installinit makes a perfectly find postrm script.. 2002-05-03 04:13:02 +00:00
fff780035d Update. 2002-04-30 17:13:43 +00:00
46127e673d Some partial VG support with format_text. 2002-04-30 17:12:37 +00:00
70df59b224 get_vgs must check for text format VGs when no lvm1 format VGs present 2002-04-30 12:27:13 +00:00
0fdbaa803f o Updated *display output for LVM1 compatibility
o There is still a bit missing
   + all are missing the {PV,VG,LV} # - that is not applicable in LVM2
   + pvdisplay doesn't show how many LVs are contained on it
   + much of the snapshot information isn't available for lvdisplay
 o Look at the code for other potiential FIXMEs  :)
2002-04-29 21:43:14 +00:00
6af1830eff Changed DEFAULT_PV and DEFAULT_LV to 256 (has been fixed in LVM1 before) 2002-04-25 10:53:58 +00:00
6f860e2bd5 Updated for new release 2002-04-25 06:12:07 +00:00
20a492f7ee Update example config 2002-04-24 18:41:02 +00:00
63875e7591 Merge with text format branch.
Lots of changes/very little testing so far => there'll be bugs!

Use 'vgcreate -M text' to create a volume group with its metadata stored
in text files.  Text format metadata changes should be reasonably atomic,
with a (basic) automatic recovery mechanism if the system crashes while a
change is in progress.

Add a metadata section to lvm.conf to specify multiple directories if
you want (recommended) to keep multiple copies of the metadata (eg on
different filesystems).

e.g. metadata {
        dirs = ["/etc/lvm/metadata1","/usr/local/lvm/metadata2"]
}

Plenty of refinements still in the pipeline.
2002-04-24 18:20:51 +00:00
0ad98cabde add setlocale() call so that localisation of things like number entry
and display will work correctly.
2002-04-24 10:42:09 +00:00
668879d2e1 o Stop printing errors if flushing fails (could be an unconfigured device). 2002-04-24 08:37:34 +00:00
2e09783302 Prepare for another beta release. 2002-04-23 22:13:04 +00:00
49734114b3 Commit snapshot-related changes preparing for the next beta release. 2002-04-23 21:47:50 +00:00
950d9d6ee7 Missing seg->lv gives segfault when activating from text format. 2002-04-16 19:41:54 +00:00
f7974aee2e Allow deactivation of final snapshot. 2002-04-16 14:42:20 +00:00
c870a82621 o Added support for chunk_size to lvcreate. 2002-04-15 18:49:20 +00:00
984929a001 Missing VG lock when iterating through all LVs. 2002-04-15 16:27:39 +00:00
7f9e2c1db8 More memory leak plugging. 2002-04-15 13:24:14 +00:00
324e8389dc o Drop the default chunk size for snapshots down to 16k. 2002-04-15 08:41:00 +00:00
6f448c5a38 Implement a no_locking module that *does* attempt activation. 2002-04-11 14:10:32 +00:00
ec43efbb20 Rename device node during a DM_RENAME command. 2002-04-11 12:45:18 +00:00
3ed065de37 Return status from _lv_activate and friends.
Alasdair, I think this is right (and I need it) but you may like to check.
2002-04-11 09:14:04 +00:00
8152f0d72c Remove \n from log messages. 2002-04-10 15:49:47 +00:00
f8047f4736 o Perform a BLKFLSBUF ioctl whenever a block device is closed.
Patrick, can you see if this fixes your cluster syncing problem please ?
If so I'll make it so it only syncs if you have actually written to the
device.
2002-04-08 18:59:50 +00:00
b93c66dc2d Implement an external locking interface. 2002-04-08 16:04:50 +00:00
ac877b3065 Fix prototype. 2002-04-08 13:35:09 +00:00
dee8abfdde Fix lv_setup() not to generate a new lvid each time if asked to setup the
same LV more than once - subsequent times validate only.
2002-04-05 14:32:22 +00:00
cef3841d73 Make lock type numbers match the DLM numbers in use, and move UNLOCK out
of the way.
2002-04-04 13:31:21 +00:00
3cd5e8a041 Rename LCK_NONE to LCK_UNLOCK 2002-04-04 11:18:45 +00:00
515b5f866e Tidying. 2002-04-03 12:17:55 +00:00
321f62bf92 Cope with creation of additional snapshots while active.
(More work on suspension dependencies still needed.)
2002-03-27 18:17:43 +00:00
f94fa47b52 Snapshots are now attached to their origin device for locking purposes
so lock the origin instead of the snapshot itself when creating one.
2002-03-26 15:01:57 +00:00
c502f8a722 New-style persistent minor support. 2002-03-26 13:41:37 +00:00
59b4868ac3 o read-only device support
o name/uuid disambiguation
2002-03-25 18:54:59 +00:00
3634e12cce Fix typo. 2002-03-25 18:50:37 +00:00
6d45445391 all people to actually uninstall lvm2 (*grin*) 2002-03-23 08:23:15 +00:00
4f47e268cc Improve log messages. 2002-03-20 14:34:15 +00:00
0035b31cdb Better support for LVs with hyphens in names. 2002-03-19 16:41:44 +00:00
f2565aee03 Support device queries by uuid as well as by name. (Used by lvrename.) 2002-03-18 23:39:42 +00:00
5bd85668dd lvrename works on snapshots now 2002-03-18 23:25:50 +00:00
20f990b6ce Tie all snapshot (de)activation requests to (de)activation of origin device. 2002-03-18 13:09:27 +00:00
6821379586 s/Removing/Unloading/ in messages to reduce confusion 2002-03-15 23:01:59 +00:00
73b040eb49 Cut the number of device-mapper calls. 2002-03-15 22:59:12 +00:00
49aa4b2e1e New function to enable suppression of messages to stdout/stderr. 2002-03-15 22:54:04 +00:00
972241c74c Review locking: block signals instead of ignoring them and restore state
afterwards; avoid race condition with unlink; add LCK_HOLD to process_each_vg.
2002-03-15 16:07:38 +00:00
680750e3c2 Reduce the number of dm info calls. 2002-03-14 21:17:30 +00:00
5e7d4d9d15 distclean also to remove libdm-common.h 2002-03-14 16:56:02 +00:00
1e57e60613 Integrate suspend. 2002-03-14 15:36:07 +00:00
3ac7ce605a Suppress verbose/debug messages from libdevmapper. 2002-03-14 13:39:33 +00:00
b720dea9f0 o dev_manager_suspend, untested. 2002-03-14 10:56:09 +00:00
c80722aefe A missing free() found by Valgrind. ( http://developer.kde.org/~sewardj/ ) 2002-03-13 23:19:20 +00:00
a84fa69f28 dmsetup display uuid 2002-03-13 16:19:17 +00:00
e33781e59f Set LV uuid. 2002-03-13 15:11:29 +00:00
8824bc7ece o Mention that vgscan needs to be run after changing the filter var. 2002-03-13 14:25:53 +00:00
c2e3b0e448 Fix _align so it works on 64-bit machines. 2002-03-12 15:27:51 +00:00
f61a38e85a Let dmsetup store the uuid on device creation. 2002-03-11 22:44:36 +00:00
d23e948216 Move is_empty_dir to lvm-file 2002-03-11 22:23:24 +00:00
58bdaa31f0 o Actually check that the vg directory is empty rather than speculatively
rmdiring it.  Work around for devfs bug.
2002-03-11 20:43:58 +00:00
b6491d88a6 o This should complete the dev_manager alg. Please could people now
report any activation oddities they see.
2002-03-11 20:36:04 +00:00
f6061ba62e lv_info replaces lv_active etc. 2002-03-11 19:02:28 +00:00
427899ddce o activate/reactivate merge
o unlocking macro
2002-03-11 15:08:39 +00:00
c4ab7d2dbd o dm->active_list now filled in, ATM this is based on the layer name rather
than the uuid.
2002-03-11 11:27:48 +00:00
0fd2ba033f o Comment out some new code that was preventing pjc activating
snapshots.  This will go back in when the active_list is working.
2002-03-11 10:38:16 +00:00
ed38939a93 o knock out the offset for origin targets. 2002-03-08 10:45:01 +00:00
c7ee26ce5a o Add active_list to dev_manager
o  Origin layer is only added to snapshots if a snapshot is in the
   active_list.
2002-03-08 10:41:48 +00:00
909b8cb303 heh, whoops. s/device-mapper/LVM2/g. 2002-03-08 02:39:08 +00:00
b0277370cf o dm_destroy_all() called on exit - but doesn't touch suspended devices yet.
o 'dmsetup remove_all' calls dm_destroy_all() to provide a quick way to
  prepare for unloading the module
o Ran through indent again.
2002-03-07 20:56:10 +00:00
2ec8656bea o First cut at dev scanning.
o  Split up _expand_lv
2002-03-07 17:37:38 +00:00
b2ef256910 o Add comment describing what we're aiming for with dev_manager.
o  Remove dev_manager_reactivate, since it'll be the same as activate.

o  Merge the mark, visible and dirty fields into the same flags field.
2002-03-07 16:48:46 +00:00
63d6ce95db o Top level device is now just called <vg>-<lv> (there's no 'top'
layer appended).

o  Got rid of the unused layer->type field and enum.
2002-03-07 15:29:31 +00:00
a9532b189c Kernel functionality that returns device dependencies (ejt). 2002-03-06 19:42:23 +00:00
844545411f o Rename dmsetup dependencies -> dmsetup deps 2002-03-06 14:47:13 +00:00
4e23a2b9b8 o Add support for getting dependencies for a device.
o  dmsetup dependencies <dev>
2002-03-06 14:38:25 +00:00
5deba027eb convert from debian native package 2002-03-06 05:43:54 +00:00
fc8b7efc6f o Use new LCK_HOLD flag to indicate whether lock should be held on return
from lock_vol() - otherwise it now attempts to acquire the lock and then
  immediately releases it.
o Extend the id field in struct logical_volume to hold VG uuid + LV uuid
  for format1. This unique lvid can be used directly when calling lock_vol().
o Add the VG uuid to vgcache to make VG uuid lookups possible.  (Another
  step towards using them instead of VG names internally.)
2002-03-05 20:03:09 +00:00
a1c2d9c0f3 Fix activation for VG with more than one LV. 2002-03-04 18:50:34 +00:00
4ca49a0501 snapshot/zero logic 2002-03-04 15:25:52 +00:00
493c53d090 o Add a line to lvdisplay to say if the volume is a snapshot. 2002-03-04 15:12:30 +00:00
b27e956d35 o Bad dependency, meant the origin was always getting activated. 2002-03-04 15:10:30 +00:00
35ebed75c6 Remove unused fns. 2002-03-04 14:27:25 +00:00
7bfdb5f77f o I was tearing down device bottom-up instead of top down. Which
is why lvremove of snapshots wasn't working.
2002-03-04 14:26:43 +00:00
8d8c02317f o Break creating a snapshot down into:
i)   create cow
   ii)  activate cow
   iii) zero cow
   iv)  deactivate
   v)   add snapshot info
   vi)  reactivate
2002-03-04 13:46:37 +00:00
a34482feab proper /etc/lvm/lvm.conf now 2002-03-04 11:13:47 +00:00
cbdc8fd4a6 fix various issues 2002-03-04 11:12:57 +00:00
8d3afaa53c More use of LV locking. 2002-03-01 19:08:11 +00:00
7ced9ef3df o point snapshots at origin:real rather than origin:top, and *ping*
snapshots work.
2002-03-01 09:07:00 +00:00
e8a9ae7e80 Fix unlock parameter. 2002-02-27 14:48:42 +00:00
73a88ab3d3 o Lock mechanism for LV activation
o #defines for common lock flag combinations
o Try out hyphens instead of colons in device-mapper names - does this
  make messages containing filenames easier to read?
2002-02-27 12:26:41 +00:00
aaed82738a Running out of filehandles? Close /dev/device-mapper/control then. 2002-02-26 18:30:02 +00:00
de7f7b96db o Format1 wasn't recording the snapshot chunk size properly
o  Activation of snapshots now works - though the resulting device
   doesn't (pjc ?)

o  text format wasn't setting vg->cmd.
2002-02-26 16:48:52 +00:00
1a669b3e68 Clearer link pathname display. 2002-02-26 16:08:22 +00:00
333af9b13a o _build_name was allocating 1 byte too few, which meant the
terminating zero was falling off at some later point.

o Don't try and iterate from a deleted node in _prune_unmarked.
2002-02-26 14:44:13 +00:00
a5bca5e240 o Removed old files
o  rewrote activate.c to use dev-manager, I'm sure these two will merge
   at some point.

o  Rename is broken ATM

o  dev-manager puts the calls through to fs.c for layers that have the
   'visible' flag set.
2002-02-26 11:49:17 +00:00
c885633e02 o More dev_manager fns. 2002-02-25 16:53:12 +00:00
ca7e20b7ca pvresize command 2002-02-25 15:32:58 +00:00
545e11a3d7 o In go the populate functions. 2002-02-25 15:19:53 +00:00
44f5287664 o More dev_manager work. 2002-02-25 14:46:57 +00:00
cf510897f1 Begin conversion so LV id is passed to activation unit instead of
struct logical_volume.
2002-02-25 12:56:16 +00:00
1d171345f8 o Sync with cvs, dev_manager still needs to be wired into activate.c 2002-02-25 12:02:33 +00:00
4fa7e1cd49 o Remove the vg argument from find_cow 2002-02-25 11:55:39 +00:00
acd008298e o hash_iterate -> hash_iter 2002-02-25 11:54:15 +00:00
83a8021515 o Added a macro called hash_iterate, that is similar to list_iterate
o Renamed hash_iterate function, hash_iter.
2002-02-25 11:52:58 +00:00
cf88dfb1db indent 2002-02-24 22:31:55 +00:00
8937c4b481 lvmdiskscan 2002-02-22 13:17:46 +00:00
cc6af10a4d Fill in format_text functions.
Sort of seems to work.
2002-02-22 11:44:56 +00:00
6d94578955 o Convert lv->id back to lv_number when writing back to disk
o Use first unused lv_number when creating new LV
o Use lv_number for refs to snapshots
o Update persistent minor logic after the lvcreate restructure
o Reset all parameters before use in lvcreate.
2002-02-21 19:04:37 +00:00
08442ab71e Avoid ambigous volume_group argument in vg_add_snapshot() 2002-02-21 18:31:48 +00:00
10d91d213f Generate LV uuid from lv_number when reading in LVs. 2002-02-21 15:26:44 +00:00
b7a3b06994 Removed wrong 'lv->vg' argument from lv_is_cow() call. Is used in lv_is_cow internally. 2002-02-21 14:00:45 +00:00
5f12c37f23 o typo 2002-02-21 10:17:01 +00:00
585edebccd o add find_cow function. 2002-02-21 10:16:33 +00:00
9921c62234 o misc little fixes. 2002-02-21 10:15:54 +00:00
1ac76d2e16 ah, it was that "set -e" that was the culprit.. 2002-02-21 08:52:36 +00:00
6e983bf400 stop init script from returning w/ non-zero if not really an error 2002-02-21 08:30:14 +00:00
6a8fd4fa6e Try out using LV locking for reactivation. 2002-02-20 21:30:27 +00:00
3698eaa2d2 Remove lv_update_write_access: use lv_reactivate directly now instead. 2002-02-20 21:28:22 +00:00
8d97ca433c Suppress meaningless <backtrace> msg on screen (no prog/line number given) 2002-02-20 21:26:40 +00:00
23cc65e537 lvd->lv_access & LV_SNAPSHOT not lvd->lv_status 2002-02-20 21:24:45 +00:00
2f5a3c2bbe Remove VG arg from lv_is_cow() and lv_is_origin() - use lv->vg instead. 2002-02-20 19:04:55 +00:00
f6485616cd o Use 'pvcreate --setphysicalvolumesize' with no short form (instead of -s)
and add severe warning if it's used to make a device seem bigger than
  it really is.  This is not an option people should be using as it
  breaks metadata integrity.
o Use uint64_t throughout (rather than unsigned long long)
o Convert a few messages that contain pathnames into the more common form:
  pathname: message
2002-02-20 18:29:30 +00:00
6544fb43d9 initial lvm2 debian packages; still missing some manpages, but otherwise lintian passes
E: lvm2: binary-without-manpage e2fsadm
E: lvm2: binary-without-manpage lvmdiskscan
E: lvm2: binary-without-manpage lvmsadc
E: lvm2: binary-without-manpage lvmsar
E: lvm2: binary-without-manpage lvresize
E: lvm2: binary-without-manpage pvdata
E: lvm2: binary-without-manpage pvmove
E: lvm2: binary-without-manpage version
E: lvm2: binary-without-manpage vgcfgrestore
E: lvm2: binary-without-manpage vgexport
E: lvm2: binary-without-manpage vgimport
E: lvm2: binary-without-manpage vgmknodes
E: lvm2: binary-without-manpage vgsplit
2002-02-20 10:28:49 +00:00
a954b32dcc install all the manpages (another make-lintian-happy exercise) 2002-02-20 10:22:02 +00:00
426dc7836c o Removed the -z (suspend) option from the tools
o  New function: int lv_setup_cow_store(struct logical_volume *lv)
   This zeroes the start of the cow device.

o  Made lvcreate call above fn.
2002-02-18 15:52:48 +00:00
ff941ffc16 o small bug in the format1 export code for snapshots.
o  tidied newlines in the snapshot section of format text.
2002-02-18 11:25:43 +00:00
a063c201df o Add support for the -s and -c flags to lvcreate. 2002-02-18 10:59:51 +00:00
e2be3fa0aa Second path on "pvcreate -s" 2002-02-15 14:33:59 +00:00
609da6fb50 o split lvcreate into seperate functions for parsing the command line,
and creating the lv.  A lot of changes in here so be on the lookout
   for bugs.
2002-02-15 11:53:22 +00:00
fc9f3ccec3 Forgot to remove test printf :-) 2002-02-15 09:37:23 +00:00
f7baa67a0a First cut on "pvcreate -s" 2002-02-15 01:26:16 +00:00
e8d78c2cdb o Initialise the snapshot list properly in vgcreate. 2002-02-14 15:06:24 +00:00
9d33366092 o Define _read_uint32 2002-02-14 14:52:21 +00:00
f5d61515c2 test printf removed 2002-02-13 21:30:51 +00:00
711a04a972 LV maximum size limit of 2TB ensured in _lv_setup() 2002-02-13 21:28:56 +00:00
e5b470a3f1 spaces 2002-02-13 21:28:15 +00:00
31820e1e22 > 2TB numbers in vgdisplay_full 2002-02-13 20:21:13 +00:00
4849e8cd6d o snapshot support for the text format.
The logical_volumes, and snapshots sections of the text format are now
optional.
2002-02-13 13:29:16 +00:00
77e3b460aa o First pass at format1 snapshot support. 2002-02-13 11:43:29 +00:00
b5321001f8 o First changes to add snapshot support.
I'm taking a different route from LVM1 here in that snapshots are a
seperate entity from the logical volumes, I think of them as an
application of an LV (or two lvs rather).  As such there is a list of
snapshots held against the vg, and there is *not* a SNAPSHOT, or
SHAPSHOT_ORG flag in lv->status.
2002-02-12 16:31:31 +00:00
38eba9f5ea use portable <inttypes.h> macros for printing. 2002-02-12 14:12:13 +00:00
ea6f399454 o Turn the device_create_* functions into device_populate_*, they only
fill in an already created dm_task.  This allows common code, such
  as minor number selection, and read_only to be lifted.
2002-02-12 11:15:45 +00:00
f8bf2d7b7d Run through indent - no (intentional) changes to any code. 2002-02-11 21:00:35 +00:00
c4856caebb Preparation for an LVM2 liblvm - pass cmd_context into each tool and
link some globals that the tools need into that structure.
2002-02-11 20:50:53 +00:00
fc1030bb22 Now that most of the usage of 'stack' only occurs when there's an error,
don't suppress it from the screen output any longer.
2002-02-11 18:25:18 +00:00
9eb6cad8dc dbg_free(tc->desc) 2002-02-11 18:21:54 +00:00
0fa2a78dce Document return codes. 2002-02-11 17:42:02 +00:00
a56fa1558b o Split activate.c into a high level (remaining in activate.c) and low level (ll-activate.[hc]) API.
o  Creation of a device from an lv now lives in activate-lv.c
2002-02-11 15:48:34 +00:00
261c73a997 o Support locking with local lock files
o Disable control-c during updates (except if blocked waiting for a lock)
2002-02-11 15:42:34 +00:00
929c1333ca o Little recipe for testing LVM2 with loopback devices. 2002-02-11 12:01:59 +00:00
286a79d94d o Added functions to display what's in the archive.
o  For now vgcfgrestore -l <vg> displays this list.

A bit hacky, but it'll get better.
2002-02-11 11:43:17 +00:00
8b951f99da Locking prototypes. 2002-02-08 14:30:37 +00:00
abb449bca0 move defaults.h 2002-02-08 14:28:52 +00:00
bd084028d1 Move defaults.h 2002-02-08 14:28:14 +00:00
138a27570b o I decided that the archive_format shouldn't really be a format at
all since it only supports vg_write.  It has been replaced with:

int archive_vg(struct volume_group *vg,
	       const char *dir,
	       const char *desc,
	       uint32_t retain_days,
	       uint32_t min_archive);

which is now called directly by tools/archive.c
2002-02-08 11:58:18 +00:00
c2ed40a74f o Add cmd_line field to struct cmd_context
o  Text format now has a description and time field at the top level.

o  archiving and backup set the description appropriately. eg,

   for an archive:

     description = "Created *before* executing 'lvextend test_vg/lvol0 -l +1'."
     creation_time = 1013166332

   for a backup:

     description = "Created *after* executing 'lvextend test_vg/lvol0 -l +1'."
     creation_time = 1013166332

This is preparing the way for a simple vgcfgundo command.
2002-02-08 11:13:47 +00:00
a7e7a00cab Poor mans lvmdiskscan 2002-02-05 14:31:57 +00:00
64a31ab3cd Another release (includes some fixes from last week; persistent minors,
partial activation etc.)
2002-02-04 13:30:21 +00:00
71958bc0f1 lv->minor >= 0 (ejt) 2002-02-04 13:08:31 +00:00
366ec35612 Basic support for persistent minor numbers;
slightly different from the current LVM1 method.

  lvcreate --persistent y  --minor 10   (to specify when created)
  lvchange --persistent n  (to turn off)
  lvchange --persistent y  --minor 11   (to change)

--persistent uses a new LV status flag stored on disk
minor number is stored on disk the same way as LVM1 does
(but major number stored is 0; any LVM1 major/minor setting gets lost)

  lvchange -ay --minor 12 (to activate using minor 12, regardless of the
                           on-disk setting, which doesn't get changed)

--minor == -m
--persistent == -M
2002-02-01 17:54:39 +00:00
3738f6e8ae Failure signalled by -1 not 0; MAX_DEVICES 256 (was 64); change a '>' to '>='. 2002-02-01 17:39:20 +00:00
051a8e2af1 Display error when running unimplemented functions. 2002-01-31 20:37:26 +00:00
2f43f28d5e Remove gcc -D to support as different gcc versions handle it differently. 2002-01-31 20:15:26 +00:00
b64769754b "exit" means "quit" (lamer) 2002-01-31 20:08:52 +00:00
a97daa18d1 o Remove redundant dbg_free. 2002-01-31 15:28:30 +00:00
b6556dce8b Remove stray comma. 2002-01-30 17:25:51 +00:00
aa8d8bc8b5 Propagate volume group read-only setting down to its logical volumes.
(Might sometimes be safe to relax this restriction.)
2002-01-30 17:12:14 +00:00
0800dcfdc4 Basic support for (read-only) partial activation if any PVs are
missing from a VG.  (Linear targets use the device-mapper 'error' target
which returns ioerror; striped targets use '/dev/ioerror' for now - which must
already exist e.g. as a sufficiently large block device version of /dev/zero).
2002-01-30 15:33:12 +00:00
12b0101e94 quotes around names in output 2002-01-30 15:04:48 +00:00
021b391a02 Allocate fixed space for vg->system_id when vg is created, instead of
dynamically.
2002-01-30 12:47:29 +00:00
d11e2b6057 Correct statement order for case when 'stripes' parameter is not supplied. 2002-01-30 12:17:40 +00:00
264d90e7e5 add vgimport 2002-01-29 19:23:46 +00:00
f9f3da9e78 o A vgimport implementation
o Require -a or <list of vgs> parameters with vgexport/vgimport
o Allow pvcreate -ff to destroy exported/partial VGs
2002-01-29 19:19:37 +00:00
6435b49153 o Basic support for exporting (but importing not completed yet).
o When volume group does not have write flag set, prevent changes to it.
o Preparation for partial activation (not completed yet).
2002-01-29 17:23:33 +00:00
f9aa2941cf Display 'exported' status. 2002-01-29 16:30:18 +00:00
5a933d4bee Add list_iterate that's safe with deletions. 2002-01-29 16:28:52 +00:00
5536aea0df Date changed 2002-01-29 15:54:49 +00:00
976666d216 Zero gap after PV structure on write to disk in order to make non LVM tools happier (AED's idea and patch for LVM1) 2002-01-29 15:52:11 +00:00
9a5bcd4392 fixed div bug in calculation of end in calculate_extent_count 2002-01-29 15:43:04 +00:00
812060a118 Check that vgname doesn't already exits in dev_dir 2002-01-28 16:30:42 +00:00
089b5052e6 o There were some alignment problems with pool-debug which I've resolved
by allocating the data block with an additional dbg_malloc.

o  Added an assertion to check that no one is requesting alternate
   alignment for memory allocated from pool.  I can't see us needing this
   for LVM2.
2002-01-28 09:16:09 +00:00
874e5d72f4 *** empty log message *** 2002-01-27 21:48:05 +00:00
6b11de1329 Tweak some error message levels. 2002-01-27 21:30:47 +00:00
2245a7ad8d If lv isn't active, skip reactivation. 2002-01-25 22:58:01 +00:00
ee5ec1b870 Prevent lvextend from adding segments with different stripe characteristics
at the moment because the old LVM format doesn't support this.
2002-01-25 21:14:43 +00:00
74ccfe851b The latest attempt at making extended striped LVs work portably with LVM1. 2002-01-25 20:24:14 +00:00
e1c24bd5a2 Set pv->pe_size when reading in text-file backup.
Otherwise LVM1 decides the PV structure is corrupt.
But do we need to keep both pv->pe_size and vg->extent_size
in internal metadata or can we generate pvd->pe_size when writing out
a PV that belongs to a VG?
2002-01-25 20:21:13 +00:00
1349b79728 Only remove symbolic links when deactivating.
(if this code didn't create it, don't delete it)
2002-01-25 20:17:44 +00:00
d294d7604c o Tidy 2002-01-25 13:41:13 +00:00
01df2cf464 Have a pe_total check using theoretically big number instead of the
unnecessarily small limit LVM1 imposes in vgcreate (but not vgextend)
2002-01-24 23:35:56 +00:00
45b7322488 Don't bother to write out an empty cache. 2002-01-24 23:17:16 +00:00
b3055e992f Fix the device cache to cope reasonably safely with device name changes.
This should be a rare occurrence so the aim is to recover if it's
straightforward to do so, otherwise just to abort the operation.
If people *knowingly* change device names, they should always run vgscan
afterwards.

A few bytes of memory gets leaked inside a pool each time an alias
has to be discarded - it's not worth restructuring the code to reuse it.

More of LVM2 needs updating to pass device objects (or uuids) about
instead of pathnames so that resolution of pathname->object only happens
once per operation.

dev_cache_get() should now always return the *current* device at the path given

dev_name_confirmed() replaces dev_name() whenever it's important to
know that name for the device is still current (ie when opening it).
If the cache doesn't know a current name, the function fails.

dev_open() guarantees that the file descriptor returned is for the dev_t
of the device structure it was passed.
2002-01-24 23:16:19 +00:00
3da548565c Clear a FIXME about checking for identical devices by comparing dev_t
instead of name.
2002-01-24 22:37:24 +00:00
a975e85548 removed ~64limit for PEs per PV agk introduced 2002-01-24 19:20:35 +00:00
c4b5ade752 o Limit for number of extents should be 65534. 2002-01-24 17:32:56 +00:00
a4b61b0794 Improve allocation error messages when PVs in a VG have the allocatable
flag unset.
2002-01-24 17:26:00 +00:00
f6011184b8 Impose max PE limit for each PV. 2002-01-24 17:24:32 +00:00
74de118c6e o Add check for > 65k extents in a single lv. 2002-01-24 17:16:36 +00:00
9c25e77c17 o Add extra parameter to lv_manip fns 2002-01-24 17:15:49 +00:00
440113e67e o extra fid parameter to lv_manip fns 2002-01-24 17:15:24 +00:00
a11b60c445 o Remove pointless calculation. 2002-01-24 14:15:42 +00:00
a6052681ad Ignore all except one PV found with the same UUID. Use one which
has the md major number if there is such.
2002-01-24 13:36:33 +00:00
482d50536a Fix dev_close arg. 2002-01-24 13:31:18 +00:00
25c79a4fcd Remove any core files on distclean. 2002-01-24 13:30:40 +00:00
02946144ac o typo 2002-01-24 09:54:09 +00:00
71a360e9a3 o Cut and paste description of how pvmove works that I was mailing someone. 2002-01-24 09:26:13 +00:00
f7912d88b1 o Remove redundant symlink-handling code.
o When opening device, return error if its cached name is incorrect (eg if
  it's changed since the cache was generated).  This prevents use until
  the cache is rebuilt (eg with vgscan).  Doesn't catch every case.
2002-01-23 18:55:01 +00:00
975101d7d2 Avoid using VG metadata on PVs that are not in VGs. 2002-01-23 15:50:34 +00:00
ef58c5ff55 *** empty log message *** 2002-01-23 12:25:30 +00:00
e10221804a Silently remove any existing symlink before creating a new one. 2002-01-22 19:58:37 +00:00
284ed9ee0e Update with info on how to configure command output to look like LVM1 2002-01-22 19:20:46 +00:00
5d7b961997 Reviewed interaction with lib/activate now that the interface has settled down. 2002-01-22 19:11:12 +00:00
c699a5c4b4 New config options to customise message output. 2002-01-22 15:33:57 +00:00
1f4ceb89cf Customisable message output prefix / indentation. 2002-01-22 15:33:40 +00:00
0934ca0040 o added BUGS file. 2002-01-22 14:40:38 +00:00
4738f892c2 o Fix inverted logic in list_empty test. 2002-01-22 14:16:27 +00:00
33004fcf33 old file 2002-01-22 13:29:34 +00:00
34d214c166 Update. Ready to release? 2002-01-22 13:11:01 +00:00
a56cd92a1e No need for file output to default to stderr now that log file can be
specified in config file.
2002-01-21 19:05:00 +00:00
7251348507 Insert a missing hash_remove. 2002-01-21 19:04:13 +00:00
01cd5c84d6 o Allow fractional parts for size args. eg, lvcreate -L 34.4M
o  Fix a couple of bugs related to the earlier lv_list change
2002-01-21 17:43:10 +00:00
e210599fa6 o Similar changes for lv_list. 2002-01-21 16:49:32 +00:00
dbe7cee7e9 o fail if create_pv_list would produce an empty list. 2002-01-21 16:15:25 +00:00
7370d88ceb o Typo in comment 2002-01-21 16:10:36 +00:00
34458e0c57 o Changed
struct pv_list {
	struct list list;
	struct physical_volume pv;
   };

   to

   struct pv_list {
	struct list list;
	struct physical_volume *pv;
   };


o  New function in toollib 'create_pv_list', which creates a list of pv's
   from a given command line array of pv's.

o  Changed lvcreate/extend to use this (fixes lvextend [pv list] bug).
2002-01-21 16:05:23 +00:00
05c8c3abf2 Is this sufficient to fix make -j? 2002-01-21 16:02:55 +00:00
e9d464b4d3 Fixx OB1 error in max LV and max PV numbers 2002-01-21 14:53:47 +00:00
6968c3ab9b o Changed find_pv_in_vg, and find_lv_in_vg to return a struct pv_list * and
struct lv_list * respectively.
2002-01-21 14:28:12 +00:00
131a8a9650 o names.[hc] 2002-01-21 13:11:03 +00:00
379ecbf9a9 o lvdisplay now gives a segment map for the -m option. 2002-01-21 12:05:39 +00:00
7b9dfa9a28 o removed display_uuid
o use id_write_format from lib/uuid/uuid.h instead
2002-01-21 11:29:06 +00:00
fbd0f5eed2 o move the path building functions to lib/activate/names.c
o  Update activate.c and fs.c to use them

o  device names are now of the form <vg>:<lv>
2002-01-21 11:06:32 +00:00
5970f904ae Allow syslog facility to be set, or turned off, from the config file. 2002-01-18 21:26:37 +00:00
8cbcb2868d Display something in the "hypothetical" unknown log level case. 2002-01-18 19:38:19 +00:00
8ff2a4b026 Use same log levels as LVM2. 2002-01-18 19:37:26 +00:00
ae14d205a5 Allow compilation against a device-mapper that was installed into $DESTDIR
Always check for negative (error) return code from lv_active()
2002-01-18 16:43:19 +00:00
ec5d560ec5 More updates. 2002-01-18 13:45:12 +00:00
fb543b53c0 added before 2.1 item 2002-01-18 11:07:26 +00:00
39c16422e2 beta1-pre1 tagged, but there's still some documentation to update/write. 2002-01-17 18:48:08 +00:00
4d5b273ebe Support --version argument and 'version' shell command. 2002-01-17 16:39:24 +00:00
ed6a860fad Add function that returns the library version. 2002-01-17 14:13:25 +00:00
423e579292 Add another level of symlink to library name (like LVM1) so people who find
themselves running multiple incompatible kernel versions will just need
to swap symlinks at boot.
2002-01-17 13:37:09 +00:00
ee11aa9e75 Use additional version numbers.
Kernel driver has a version number (stored in kernel/VERSION).
  The first two components of this (0.94) give the version number of the
  ioctl interface.  This number must be changed whenever a change is
  made to the ioctl interface that breaks backwards compatibility.

  The library has a version number (stored in VERSION) which is
  used for linking.
  The first and/or second component of this must be changed whenever
  a change is made to the library API that breaks backwards
  compatibility.
2002-01-17 13:19:55 +00:00
c46d20fa92 o pvcreate --uuid to specify the uuid (required before using vgcfgrestore
onto a new device).  uuid specified must not already exist on the system.
o More message tidying.
o When checking for label, only read PV metadata.
o Add ataraid.  [Needs moving into config/defaults files.]
2002-01-16 18:10:08 +00:00
dc8d17574c o save before committing 2002-01-16 15:53:42 +00:00
5c17cd04c8 o lvm.conf file that contains the same settings that would be assumed if it
wasn't there.  A good starting point for tweaking.
2002-01-16 15:52:53 +00:00
67ada02076 Move test flag from log to global section of config file. 2002-01-16 15:20:51 +00:00
32d94c2eaf o Don't update vgcache when (not really) writing in test mode.
o Don't continue iterating through a possibly-deleted list.
2002-01-16 14:43:27 +00:00
687b39a12a Remove a duplicate disk read (can_handle). 2002-01-16 13:09:26 +00:00
705af407bf #include <string.h> 2002-01-16 12:02:06 +00:00
080052da2e o Set the segment counter back to 1, for a new LV. 2002-01-16 11:34:29 +00:00
ef735fd92a o Add pvmove to the stub file. 2002-01-16 11:27:19 +00:00
17c16dcafc o Knock out the "'%s' is not a block device" debug message. 2002-01-16 09:23:28 +00:00
a89b3018fb Reduce 'no label found' message severity to debug level. 2002-01-16 00:01:36 +00:00
851e2ebd32 Fix function typecasts. 2002-01-15 23:47:56 +00:00
1225ce7fe8 o More comprehensive config parameter debugging messages.
o Make /proc configurable.
 o Review hard-coded "/dev"s - made 2 more of them configurable.
2002-01-15 23:34:13 +00:00
7e77a31b96 o missing labeller free
o updated vgcfgrestore args
o change _check_for_open_devices only to check devices present in the hash
  table instead of using dev_iter which triggers a full scan even when only
  displaying command line help
2002-01-15 21:28:04 +00:00
d146b9002f o Actually check in vgcfgrestore. 2002-01-15 18:17:57 +00:00
1f9d567b23 o vgcfgrestore works ! (with the couple of examples I tried). 2002-01-15 17:37:23 +00:00
ed1b3a023c Another ioctl interface update:
Supply offset to start of variable data area (so struct size can change
without breaking backward compatibility)
  Add command that just returns the driver version
2002-01-15 15:21:57 +00:00
1ca18f501a o split the uuid -> device map out from vgcache
o  roll vgcache back to agk's implementation, we'll revisit this as part
   of the cluster integration.

o  change the extra_info field in a label to be a void *
2002-01-15 10:24:48 +00:00
49588ccd98 Some ioctl interface changes. (Do we want these?)
- use status bits (so we can add flags without changing the struct size)
  - use dev_t
2002-01-14 23:07:32 +00:00
098dedc092 o Non-caching implementation of new vgcache interface. 2002-01-14 11:43:52 +00:00
b06f6b9545 o LVM1 labeller. 2002-01-14 10:00:56 +00:00
ba3cb94999 o Reformat comment and correct typo. 2002-01-14 09:59:12 +00:00
74c67fbf4b o Add rename support to dmsetup.
o Add support to use specified minor number to library and dmsetup.
2002-01-11 12:12:46 +00:00
32b46e4910 Couple of typos fixed. 2002-01-11 11:34:53 +00:00
ecf5539ed2 o Put in the pv_hash which stores the pv section name -> pv struct mapping. 2002-01-11 11:09:12 +00:00
ac9db4e4d5 o label.c now compiles. 2002-01-11 10:43:32 +00:00
0eb96094b0 Change lvm2_label to use Joe's new label switch system. 2002-01-11 10:39:56 +00:00
30b3ac7dc5 Support the renaming of active mapped devices (ioctl interface only). 2002-01-10 23:29:16 +00:00
0092790c7d o ACTIVE is no longer a status flag - lv_active() used to check if an LV
is active in the device-mapper.
o Many operations can be carried out regardless of whether the VG is
  active or not.
o vgscan does not activate anything - use vgchange.
o Change lvrename to support renaming of active LVs.
o Remove '//' appearing in some pathnames.
o Dummy lv_check_segments() for compilation.
2002-01-10 23:21:07 +00:00
28909d8a51 o _read_id function for import.c 2002-01-10 18:12:26 +00:00
b20cfbb7b6 More steps towards successful compilation. 2002-01-10 16:48:28 +00:00
97639bd0a8 Add 'get' functions. 2002-01-10 16:47:58 +00:00
161ec73c96 More detail in error msgs. 2002-01-10 16:47:25 +00:00
957d6bea15 Separate constant fields from variable ones. 2002-01-10 16:47:04 +00:00
f8b6e5b414 Clarify terminology:
VG is resizeable  - PVs can be added or removed
  PV is allocatable - free extents on it may be allocated to LVs
2002-01-10 15:09:51 +00:00
1ab450870e o Moved the current label.[hc] sideways to lvm2_label.[hc]
o  First pass at low level labelling switch.  This allows us to
   register different label types (eg, lvm1, lvm2).
2002-01-10 15:01:58 +00:00
de45f4884c Allow for multiple spellings / backwards compatibility of renamed
command line options.
      vgchange --resizeable y
      pvchange --allocatable y
But --allocation is still allowed for both (as LVM1) and --resizable is OK.
2002-01-10 14:46:50 +00:00
5da1f3e7c8 o vgcfgrestore. 2002-01-10 14:27:47 +00:00
983014952b Temporary file creation & renaming. 2002-01-10 12:22:17 +00:00
55298019a3 o First pass at import.c. Still waiting for label code for the uuid->pv
mapping.
2002-01-10 11:18:08 +00:00
a1ffc3f271 o Put in the 'out of memory' log_err for pool. 2002-01-10 09:35:55 +00:00
2fb60aa997 Renamed to archive.c 2002-01-09 19:17:11 +00:00
f5ec76537a o Rename many occurrences of 'backup' to 'archive' to reduce confusion.
o Extract file creation/renaming code into a library and change backup code
  to use it too.
o Support umask.
o Bring lvm.conf man page up-to-date.
2002-01-09 19:16:48 +00:00
728491fd2b Accept octal values for numbers (such as umask). 2002-01-09 18:53:07 +00:00
d9d3f2b9e4 o Let the comment wars begin. 2002-01-09 14:14:07 +00:00
3fe4864f65 o new function backup_remove(const char *vg_name), to be called from vgremove. 2002-01-09 14:07:49 +00:00
0b156f22a4 o Reformat comments. 2002-01-09 13:56:11 +00:00
35b1d93813 Add archiving. 2002-01-09 13:17:14 +00:00
d770851ac0 o Try to improve NFS-safety for temporary file creation (unique name; O_APPEND
+ fcntl lock) and rename (using hard link), avoiding any "real" archive
  files ever being zero length.
o Fix filename parsing & ordered list handling.
2002-01-09 13:16:19 +00:00
989e7b1033 Explicitly close (=>flush) files. 2002-01-09 13:07:03 +00:00
c4e0eb7b49 Allow pool_begin_object in empty pool. 2002-01-09 13:06:02 +00:00
71f5d0dac7 Another attempt to support both readline versions. 2002-01-08 19:17:08 +00:00
561b0c4381 call archive_exit() & backup_exit() on exit 2002-01-08 18:14:04 +00:00
995fbc7330 o Remove anomalous punctuation. 2002-01-08 10:51:13 +00:00
10ab8949c4 o Introduction to pool for those without psychic powers. 2002-01-08 10:47:17 +00:00
c441202fea fixes for compilation 2002-01-07 23:28:25 +00:00
ca261b0bee Sync. 2002-01-07 23:04:48 +00:00
52f3709f67 Sync tidy. 2002-01-07 22:49:04 +00:00
c2ca6187fe If a device somehow became suspended, lvchange -ay now reactivates it. 2002-01-07 22:36:12 +00:00
671a13d295 Support for read-only. 2002-01-07 22:28:36 +00:00
14c3e2eccf Missing close() in error case. 2002-01-07 22:25:57 +00:00
08e5b852c2 tidying 2002-01-07 22:01:50 +00:00
1c9606c824 o vgcreate wasn't setting vg->cmd 2002-01-07 15:27:55 +00:00
3cd47b5c9b o New function 'merge_segments'
o  Call said function at end of lv_extend
2002-01-07 15:08:28 +00:00
aedc729087 o tidy up renaming of archive files. 2002-01-07 14:21:33 +00:00
5f7cfa3fa9 o sync tool changes for backup stuff. 2002-01-07 11:12:11 +00:00
0083f30af5 o Added find_config_bool 2002-01-07 10:23:52 +00:00
4a06f05ef5 o Get format-text.c compiling. 2002-01-07 09:16:20 +00:00
8f37cadce8 o sync laptop to test machine. 2002-01-07 09:05:31 +00:00
a11603ca6c Imported man pages from LVM1 with some quick LVM2 updates. 2002-01-04 20:35:19 +00:00
86274842e9 The start of an lvm man page. 2002-01-04 18:56:56 +00:00
cf9c955a44 Document remaining configuration file parameters. 2002-01-04 17:49:38 +00:00
55d828c35f o Revert to the 6-4-4-4-4-4-6 format for uuid's
o  When reading a uuid all -'s are stripped, wherever they are.
2002-01-04 16:55:14 +00:00
cdff28aca6 Put device name in quotes. 2002-01-03 17:47:48 +00:00
b9da39274f o High level archiving and backup functions.
I've split the old autobackup function into two seperate areas:

'archiving' is performed *before* a vg configuration is changed.  This
produces a numbered backup in /etc/lvm/archive.

A 'backup' is performed *after* a vg change.  So the directory /etc/lvm/backup
will hold the  a copy of the current configuration.
2002-01-03 15:46:48 +00:00
c379aa5782 stub for read-only functions with fs interface 2002-01-03 15:12:02 +00:00
9dcabac9dd Fix final comma in arrays. 2002-01-03 12:43:01 +00:00
794f3a2b9f *** empty log message *** 2002-01-03 12:39:04 +00:00
2066121b7c o Added -r, --read-only switch to dmsetup for use with create and reload. 2002-01-03 10:39:21 +00:00
0c4067f143 o Allow the definition of read-only devices (ioctl interface only) (Joe)
o Add version number to ioctl structure with error on kernel/library mismatch
2002-01-02 19:01:09 +00:00
8aa69243b7 o Added section on the syntax of the config file, with an informal grammar. 2002-01-02 17:54:57 +00:00
8697263bde Fix $DESTDIR support 2002-01-02 14:23:10 +00:00
ea25c4f65c Tidy makefiles - $DESTDIR & shared library version (like LVM1) 2002-01-02 13:40:49 +00:00
82ac3ebd7e Add test mode parm. 2001-12-31 22:12:03 +00:00
13cb94909c o Add autobackup support to tools (follows most vg_write calls).
o Skip autobackup when in test mode.
o Set test mode from config file.
o Create system/backup dirs if not present (unless LVM_SYSTEM_DIR holds "").
2001-12-31 21:27:39 +00:00
b57ca2a763 vgcache.h inclusion (avoid compiler warning) 2001-12-31 19:18:44 +00:00
83c49e9745 o Use lvm_snprintf wherever return value is used
o Add parameters to set retention limits for backups
2001-12-31 19:09:51 +00:00
e15771d78d Remove some old files. 2001-12-31 17:34:51 +00:00
6edc4920ba Redundant. 2001-12-31 17:26:42 +00:00
302bb1bd93 Document lvm.conf fields 2001-12-31 17:20:22 +00:00
529b1bceee Outline docs 2001-12-31 16:12:40 +00:00
42cd47d32e o Allow more default values to be overridden from config file.
o Cope with both the readline versions used around here.
2001-12-31 15:20:18 +00:00
711d884c2e Fix C99 error case handling (snprintf ret value >= buffer size). 2001-12-31 15:17:34 +00:00
183d1c4674 Fixes for compilation. 2001-12-31 15:14:44 +00:00
faed63a0bb Remove unused --with_kernel_dir
Current version of LVM2 instead relies on /usr/include/libdevmapper.h
which gets installed by the device mapper package.
(Should this location now be configurable?)
2001-12-31 15:13:42 +00:00
53bff262f8 Revised ioctl/dmfs merge with fixes for bugs found in tests. 2001-12-20 20:32:14 +00:00
3251a708e4 o Added a quick vgcfgbackup, needs parameters as yet. 2001-12-20 16:05:14 +00:00
b5dbdbf7b2 o Debug version of the pool_grow stuff. 2001-12-20 12:27:41 +00:00
a9649e92c9 o sync backup changes 2001-12-20 11:52:54 +00:00
b561f1fa8b Wipe the first label if writing the second one failed. 2001-12-18 14:39:32 +00:00
cecd7491b5 o sync the backup stuff 2001-12-17 19:46:10 +00:00
55a66322b5 o history is now saved in ~/.lvm_history 2001-12-17 17:59:58 +00:00
155c31a2d7 o Shuffled completion functions around so we dont have to declare them
at the top of the file.

o Changed completion_matches -> rl_completion_matches, and added some consts.

This will probably break things on pre readline 4.2 systems.
2001-12-17 17:18:47 +00:00
a89ce91089 o Changed the macro name in args.h from 'xx' to 'arg'
o  There is now a _default_debug, and _default_verbose level, when
   using lvm interactively -vv and -dd switches just effect the current
   command.

o  Added a --quiet switch which sets both verbose and debug to zero.
2001-12-17 16:58:17 +00:00
b897fe6700 o Use lvm_snprintf 2001-12-17 14:05:43 +00:00
548a351b06 o Add symlink for lvm-string.h 2001-12-17 14:04:33 +00:00
4b1da57ca1 o lvm_snprintf
Could everyone please use this from now on.
2001-12-17 14:04:10 +00:00
529aec7f25 o Remove LVM_CONFIG_FILE environment variable.
o  Introduced the LVM_SYSTEM_DIR variable.

This makes more sense because the persistent cache, and backup directories
are config specific.

eg, I use /etc/lvm for running my real LV's

    but I have another directory /dev/lvm_loops that contains a config
    that allows only loopback devices, I use this for testing.
2001-12-17 12:01:09 +00:00
1661e545cb Typos in error messages 2001-12-17 11:07:33 +00:00
ec71d08878 I had another look at the argument processing code:
o You must list long args with no short option (eg. --version) at the
  front of the args.h file.

o If an argument has no short option, set the short option in args.h to '\0'

o The index into the 'the_args' var is now stored as the option value
  for getopt, iff there is no short opt.
2001-12-17 10:08:27 +00:00
ac258b7dd7 o Include dmsetup man page in build
o Allow pathname in dmsetup device arg
o Generated patches for 0.90.02
2001-12-14 13:30:04 +00:00
0f57876233 Write the location of both labels in the labels so we can check them. I don't do
much with this ATM (apart from check that they all match up).
Use a different CRC routine.
2001-12-14 13:15:15 +00:00
1d25a3693d o I figure if I can't remember how to use my code, then I should add
a comment.  It's quite cool, wish I remember writing it.
2001-12-13 16:09:06 +00:00
45fa428bf1 Handle orphan PVs too, so hints remain valid after vgreduce. 2001-12-13 15:08:58 +00:00
177fa80f1a o Man page for dmsetup 2001-12-13 13:46:21 +00:00
3261261bfe made the hard-coded 512 into BLOCK_SIZE just for neatness sake.
log_error() if writing the label fails so someone knows which was in error.
2001-12-13 08:40:47 +00:00
d4de7934f8 Add internal cache holding a 'hint' list of the PVs belonging to each VG.
A substantial speed-up - particularly in readline mode.
If the hints turn out to be wrong, the relevant parts get thrown away.
vgscan destroys it totally.  In both cases it then rebuilds itself as
required.
2001-12-13 00:07:29 +00:00
c3475af809 fix for clean compilation 2001-12-12 16:25:53 +00:00
b12f707812 o silly bugs 2001-12-12 16:22:38 +00:00
22c0c34d60 o pool-debug version of end_object wasn't returning the object. 2001-12-12 16:05:52 +00:00
a60b66f230 o Add error checking in _new_chunk 2001-12-12 14:54:24 +00:00
83f6e93628 o pool-debug versions of begin_object, grow_object etc. 2001-12-12 14:25:20 +00:00
222b5f0229 Build label code into the library 2001-12-12 09:09:04 +00:00
30aa383e26 Use a proper CRC calculation. 2001-12-12 09:05:44 +00:00
676b401294 - Change label format to include a string disk_type and a version number.
- The iterator can find labels by string and also appropriate version number (==,
  <= or any) if you want.
- Add labels_match() call that compares the two labels and returns an error if
  they do not match.
- Write labels in sector 1 & last rather than 2 & last as per Joe.
2001-12-11 16:49:40 +00:00
ebf57159de Apply make distclean to test subdirs too. 2001-12-11 16:26:34 +00:00
199d2aafec Fix label filter. 2001-12-11 14:17:10 +00:00
81952f56fd o Add output_date 2001-12-11 12:29:25 +00:00
c5bac82b43 o flags.c reads and writes a status bitset 2001-12-11 12:18:56 +00:00
081b86109c o Split import-export.c into two files. 2001-12-11 12:16:58 +00:00
8ac2028a75 o Update sample to a format that supports multiple vg's per file. 2001-12-11 12:15:08 +00:00
264fed1c9f Label reading/writing code.
Not tested the filter yet.
2001-12-11 11:42:30 +00:00
dd59f7b2c7 o Pretty print and read for uuid's 2001-12-11 11:40:34 +00:00
9245a760db Add a dev_get_sectsize call. 2001-12-11 10:18:49 +00:00
b61b32bbc3 Fixes for allocation of striped volumes. 2001-12-07 21:17:12 +00:00
09b3914f5d Fixes for library compilation. 2001-12-07 21:15:33 +00:00
fe644e4c9e Moved across to device-mapper repository. 2001-12-06 14:20:38 +00:00
7b09bf2156 o Updated projects.txt to remove the earlier error which turned out to be
a build error.
2001-12-05 18:04:55 +00:00
987d0aae66 Various fixes & restructure to extract common code. 2001-12-05 16:41:52 +00:00
9cbcbc1c22 o Removed unused MOD_INC/DEC_USE_COUNT 2001-12-05 12:00:01 +00:00
cfc4e2bc60 o Added a few more projects 2001-12-05 11:58:43 +00:00
a03405fa81 o Initial merge attempt
There are still a few odd things going on, so more debugging remains to be
done.
2001-12-05 11:28:41 +00:00
d5c9ccbe6e Correct activation message. 2001-12-05 00:04:18 +00:00
e52772d65f Added more log messages. 2001-12-04 23:20:27 +00:00
1e3259e728 o sync 2001-12-04 14:14:07 +00:00
e905a20a60 Tweaks for make install. -m args replaces verbose to display maps. 2001-12-03 20:23:53 +00:00
88e2be7a33 More striping support & fixes. 2001-12-03 16:27:16 +00:00
8939131600 o Comparison function was sorting things in ascending rather than
descending order.

o free off the sort array when finished with it.
2001-11-30 09:19:46 +00:00
ba37ebff8b o Striped allocator
o  Changed pv_map.c to maintain the list of free areas in size order, which
   is more helpful to the allocators.  If you want to allocate a bit of an
   area call consume_area(area, size), this will adjust the area if there's
   some space left and shuffle it to the correct place in the list.


Not tested.
2001-11-29 18:45:35 +00:00
28f4cb7e07 o I was reading striped volumes incorrectly. 2001-11-29 14:13:43 +00:00
db1e7102cd o Confusingly, dmfs-tdir isn't gone, its now called dmfs-lv.c and its the
old dmfs-lv.c thats gone.
 o Dropped out support for multiple tables in line with ioctl interface
 o Some reordering to better support the userland library
 o Updated to 2.4.16

I'm fairly happy with the way that this is working now, so the next job is
to start the integration with the ioctl interface so there is a single
common dm.[ch] and selectable interfaces (fs or ioctl).

Further improvements can be made even now, but I hope to wait until we've
got this going and integrated and the libdm parts working as well before
investigating other avenues.
2001-11-29 14:00:04 +00:00
07eb7a5830 New patches for 2.4.16 2001-11-29 13:44:46 +00:00
b7c6c685fa configure --with-interface=ioctl (default) or =fs to choose kernel interface 2001-11-28 21:03:50 +00:00
212134df70 Add autoconf & makefile structure like LVM2. 2001-11-28 20:08:11 +00:00
6eeb5528f5 Add -t or --test arg to all tools that update metadata to avoid
committing metadata changes or (de)activating.
2001-11-28 18:03:11 +00:00
54fad845c9 o Output the correct format for the stripe target 2001-11-28 17:52:27 +00:00
d6c0de6fc7 Fix single stripe resizing. 2001-11-28 16:16:44 +00:00
649c8649f7 Make source files depend on makefiles. 2001-11-28 15:00:49 +00:00
da2f53d1b1 o pool_free was leaving one block hanging around. 2001-11-28 14:58:33 +00:00
405139e3b8 o Tool support for segments.
o vgmerge working.
2001-11-28 13:45:50 +00:00
4f8d347171 Use CFLAGS during make rule generation. 2001-11-28 12:28:03 +00:00
bf0db4876c o pool-debug.c contains an alternative implementation of pool that gets
a seperate chunk of memory from dbg_malloc for each pool_alloc.  This
   will allow the bounds checking code in dbg_malloc to do it's stuff.

o  The normal implementation moved to pool-fast.c

o  pool.c now just contains a #ifdef and includes the appropriate .c file.

Alasdair, could you make sure that gcc -MM get's passed all the
CFLAGS please, otherwise the dependencies get calculated incorrectly.
2001-11-28 09:13:00 +00:00
47a14884d6 o Turn on pool debugging by default (-DDEBUG_POOL) 2001-11-28 09:07:53 +00:00
3a7bbc8b08 Fix a memory smash. 2001-11-27 23:12:06 +00:00
1b1d65372c o extra error checking 2001-11-27 20:03:45 +00:00
fd2faaa16e o These now compile. 2001-11-27 17:39:15 +00:00
0609cdb9ea o Get format1 building. 2001-11-27 17:29:56 +00:00
d3bb140f89 vgmerge first cut 2001-11-27 17:02:24 +00:00
b31dc66628 o Sync up todays work on converting to the segmented representation of
logical volumes.  It includes:

   format1 changes.

   metadata.h changes.

   lv_manip.c changed (striped allocation still not done though).

   activate.c changes.

Nothing has been near a compiler as yet.

Alasdair can you look at changing display.c to use to output the mappings
in a more segment oriented format please ?

I haven't put the span list into struct physical_volume to represent allocated
extents.  I think the burden of maintaining it for things like lv_extend may
out weigh it's uses.
2001-11-27 16:37:33 +00:00
09476171a6 Tool support for multiple (striped) segments (incomplete). 2001-11-27 13:42:37 +00:00
33dee813b5 o change chunk_size to stripe_size 2001-11-26 16:30:43 +00:00
bb4e73c40b o More metadata changes. 2001-11-26 16:18:48 +00:00
b1f23ffa94 LV create/extend prototype changes for striping 2001-11-26 15:31:46 +00:00
b0e8cec1e7 o make it obvious that stripe_segment is variable sized. 2001-11-26 13:15:22 +00:00
5077ae19bc o segments will have to be held as an array of pointers since they're now
variable sized.
2001-11-26 13:03:36 +00:00
0d8447bf59 o sync the new in core rep. for Alasdair.
This will break everything !  Hopefully things will be working again by
   this evening.
2001-11-26 12:49:29 +00:00
c6cf08a274 additional patch required 2001-11-23 12:35:31 +00:00
dc49ae519e o Revised seq_file usage after discussions on linux-fsdevel 2001-11-22 15:14:20 +00:00
904539476a o Make sure that every switch has a short option, even if it's
non-displayable so we can remove the pointer mangling that was
   breaking 64bit arch.s
2001-11-22 14:37:07 +00:00
3fbf02dc82 o activation & active status tests
o lvdisplay fields from kernel
o update lv->size on resize
2001-11-21 19:32:35 +00:00
c9392a840d dmdir path 2001-11-21 19:20:41 +00:00
d164e8ab72 o Remove an old debug statement 2001-11-21 18:24:22 +00:00
6dc62c9fb6 o Display major number 2001-11-21 18:12:41 +00:00
87a9684d66 o use the major number returned from dm_ioctl. 2001-11-21 17:57:57 +00:00
94525e2f44 o There's no need to prefix dm_dir() with /dev/ anymore 2001-11-21 17:20:49 +00:00
b408b1b3b9 o You can now specify the dev directory for libdm
o  dm_dir() returns the full path to the device-mapper dir (eg, /dev/device-mapper).

o  put stat in on _rm_node
2001-11-21 17:08:37 +00:00
27c2f09e32 o Removed _check_devfs
o  We now do a stat to see if the device node is there
2001-11-21 16:47:10 +00:00
19bc4d3349 o Remove hard coded path to /dev/device-mapper/control 2001-11-21 15:49:45 +00:00
f2b6c424d6 Tidy makefiles 2001-11-21 15:41:14 +00:00
a49d4453e9 o Change name of libdm.h 2001-11-21 15:15:37 +00:00
65e50087b9 o Use MKDEV to build the dev_t for mknod 2001-11-21 15:14:35 +00:00
2d90f759d9 o Don't use dmt->dmi until it has been initialised. 2001-11-21 14:52:16 +00:00
4230ac7674 o Migration of device-mapper from LVM_WORK to it's own (public) repository.
Please use this one from now on.
2001-11-21 12:47:42 +00:00
d96e9182e9 o Oops, I thought this was checked in ages ago. 2001-11-21 09:21:31 +00:00
68c87b9616 o Sync. only 2001-11-21 09:20:05 +00:00
7f8e9a0b6d o _emit_target wasn't spotting contiguous targets properly. 2001-11-19 15:44:06 +00:00
81a229f2a5 o Use new info interface to dm. 2001-11-19 15:38:39 +00:00
8be7ae2733 vgdisplay 2001-11-19 15:20:50 +00:00
846bca4cb1 file cmgr.h was initially added on branch CLUSTER_TAG. 2001-11-19 14:40:32 +00:00
f36f353789 file cmgr.c was initially added on branch CLUSTER_TAG. 2001-11-19 14:40:32 +00:00
939a2731ed file clvm.h was initially added on branch CLUSTER_TAG. 2001-11-19 14:40:32 +00:00
835dab97ff Zero first 4k of new LVs. 2001-11-16 15:38:52 +00:00
fa904b53be Don't need EXTRA_LIBS as autoconf fills in LIBS for us with all that is needed.
BTW if there are any *real* autoconf experts out there please feel free to flame
me.
2001-11-16 11:39:13 +00:00
0ec52dddce size_ts aren't really pointers but there are no format specifiers for them,
so this will just have to do.
2001-11-16 11:37:45 +00:00
c289355a3a Fix format characters for printing size_ts 2001-11-16 10:56:11 +00:00
02a13a5a18 Do substitution on LIBS so that those platforms that need -lncurses as well as
lreadline will work.
2001-11-16 10:40:16 +00:00
6cf2a0281b lvrename (without reactivation) 2001-11-15 17:27:45 +00:00
120d35f9af Use POSIX defined PRIu64 for formatting 64 bit unsigned integer types 2001-11-15 15:18:53 +00:00
2b15d5e7b3 Use FMT_64 to format 64bit types 2001-11-15 14:27:51 +00:00
fc167bd3f0 define FMT_64 to be the right format string for 64-bit types a la GFS 2001-11-15 14:27:34 +00:00
91b04abf05 Use inttypes.h 2001-11-15 14:14:03 +00:00
77faac8740 #include <string.h> for memset 2001-11-15 11:46:00 +00:00
43b3d54855 More LV-related tidying. lvdisplay without args now shows all LVs. 2001-11-14 18:38:07 +00:00
69e9b85700 Avoid generating duplicate lv names 2001-11-14 14:12:01 +00:00
0b6d132759 Miscellaneous tidying 2001-11-14 13:52:38 +00:00
7c233c6c0c o lvcreate no longer needs the explicit -n flag
o  disabled zeroing of lv until bug's worked out
2001-11-14 12:07:37 +00:00
c35b290fa4 o Prefix static var with '_' 2001-11-14 10:44:14 +00:00
3d95cfb367 o Added dev_open and dev_close functions
o  Changed disk-rep to use these

o  if NDEBUG is not defined the dev_cache will check for open devices on
   teardown.

I was hoping this would speed things up.  But I'm still getting:

reti:/home/joe/sistina/LVM2/tools# time ./lvm vgchange -a n
  Volume group vg0 successfully changed

real    0m5.751s
user    0m0.060s
sys     0m0.070s

even though I have only 1 device with the vg on it passing the filters.
2001-11-14 10:01:52 +00:00
b90fc3a56e o Deal with sparse lv arrays (on disk)
o  new fn. dev_zero which zero's an area of a device
2001-11-13 18:52:52 +00:00
1ef3fdccf5 o lvdisplay now shows LE / PV map
o fix LE allocation when first PV is full
o reduce VG free_count when removing PVs from VG
2001-11-13 17:53:06 +00:00
02b7f77bd8 o Put underscore between vg and lv name. 2001-11-13 16:14:54 +00:00
0ac7ead922 Merge lvreduce & lvextend into lvresize. 2001-11-13 14:17:50 +00:00
da9d0e03ce o Stuff 2001-11-12 19:28:50 +00:00
120f65f672 o Add ALLOC_SIMPLE 2001-11-12 17:55:05 +00:00
200a14caa4 Remove hard-coding and create device-mapper directory if required 2001-11-12 17:21:25 +00:00
35bf6da8e2 o if any pattern rejects a device, and there were no accepts then reject ! 2001-11-12 17:06:33 +00:00
f08f70276c o check result of an allocation 2001-11-12 16:00:52 +00:00
1ae50fd95b iospace restructured 2001-11-12 15:10:01 +00:00
40512beb47 o add fs.c to the Makefile 2001-11-12 13:02:06 +00:00
0d7f9b2c94 o add uplink from vg to cmd_context 2001-11-12 12:23:10 +00:00
52f42140a7 o Plug in fs_(add|del)_lv 2001-11-12 12:20:58 +00:00
3f6c50297f o Split struct io_space into:
struct format_handler - format methods
   struct format_instance - links instance data, methods, and cmd
   struct cmd_context - dev_dir, memory allocator, device filter
2001-11-12 12:16:57 +00:00
f72d80afc5 o Compile errors 2001-11-12 11:48:31 +00:00
7c5cb13b22 o Ready for testing 2001-11-12 11:42:29 +00:00
d728750eb2 o Fix module ref counts so that you can actually unload dm-mod
N.B. This means that you have to take very great care in the event that
   you want to access the dcache tree from in kernel

 o Added extra field to allow out of memory conditions to result in the
   correct error code. (This hasn't received a lot of testing...)

I've ditched the final project (which would have cleared my whole list)
since its got other complications which I don't have time to fix right
now. Still as Meatloaf says, two out of three ain't bad!
2001-11-10 17:11:36 +00:00
02a70e5667 o Added lvextend
o Full signed arguments to lvreduce/lvextend
o Consistent lv_number/pe map use
o Populate pv->pe_allocated
o Fixes for allocation/writing of multiple LVs
2001-11-09 22:01:04 +00:00
44e51ea5fa sync only, not ready yet 2001-11-09 08:48:22 +00:00
87e201460a lvdisplay & lvreduce 2001-11-08 16:15:58 +00:00
039bd945e2 more todo 2001-11-08 08:19:06 +00:00
e9e52d2b4b o Always set LVM_READ.
o Avoid duplicate deallocation.
2001-11-07 22:47:43 +00:00
2bf92e7399 Oops. Forgot to check this in earlier. Changes as per previous check in
comments.
2001-11-07 19:27:17 +00:00
5b0df241f0 o more todo 2001-11-07 17:38:25 +00:00
76f5b05eff o Lot's to do 2001-11-07 17:25:17 +00:00
40fb6c998f o Added lvs_in_vgs_opened 2001-11-07 15:02:07 +00:00
33f50a342d o pool_empty was very wrong 2001-11-07 14:11:20 +00:00
81523ab68a Tidy and changes to make code smaller.
o Created dmfs.h as a private header for the filesystem code
 o Using seq_file.[ch] written by Al Viro as a generic mechanism for /proc
   style files which have one record per line. We use a slight modification
   here, so if you are using a recent -ac kernel you'll need to replace the
   existing seq_file.[ch] with  the ones here and do a bit of editing to make
   it work. I'll submit the changes to Al Viro shortly as they are very
   small and I think make sense generally.
 o Using fail_writepage()
 o Init code for filesystem now all in dmfs-super.c
 o Some common code reduction amoung the dmfs-*.c files
 o Auto allocation of major device number (default). You can specify a
   particular major by using a module argument. If built in then you don't
   get this option at the moment but it could be added if required.
 o Hotplug support
 o General tidying
 o Updated projects.txt file
 o Patches updated to 2.4.14
2001-11-07 12:12:56 +00:00
2bf8cc62cf o Another pass at the activation code 2001-11-07 11:51:42 +00:00
1ae8247af3 Added GPL disclaimer 2001-11-07 08:50:07 +00:00
5ef32227ec lvcreate 2001-11-06 19:02:26 +00:00
6456e773bd o lv_extend 2001-11-06 12:01:46 +00:00
234fe53ca3 o Factor _allocate out for use by lv_extend 2001-11-06 11:31:29 +00:00
7c93e7a7b3 o lv_reduce
o  pv_maps wasn't taking a list of acceptable pvs
2001-11-06 11:19:33 +00:00
8afc6c7f4b o Contiguous allocation 2001-11-06 10:55:01 +00:00
4609d0fa3a o lv_manip.c will contain the code for lv_create, lv_extend and lv_reduce. 2001-11-06 10:29:56 +00:00
d452c035c6 Reinstate size of lv 2001-11-05 18:07:44 +00:00
45113c8f5a o code for building free area lists on a pv. Compiles but not run. 2001-11-05 16:41:38 +00:00
0acdd3c62b o adjacent extents are now merged into a single target when activating. 2001-11-05 13:37:13 +00:00
96d7d0a33e lvcreate prototype 2001-11-05 13:06:03 +00:00
b6b280267b o build lv name from <vg>_<lv> 2001-11-02 16:45:44 +00:00
6e6d253b1a Link in the activation library. 2001-11-02 16:28:04 +00:00
d92c105db2 o First pass at activation 2001-11-02 13:45:05 +00:00
906db728d6 o Changes to activation interface
o Add pointer lv->vg
o Some naming tweaks to improve clarity
2001-10-31 17:59:52 +00:00
c4b7411565 o LGPL list implementation 2001-10-31 12:47:01 +00:00
de06396046 o random little fixes 2001-10-30 17:53:21 +00:00
ee6bfeb8e3 lvchange 2001-10-30 14:32:48 +00:00
058347321f basic lvscan 2001-10-29 18:23:35 +00:00
feefe49324 o Add read_ahead and stripes to struct logical_volume 2001-10-29 15:34:56 +00:00
187381a9a2 prefix & vgname in lvname 2001-10-29 15:28:00 +00:00
993dfa4368 lvremove 2001-10-29 13:52:23 +00:00
7e35a16440 o Added two items which ought to be done when we update to 2.4.14-pre3 or
above.
2001-10-29 11:06:46 +00:00
e4eeb15926 o Added a file containing a TODO list.
Please add to/edit this file as you think of new ideas or discover bugs. The
items in it are in no particular order. They are also only ideas and hence may
never get implemented depending on whether they turn out to be good ideas or
not.
2001-10-29 10:03:05 +00:00
634e0db26d o rfilter was no longer accepting by default 2001-10-25 18:12:44 +00:00
56855c23e1 o log/overwrite=1 in config file to overwrite instead of append to log 2001-10-25 17:25:48 +00:00
0b00f742e3 o was freeing memory from the wrong pool 2001-10-25 15:24:35 +00:00
b7ab3f673c o fopen error message
o debug options in makefile
2001-10-25 15:07:26 +00:00
be04ea1e35 o pfilter stores results for all aliases. 2001-10-25 14:51:51 +00:00
1f8e695802 o It's a bit of a hack, but the regex filter now makes sure a device path
that passed the filter is at the front of the aliases list.
2001-10-25 14:41:28 +00:00
2d82b2c64f o rfilter now checks all aliases for a match 2001-10-25 14:19:39 +00:00
d076caf473 o use dev_name(dev) to get the name of a device, this operation is cheap
since it just get's the first alias.
2001-10-25 14:04:18 +00:00
c7abdefa31 o Remove a couple of warnings, and one bug in ttree. Spotted by the optimiser 2001-10-25 13:08:29 +00:00
ba772c0bca o Shuffle the keys to stop degeneracy. 2001-10-25 12:38:18 +00:00
5bad234119 o Trivial binary tree 2001-10-25 11:38:19 +00:00
c7e7baaf23 o added aliases list to struct device. 2001-10-25 11:34:55 +00:00
36658a671b o Correction in logic for write access to tables 2001-10-25 11:05:29 +00:00
045f2e10ba o Fix typos from yesterday 2001-10-25 10:37:05 +00:00
fb5a7db66d o Merged common code between hash_destroy and hash_wipe. 2001-10-25 08:31:43 +00:00
ba7d33982e persistent cache fully incorporated. Goodbye to scanning /dev/cdrom :-) 2001-10-24 17:53:50 +00:00
c62279a755 o Updated 00_makefile
o 00_bh-async-3 has been merge with vanilla
2001-10-24 10:52:10 +00:00
17fa1a7ffb o Error list handling now part of fs rather than part of table. 2001-10-24 08:26:10 +00:00
e89ceac351 o Fix bug in dmfs-error.c where it could return too many bytes under some
circumstances.
 o Use sscanf() in dmfs-table.c
 o Use do_generic_file_read() instead of original hand made loop in dmfs-table.c
2001-10-24 07:51:42 +00:00
0b8c30c109 persistent filter & some log message changes 2001-10-23 18:20:27 +00:00
9ab0f463cc o removed old files 2001-10-23 14:17:07 +00:00
6433dda7b8 o forgot to use the path passed into _read_array. 2001-10-23 13:12:05 +00:00
fa7a2f4be4 o test program for the new persistent filter. 2001-10-23 13:11:28 +00:00
ba90e16505 deallocations 2001-10-23 12:33:57 +00:00
008f710203 o rethink of the persistent filter 2001-10-23 12:24:55 +00:00
df2740f126 filter integration into tools 2001-10-23 11:50:49 +00:00
2db89d143e o forgot to retry on EINTR or EAGAIN, doh ! 2001-10-23 11:16:30 +00:00
0525d49da3 o forgot 'static' 2001-10-22 14:40:31 +00:00
e2b0745882 o composite filter that allows us to merge filters. Think of it as &&'ing
filters in order.

eg,

	f = composite_filter_create(2, regex_filter, persistent_filter);

  ownership of the filters passes, they will be destroyed when f's
  destroy method is called.
2001-10-22 14:39:12 +00:00
92e804fc50 o Filter which caches valid devices in a file. Pass in init == 1 to the
constructor if you want it to ignore the existing cache and check every
  device again (eg, vgscan, pvscan).
2001-10-22 14:14:00 +00:00
67abf45576 reinstate a removed line 2001-10-22 13:44:09 +00:00
d2c9c814e7 o removed 00_latest since it never is. 2001-10-22 10:03:05 +00:00
22f8881a64 o tidying 2001-10-21 10:24:10 +00:00
4ab20322fe o Filter for the dev cache that takes values from config file:
devices {

        # first match is final, eg.  /dev/ide/cdrom
		        # get's rejected due to the first pattern

					filter=["r/cdrom/",         # don't touch the music !
							"a/hd[a-d][0-9]+/",
							"a/ide/",
							"a/sd/",
							"a/md/",
							"a|loop/[0-9]+|", # accept devfs style loop back
							"r/loop/",        # and reject old style
							"a/dasd/",
							"a/dac960/",
							"a/nbd/",
							"a/ida/",
							"a/cciss/",
							"a/ubd/",
							"r/.*/"] # reject all others
}


Alasdair this is ready to roll into the tools now.
2001-10-19 18:20:37 +00:00
5370eeecea o First pass at the regex code. lib/regex/matcher takes an array of regex's
and builds a *very* efficient engine that will tell you which regex a string
  matches with only a single pass through the string.  To be used in the config
  file when specifying devices.

o Anchor's aren't supported yet (^ and $) but that won't take long.

o Also when we get some realistic config files we may want to consider adding an
  extra level of indirection to the dfa state in order to compress the table.
  It all depends on how large typical tables get.
2001-10-19 14:36:57 +00:00
ba71cb5dd7 pvdisplay 2001-10-18 16:55:19 +00:00
9aad6c2c52 o Remove unused variable. 2001-10-18 15:59:25 +00:00
4d9627f20c pvchange 2001-10-17 15:29:31 +00:00
c142492e91 o Fix crash that Patrick reported 2001-10-17 15:03:00 +00:00
6bf8d9e207 o Fix a typo. This should fix devfs support. 2001-10-17 14:34:53 +00:00
4f9a6168c1 o Patches to go with earlier check in 2001-10-17 13:13:25 +00:00
38397f99aa Ok. this is the big one.... the change to the new fs interface.
Things to note:

 o Changes to the dm-*.c files have been kept as small as possible during
   the development of the new fs interface and there are a few places where
   the new code does odd things to give the original code what it wants. These
   places will gradually go away during the next few days once we are sure the
   new code is sound.
 o I've spent most of my testing time looking at the parser since thats where
   a lot of the changes are, I've not checked the actual I/O very much, but
   then that code hasn't changed at all.
 o The print operation in the target type operations is there to help in
   debugging and will go away eventually
 o There are some other printk's which will also go away once we are sure that
   things are working correctly.
 o I've tagged the old code with PRE_DMFS if you want to use that until this is
   stable.
 o There are no kernel patches for this yet (will fix after lunch... :-)
      o Makefile needs some changes
      o need to EXPORT_SYMBOL(deny_write_access); in ksyms.c

How to use the new interface ?

 mount -t dmfs dmfs /mnt/dm
 cd /mnt/dm
 mkdir fish fish/tank
 cd fish/tank
 cat ~/my.table > table
 cd ..
 ln -s tank ACTIVE

Creates a logical volume called fish and activates a table called tank, if
there is a problem doing the link, look in /mnt/dm/fish/tank/errors to see
what is wrong.

If you see any odd things happening, let me know right away as I'm sure there'll
be one or two things that slipped through my testing.
2001-10-17 11:34:50 +00:00
f8686d0e75 o Update to parser
o Extra checks in symlink routines
2001-10-17 11:09:43 +00:00
549e3c8f9d pvscan 2001-10-16 18:07:54 +00:00
bb56225b95 o Fixed infinite loop in parser
o Fixed error handling whilst creating volumes
 o General tidy up
2001-10-16 17:09:27 +00:00
f00be261ba vgchange 2001-10-16 16:25:28 +00:00
9cd94f26d0 o Get file size correct for table
o Make parser look at the right object
2001-10-16 12:17:54 +00:00
4d8f5c80a7 o Fixes to parsing code 2001-10-16 11:56:55 +00:00
24a23acc3d o Tidy up, removing debugging printk's no longer needed 2001-10-16 10:38:13 +00:00
ca8703cfd8 o More bug fixes 2001-10-15 22:39:14 +00:00
6dcbb5b2f8 vgextend 2001-10-15 22:04:27 +00:00
a84fdddb2a vgcreate basic extent size validation 2001-10-15 20:29:15 +00:00
38bb2f8ceb More vgcreate error trapping 2001-10-15 18:39:40 +00:00
23f5ef4345 o More fixes 2001-10-15 16:40:17 +00:00
ef8a2a9054 o lvm readline error-case tidy-up
o more vgcreate error cases
2001-10-15 12:49:58 +00:00
96103d0e36 o Some bug fixes
o Added symlink ops
 o Some extra sanity checks
2001-10-15 11:31:00 +00:00
ff5f6748df o vgcreate 2001-10-12 14:25:53 +00:00
1c1fd6c366 vgcreate 2001-10-12 12:21:43 +00:00
32d37d00cb o make ios the first argument to pv_create 2001-10-12 10:52:32 +00:00
82f6cda966 o lift call to check out of pvcreate_single 2001-10-12 10:45:04 +00:00
f1ff8ff0d0 o rename _single pvcreate_signle 2001-10-12 10:43:36 +00:00
756c72902f o made _single static 2001-10-12 10:42:31 +00:00
73f8f0bbd0 o pvcreate
o added uuid unit

o stubbed partition stuff
2001-10-12 10:32:06 +00:00
18ed528f5d o Further tidyups and fixes. 2001-10-12 10:06:40 +00:00
8fd2f136bc sync 2001-10-12 09:52:30 +00:00
0524b1bf67 vgreduce, vgremove, vgrename & vgscan 2001-10-11 21:35:55 +00:00
15716f65ce Some more sync ups
o Error file routines (initial idea)
 o Various fixes for bugs
 o Tidy a few things
 o Added a bit of debugging code ready for when this gets tested
 o get_exclusive_write_access() function which will get moved into namei.c
   I hope (and rewritten accordingly), should this become the final version
   used.

Still a few more areas need thinking about, but in general much closer now I
think. Last area to sort out before testing is the symlink code which is
pretty close now... just a few more checks needed and the actual calls to
the core code.
2001-10-11 20:29:00 +00:00
d46bdba332 o try incrementing pv_number from 1 2001-10-11 16:31:09 +00:00
760728110a o if contained &= instad of & 2001-10-11 15:09:31 +00:00
12d0a194ca o initalise list_heads, initialise list_heads, initi .. 2001-10-11 14:21:38 +00:00
4104543508 o a very quick hack to get vg_number right 2001-10-11 14:10:18 +00:00
5c211db015 o set PV_ALLOCATABLE flag correctly 2001-10-11 13:34:17 +00:00
2dc6180f8d o pv->system_id 2001-10-11 13:22:51 +00:00
e222a34b69 o vg->pv_act 2001-10-11 13:05:55 +00:00
ef17d95063 o calculate pv_numbers and lv_numbers for LVM1 support 2001-10-11 10:55:19 +00:00
853502e5d7 o pe_start wasn't being set properly when exporting to disk
o added a check for lv's with null lv_name

o setup pv->lv_cur correctly

o test program for vg_write
2001-10-11 10:08:44 +00:00
c18e297e77 o Everybody needs dm.h
o Fixed to work with highmem
 o Added dmfs private inode struct for lv and table directories
 o Fixed a number of errors/typos
 o Status file read returns 0 so we can leave this until we've actually got
   something to report in this now.
 o New locking on tables.... still some issues to be worked out here but
   closer now I think.
 o Now use mapping of table directory to hold pages rather than mapping of
   table file inode. Need to write a note to myself to fix issues with the
   file length at the same time....

Well thats enough for tonight I think. The error file will be part of
tomorrows work.
2001-10-10 21:49:21 +00:00
c5a49599ba o sync 2001-10-10 17:11:31 +00:00
df9da9edf5 standardise some log messages 2001-10-10 16:36:32 +00:00
e2200fd050 o builds a very sub-optimal table 2001-10-10 15:30:31 +00:00
c6207f5d9c o allocate and zero the extents before exporting the lv's 2001-10-10 14:56:53 +00:00
4302b7ff6b o zero all of uuid 2001-10-10 13:33:20 +00:00
50a7923438 o uuid_list->id should be NAME_LEN wide 2001-10-10 13:30:58 +00:00
ab416445c8 o sizeof(NAME_LEN), don't do that 2001-10-10 13:24:16 +00:00
a54698d43c o forgot to init a list head 2001-10-10 13:09:40 +00:00
c5a77cc1c0 o dev_write 2001-10-10 13:03:10 +00:00
a9ffa811fc Tidy metadata diagnostic messages. 2001-10-10 12:45:20 +00:00
080a2608e0 o return data not 1 in read_ov 2001-10-10 12:42:03 +00:00
57f2e83d6a o check for orphaned pv's when reading 2001-10-10 12:28:10 +00:00
5b030139d3 o pv_setup for format1, this is the last one ! 2001-10-10 10:55:55 +00:00
0da1ff42d1 o AC_INIT was pointing to an old file 2001-10-10 10:11:25 +00:00
2c599b7baa o metadata.h was in here twice 2001-10-10 10:09:12 +00:00
5c8af8d21a o pv_write for orphan pv's 2001-10-10 10:05:29 +00:00
026f3cfde2 o add munging for format1 and 2 2001-10-10 09:36:29 +00:00
f6349180e8 o Code to calculate the metadata layout. 2001-10-10 09:25:04 +00:00
aa6421921c o stub pv_write to stop tools crashing 2001-10-09 17:44:58 +00:00
7d41d2dab2 o fix seg fault while reading extents 2001-10-09 17:36:48 +00:00
f0b4d18f93 o remove another spurious error message 2001-10-09 17:30:20 +00:00
6750f06e10 o vgremove.
o filter devices by major.
2001-10-09 17:20:02 +00:00
b2bd38fa9e o spot empty list in build_vg 2001-10-09 17:09:46 +00:00
3482a01e22 o proposed interface to the kernel driver 2001-10-09 16:44:30 +00:00
6335467552 o dev-mgr disappears 2001-10-09 16:13:12 +00:00
4a39e65b62 o change pv_read to take a name rather than a device 2001-10-09 16:05:34 +00:00
c50a23e918 o remove spurious log message 2001-10-09 14:42:58 +00:00
1e76b72b98 o hack, hack, hack 2001-10-09 14:26:45 +00:00
b94cf39eef o vg_write compiles 2001-10-09 10:47:52 +00:00
fef254ffff o get_vgs works 2001-10-09 09:22:50 +00:00
e5495863a2 o pv_Read works 2001-10-09 08:58:52 +00:00
3b4df2abf0 o get_pvs now works for format 1 2001-10-09 08:11:52 +00:00
aef2aee6a4 vgrename & vgck 2001-10-08 18:44:22 +00:00
d0d9519149 o test program for get_pvs 2001-10-08 18:09:31 +00:00
685df1d2c5 o get_pvs for format 1
o fix vg_read if vg doesn't exist
2001-10-08 17:53:43 +00:00
08e6b6f2e7 o added pretty printing to read_vg_t, run this on your system
to see what vg's you've got

S: ----------------------------------------------------------------------
2001-10-08 17:28:49 +00:00
66c887d0f3 o read_vg works (or so it claims) 2001-10-08 16:08:16 +00:00
22e9960697 o dev_cache_t program works 2001-10-08 13:58:52 +00:00
64aa6e1f2d o sync 2001-10-08 12:11:33 +00:00
7a93ed9d04 o we were stuill building dev-mgr files 2001-10-08 10:35:59 +00:00
a905e922e9 o read_vg_t compiles 2001-10-08 10:20:25 +00:00
f9f08fc720 o makefile for read_vg_t 2001-10-08 09:50:00 +00:00
8d402d76d0 o get things compiling 2001-10-08 09:45:16 +00:00
46fda6281c o test program for reading a vg 2001-10-08 08:47:27 +00:00
a14dbe1ea6 Sync include file changes. 2001-10-05 21:39:30 +00:00
18810a4c16 o end of day sync 2001-10-05 16:36:53 +00:00
147bc80dba o replace {stack; return 0;}'s with a macro (just for this file). 2001-10-05 15:48:05 +00:00
c7a484195a o low level write path 2001-10-05 15:20:40 +00:00
4968eb6503 o finished writing extent reading code 2001-10-05 13:59:44 +00:00
a6f2d698a9 revised flags and comments 2001-10-05 13:03:03 +00:00
ea5ed93ea5 Just a small sync of pending changes before I start looking at this again
more seriously.

 o Odds and ends
2001-10-05 10:00:13 +00:00
e1140134c6 metadata status flags regrouping & comments; misc tool changes 2001-10-04 22:53:37 +00:00
5ed11e012e o vg_read for format1 2001-10-04 17:48:55 +00:00
5380bd39ca makefile support for tests 2001-10-04 12:07:29 +00:00
2ee2685688 o define the uintN_t types 2001-10-04 11:40:13 +00:00
782002245b o forgot to add this before 2001-10-04 10:25:34 +00:00
7fc0905843 o got dbg_malloc_t working, Alasdair could you look at the Makefile.in it
seems to be having trouble with the dependencies.

o removed some files from the lib makefile that don't compile yet.
2001-10-04 10:13:07 +00:00
72ecb99e54 o Use the __alignof__ extension to set DEFAULT_ALIGNMENT to that required
for a 'double'.
2001-10-04 09:10:11 +00:00
c863507d08 vgcreate & lvmchange outlines 2001-10-03 20:38:07 +00:00
cff86c9093 vgrename & pvchange outlines 2001-10-03 17:03:25 +00:00
0479dfcc54 o added dev-cache.c, dev-io and sorted source files alphabetically 2001-10-03 12:46:17 +00:00
68dd67f21c o moved dev-cache to device dir 2001-10-03 12:43:29 +00:00
540f6858b5 o I've moved the dev-cache and dev-io into here since this directory has a
better name.  dev-mgr will be removed at some point.
2001-10-03 12:41:29 +00:00
b61e791a4f lvremove outline 2001-10-03 12:34:08 +00:00
d0986f9482 o code sync for dev-cache.c
o made copyright headers the same

o added __attribute ((format ... to print_log so we'll get better compile errors

o added iterator to the hash table
2001-10-03 11:06:31 +00:00
112cb0dc28 pvscan framework 2001-10-02 17:09:05 +00:00
0d3d7fdcf2 o test program for the device cache 2001-10-02 13:44:44 +00:00
5d6b89ef3b o test program for the hash table. 2001-10-02 12:46:04 +00:00
ed0b26c09e o Test program for dbg_malloc unit.
I'm postfixing test programs with _t, and benchmarks with _b
2001-10-02 12:27:55 +00:00
ae292bd920 Another step towards consistency & compilation. 2001-10-01 22:12:10 +00:00
6c85a90723 Misc structural changes. 2001-10-01 19:36:06 +00:00
852592066c Misc structural changes. 2001-10-01 19:29:52 +00:00
96e1bc9b44 o changed dev-manager to a dev_filter 2001-10-01 16:21:21 +00:00
b41d81ed31 o get block size moved to dev-io.c 2001-10-01 16:07:29 +00:00
e241ec2244 merge partition code 2001-10-01 15:59:40 +00:00
16e1f1a94c Tidy includes 2001-10-01 15:53:21 +00:00
7a68c42b26 o drop the reference counting in the devices. 2001-10-01 15:43:51 +00:00
37ccc2e118 Merge fixes 2001-10-01 15:29:39 +00:00
4192fe1ab2 o missing * 2001-10-01 15:28:28 +00:00
d5c743d7bb o added filter type. 2001-10-01 15:27:16 +00:00
11814d63e8 Tidy include files 2001-10-01 15:14:39 +00:00
b753656d50 Create symlinks to .h files in an include directory 2001-10-01 13:36:54 +00:00
f7e87611fc o I'm splitting dev-manager in two. dev-cache is the bottom layer that
handles devices.  Dev-manager will sit on this filtering the view.
2001-09-28 15:42:25 +00:00
1fb0e1900e o list.h from kernel for userland tools to use. 2001-09-28 13:19:17 +00:00
954a9731e0 o logical data structures 2001-09-28 13:15:30 +00:00
65c3364ad8 o generic hash table to store void *'s, not efficient, but adequate for LVM. 2001-09-28 13:08:44 +00:00
3d72b7dccc o rewrite of dm_user_bmap, not tested though. 2001-09-27 10:15:02 +00:00
13ee569f06 Fix prototype for malloc_aux 2001-09-27 10:01:17 +00:00
d79ef23a75 Don't include asm/* files 2001-09-27 10:00:47 +00:00
5d0797d4ba o Kill write funcs for error/status files
o Redo write logic for table file
 o Relax rules for symlink content by removing the rewriting function

Well I probably won't get a chance to work on this tomorrow, so this is my
changeset to date.
2001-09-26 20:24:39 +00:00
47a8d7475f o table creation works again. 2001-09-26 19:48:20 +00:00
4939053121 o It should build now 2001-09-26 17:32:57 +00:00
b525bf554e o typos 2001-09-26 17:07:10 +00:00
f00285d2b2 o remove steve's insane ramblings from my code. 2001-09-26 14:32:07 +00:00
040f8d6eda o Lunchtime. 2001-09-26 11:47:02 +00:00
66d905325c o More updates 2001-09-26 09:26:10 +00:00
8b0cd95e73 o Beginnings of new interface. 2001-09-26 08:06:46 +00:00
d867cca6d9 fix memory leak 2001-09-25 16:26:38 +00:00
a28f736369 o quick tidy up 2001-09-25 15:23:20 +00:00
5c3a71cc59 lvactivate checkpoint commit 2001-09-25 12:49:28 +00:00
cef6dadb08 Another missing dependency. 2001-09-24 22:44:06 +00:00
36be817a3e o Check in case of setting up volumes before root is mounted. 2001-09-24 15:18:45 +00:00
02f571f081 Well when things start looking so complicated that future direction becomes
non-obvious, its time to simplify :-)

 o Moving towards a simpler and more obviously correct interface
 o Removed some fs operations in directories representing volumes
 o Changed some file names
 o Made things cleaner

more changes to follow...
2001-09-24 15:10:33 +00:00
157159e487 Fix dependencies. 2001-09-24 12:05:04 +00:00
02ada9f800 Makefiles & autoconf. 2001-09-21 12:37:43 +00:00
6fcf9a97bb Initialise root node pointer. 2001-09-21 12:32:37 +00:00
17a5d8799f Unused variables. 2001-09-21 12:31:57 +00:00
31f3fe7a22 o Sync up of todays changes .... nothing very important 2001-09-20 22:58:06 +00:00
89e46d3d83 o Bug fix in error path 2001-09-20 20:22:15 +00:00
885795e67d o Use ERR_PTR and PTR_ERR rather than an extra argument. 2001-09-20 19:25:58 +00:00
92bfb53dd4 o Changed to use table->err_msg rather than passing functions around 2001-09-20 18:22:35 +00:00
4cecbeb115 o Some new files (also part of new fs interface) 2001-09-19 21:28:25 +00:00
5971480f55 o Further changes to new file system interface 2001-09-19 21:27:46 +00:00
05bebea511 o Removed the error reporting function from the target constructor function
arguments. Errors are now reported by setting a pointer in the table to
   point to an error message.
2001-09-19 21:27:15 +00:00
76fa6c5cfb hardsect/blksize handling 2001-09-19 17:46:27 +00:00
633b68b518 o Added ref counting to tables
o Further changes to new fs interface
2001-09-19 16:01:27 +00:00
6913d8e995 o Fixed a bug where we were not holding a reference of the block devices
used by the targets correctly.
2001-09-19 14:54:44 +00:00
f3654e6f8d o Change the deallocation of tables to match the vmalloc changes in my
previous commit
2001-09-19 11:02:02 +00:00
d685dbcf22 o Cut down number of vmallocs to increase speed and efficiency 2001-09-19 10:59:10 +00:00
6a57fa079e o More fs fiddling. Another check point commit. 2001-09-19 10:32:51 +00:00
0a91d145ba o Bug fix to LV_BMAP ioctl()
o Account for I/O against tables rather than logical volume devices
2001-09-19 10:32:09 +00:00
c2866e799d Fix allocation & list-handling. 2001-09-18 20:03:00 +00:00
d8cffcaae7 These files are now a bit closer towards what I'm aiming at. Still a lot
more to do though.
2001-09-18 16:54:14 +00:00
30abca7be2 Should have been included in the previous commit. 2001-09-18 16:53:18 +00:00
edce87f3fb o Changed dm_create() to return a struct mapped_device rather than an int
o Changed dm_remove() to accept a struct mapped_device argument rather than
   a name
 o We no longer have to look up devices by name, the dcache handles that
   nicely for us
 o Fixed a bug where we were freeing a structure before we'd finished with
   it.
 o The name field in struct mapped_device is now only used in a very few
   places in dm.c and will be replaced in future with a back reference to
   the dentry rather than keeping the name in two places.
2001-09-18 16:52:50 +00:00
66bac98fc2 o New file dmfs-super.c
o dmfs-dir.c becomes dmfs-lv.c
 o dmfs-file.c becomes dmfs-table.c
 o A few tweeks and updates

The main reason for the slow progress on these files (which are not yet used
by the device mapper) is that we are working out what this interface should
look like as we go along.

Once this has evolved a bit further and in a state where it can be used we'll
announce it on the lists for further comment.
2001-09-18 15:38:54 +00:00
59156de92b Error checking: only allow block devices & test for 'nodev'. 2001-09-17 21:17:30 +00:00
e0d7d10600 o Again, please ignore this for the time being. 2001-09-17 19:05:49 +00:00
daaf862257 o Arbitrary mount path.
o Name length 128.
2001-09-17 16:55:31 +00:00
9de53d4b59 o Work in progress, please ignore these files for a day or two whilst I
get everything going.
2001-09-17 15:42:59 +00:00
f1571e2d46 o Fixed code where return value of vmalloc wasn't checked 2001-09-17 11:23:13 +00:00
bd28d06298 o Use count should be an atomic_t 2001-09-17 09:01:23 +00:00
a24e4655eb o Targets now get rw passed through so they can do COW for example
o Added error handler (not sure that this is the "correct" way to do
   this at the moment, so its a bit exprimental for now)
2001-09-14 16:22:02 +00:00
20a6c8d8e5 o Support /sbin/hotplug 2001-09-14 15:35:06 +00:00
98d264faf4 o Made pending I/O wait uninterruptible 2001-09-14 14:03:02 +00:00
321902a9b5 o New ioctl(): LV_BMAP which is compatible with LVM so that hopefully LILO
will work. I haven't actually tested that, but this support at least will
   be required.
2001-09-14 13:45:40 +00:00
8df5d06f9a Use dmfs_ function name prefix (in line with other file systems). 2001-09-14 13:27:58 +00:00
e69ea529cc lc->in->f_op->read expects its buffer to be in userspace so surround it in
set_fs() etc calls
2001-09-14 12:27:57 +00:00
15405b1119 o As promised earlier, the device registration is now hashed and the
lists are private to dm-blkdev.c
2001-09-14 11:25:51 +00:00
d2f97ce2da Always truncate error file. 2001-09-14 11:15:54 +00:00
543ca631e9 Don't store things in _devs[-1] - it's not nice. 2001-09-14 10:54:08 +00:00
f184886db1 o Forgot to create slab caches for dm-blkdev.c
o Misc code tidy
2001-09-14 10:40:20 +00:00
8432ab4324 o kmalloc error check
o error file mode
The 1st Jan 1970 date I'm seeing in /dev is a devfs issue I think.
2001-09-14 10:06:22 +00:00
6c05b37ca3 Changes to device handling;
o Only one list of block devices for all tables
 o Locking to ensure that block devices only get opened once
 o Block device handling is now in dm-blkdev.c
 o We open block devices when we create the tables and hold them open until
   the table is destroyed (this prevents the module for the device being
   unloaded after table parsing and before the table is used)
 o We compute the hardsect size when the table is created rather than when
   someone requests it.

Still to fix/change:

 o Probably want to hash the device lists in dm-blkdev.c and also remove refs
   to struct dm_bdev outside this file.
 o Need to ensure that hardsect_size doesn't change when new tables are
   swapped in (maybe this ought to be a per volume parameter and the tables
   will only parse if they match the value for the volume?).

Things are changing fast here, so if you want a stable version of thic code
try checking out yesterdays.
2001-09-14 09:45:35 +00:00
35f4beeb47 o New code for handling block device registration. Not yet used but checked
in for backup purposes.
2001-09-14 08:06:02 +00:00
cbad7caa68 is_identifier characters 2001-09-13 21:50:38 +00:00
b0388a4012 o Two fixes which Alasdair pointed out. 2001-09-13 20:10:14 +00:00
df3fab4d55 o Tidy in dm-fs.c
o Magic number is really magic
 o Check on directory names
2001-09-13 19:41:46 +00:00
da49f88a03 o Forgot to add ref to module. 2001-09-13 19:36:40 +00:00
e28feceb06 Add dm-parse to makefile 2001-09-13 19:09:23 +00:00
50496a164d o Now we handle target modules correctly
o Moved the linear target into its own module (not really because it needs to
   be there, but because its useful to have a simple example so people can see
   what we are doing)

Btw, this needs testing properly.
2001-09-13 18:30:05 +00:00
6f1dce1572 o Remove hard-coded mount point
o Fix macro for compilation
2001-09-13 16:52:50 +00:00
6847776ae7 o Some structures change size with different configs, so always include
<linux/config.h> first.
2001-09-13 14:03:42 +00:00
67bd53bdd8 o Some ioctl() commands. 2001-09-13 14:01:13 +00:00
e735abfdfd Fix includes so that string functions get prototyped 2001-09-13 12:38:31 +00:00
1de93a2d6d Fix includes so that string functions get prototyped.
Fix cast - repeat after me Joe: "I must not cast pointers to ints"!
2001-09-13 12:38:08 +00:00
36f9e7c742 o I'm afraid that wu and wl etc. is just too confusing.... I've changed it
to up_write() and down_write() etc so that you can see what kind of a lock
   it is (otherwise it could be anything.. semaphore, spinlock, spinlock_bh,
   spinlock_irq, br_lock, etc.)
2001-09-13 11:29:38 +00:00
9462763bbb o Use kmem_cache_destroy() to remove slab cache. 2001-09-13 11:07:08 +00:00
4ae0880ea6 Set DEFAULT_ALIGNMENT to 8 for Alpha.
If you think this is wasteful on other arches then stick some ifdefs in.
2001-09-13 09:03:42 +00:00
6ae2b6c835 Add dm-parse 2001-09-12 13:50:26 +00:00
a0f180fd48 o first sattab at custom fs. Very rough ATM.
Mount the dm-fs filesystem on /device-mapper (will fix later).  mkdir
to create a device, inside that directory every file you create is a table
file.  If there are errors <table>.err will appear automagically.  Mv a table
file to ACTIVE to activeate the device.  I'm not happy with mv being the
binding command, symlink would be better.
2001-09-07 11:34:46 +00:00
bf1cf89914 o more tidy ups from Clausen. 2001-09-05 07:48:11 +00:00
297a047fb4 o Added two new functions get_child [Andrew Clausen] and get_node. I think
this makes 'high()' a bit more understandable.
2001-09-04 10:17:28 +00:00
52ffc15ffc o added new constant CHILD_PER_NODE to make things clearer 2001-09-03 08:36:41 +00:00
e478c9c693 o Various tidy ups [Andrew Clausen] 2001-09-02 10:49:20 +00:00
d004f28074 o added global dm_table_lookup_device(path)
o changed linear target to : <device_path> <start>
2001-08-31 18:26:27 +00:00
bc68ed8b1d o added reference counting to the destination devices, make sure that the
destructor for any targets you write call dm_table_remove_device.
2001-08-31 16:36:56 +00:00
04555ae650 o split struct mapped_device into mapped_device and dm_table
o seperated loading of a table from binding a table to the device

These should allow multiple tables to be managed by dm-fs
2001-08-31 15:13:33 +00:00
e8f62085be o tidy ups 2001-08-31 12:49:31 +00:00
f430bffe2a o allocate io_hooks from a slab 2001-08-31 10:25:32 +00:00
1f0520634f o stray return -ENXIO in reuqest [Jens Axboe] 2001-08-31 09:43:35 +00:00
902d4c31fb o rebuilt 00_latest 2001-08-31 09:14:55 +00:00
17364ac09f o split uml part out 2001-08-29 14:23:40 +00:00
0b889f8f81 o various little tidy ups 2001-08-29 13:58:48 +00:00
40e349ff35 o change format of table line to <start> <len> <target> ... 2001-08-28 14:56:47 +00:00
c943b1b1df o Enable building dm modules (called dm-mod)
o split the patches into config and makefile specific.
2001-08-28 14:11:55 +00:00
912bc1d4e1 o more deferred io stuff 2001-08-28 14:05:22 +00:00
cacb1533a3 o added proper suspend/resume support, it now waits for all 'in flight' io's
to complete.

  
  moved comment to dm.h
2001-08-28 13:04:44 +00:00
f0feaca9d7 o ACtual source code patch 2001-08-24 09:50:16 +00:00
b6656f171b o a couple of patches we'll need for deviec-mapper 2001-08-24 09:39:32 +00:00
6206ab3931 o you can now load maps repeatedly without hanging
o tested multiple target map

Driver is now useable
2001-08-23 17:10:05 +00:00
c35fc58b1f o dm_add_target was returning 0 an error when it shouldn't
o reference count was being checked badly
2001-08-23 16:45:43 +00:00
deed8abed7 o map loads ok now
o request function appears to work, but something is segfaulting when i
  mke2fs
2001-08-23 12:35:02 +00:00
7151ad23f0 Tweak permissions - currently root-only. (no support for non-root ownership
in procfs except for PIDs)
2001-08-22 20:10:06 +00:00
0166d938af o chagngesd alloc to return 0 on success 2001-08-22 15:59:56 +00:00
6194aeddb0 o fs_add and fs_remove actually create/remove the device now 2001-08-22 15:33:08 +00:00
903dbf2c30 o added brackets to make t->name = (char *) (t + 1) more explicit 2001-08-22 15:12:31 +00:00
9380f9ff57 Return 0 on success now. 2001-08-22 15:02:55 +00:00
259ed95486 o wu macro was doing a read unlock
o added dm_fs_add/remveove
2001-08-22 15:01:09 +00:00
2ebc92681e o _tok_cpy was broken 2001-08-22 14:30:30 +00:00
195a1ffe13 o fix get_word
o capy name in when registering targets

o change _line_splitter so it expects the process functions to return zero
  on success
2001-08-22 14:13:26 +00:00
a8c2978185 o _get_workd was always returning the end on iput 2001-08-22 13:52:26 +00:00
140f97a457 o Initialisation tweaks.
o Use different major number so it can co-exist with LVM 1.
2001-08-22 13:46:58 +00:00
7f94445a1e o set permissions on /proc/device-mapper/control to -w-w-w 2001-08-22 13:45:28 +00:00
82a89aec65 o call dm_init_fs 2001-08-22 13:41:00 +00:00
7e95110232 o Ok, this seems to be a much better method for caching valid
devices based on /proc/devices
   + The dev_mgr structure now has a 256 element char array that is
     initially all 0s
   + When a match is found, the array element corresponding to the major
     number of the match is set to a non-zero value
   + to check for a match, all one has to do is check that the array
     element at the major number in question is non-zero.
 o I'm wondering if we should do this with bitwise operators instead?  Does
   anyone expect the major numbers to grow larger than 8-bits?
2001-08-21 20:40:37 +00:00
ec4aaaad89 o Quick and dirty *UGLY* hack of a /proc/devices cache using a linked list
o I don't like it, but I'm committing it so I can go back and laugh at
   myself later
 o I have a (hopefully) better idea that i'll try to commit yet today.
2001-08-21 19:51:04 +00:00
1b790fde24 o Quick and dirty hack to get lvm_check_dev code into the dev-manager
o I'm working on caching the /proc/devices entries now, and should have
   that in by the end of today or early tomorrow.
 o There will be much cleanup involved with that...
2001-08-21 18:20:14 +00:00
aaccea731e o quick hack to get the proc entry registering 2001-08-21 15:31:50 +00:00
29e31d7610 o dm-fs compiles, I've forgotten to register the device in /proc though 2001-08-21 15:24:02 +00:00
aa51f4a98f o Added a basic makefile to build liblvm.a again
o Modified source files so that this works
2001-08-21 15:23:45 +00:00
e6ccd12f00 o Brought hash table code over from experimental 2001-08-21 15:22:59 +00:00
b134315df1 o wasn't including dm-fs.o in the build 2001-08-21 14:52:54 +00:00
7f34dffa13 o dm-target compiles 2001-08-21 14:51:41 +00:00
fa239e78c9 o dm-table compiles 2001-08-21 14:47:42 +00:00
707a6c4d6a o Added _basic_ config file support to the device manager 2001-08-21 14:44:18 +00:00
e5da303b43 o make dm.c compile 2001-08-21 14:28:00 +00:00
84ccd66331 o 2.4.9 support
o new uml-lvm patch
2001-08-21 13:45:16 +00:00
ad8cc2baea o Populating with stuff from experimental 2001-08-21 13:22:16 +00:00
7c4cf70309 o Populating with stuff from experimental 2001-08-21 12:56:08 +00:00
c3211e9b4f o dm_activate/dm_close 2001-08-20 16:12:22 +00:00
268d94c983 dec use count on close. corrects a typo.
Really the use counts on these modules should be handled at a higher level,
otherwise there are races I think.
2001-08-20 15:59:22 +00:00
0bcacbba58 o implemeted dm_start_table/dm_add_entry/dm_complete_table as used by
the /proc interface.
2001-08-20 15:22:44 +00:00
8cdc26add9 o changed _dev_lock to a rw_semaphore 2001-08-20 14:06:25 +00:00
e0b2238886 o proc interface is getting there. 2001-08-20 13:45:43 +00:00
369a2e4029 o missed one 2001-08-20 08:05:51 +00:00
c4089e3b51 Just syncing with the office.
o device-mapper.c has split
2001-08-20 08:03:02 +00:00
9e2e9bc5b8 o added a description 2001-08-16 15:14:07 +00:00
a9e44426ed o checked in the new driver, and the uml dir 2001-08-16 08:26:13 +00:00
901 changed files with 23780 additions and 205266 deletions

27
.gitignore vendored
View File

@ -1,27 +0,0 @@
*.5
*.8
*.a
*.d
*.o
*.pc
*.pot
*.so
*.so.*
*.swp
*~
.export.sym
.exported_symbols_generated
.gdb_history
Makefile
make.tmpl
configure.h
version.h
/autom4te.cache/
/config.log
/config.status
/cscope.out
/tmp/

2
BUGS Normal file
View File

@ -0,0 +1,2 @@
Snapshots under 2.4.18 can deadlock due to a bug in the VM system.
2.4.19-pre8 is fine.

View File

@ -1,14 +1,14 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
@ -17,109 +17,97 @@ freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LESSER GENERAL PUBLIC LICENSE
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
@ -268,7 +256,7 @@ distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
@ -295,31 +283,23 @@ of these things:
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
@ -368,7 +348,7 @@ Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
@ -411,7 +391,7 @@ excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
@ -457,7 +437,7 @@ DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
@ -474,18 +454,19 @@ convey the exclusion of warranty; and each file should have at least the
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
@ -500,5 +481,3 @@ necessary. Here is a sample; alter the names:
Ty Coon, President of Vice
That's all there is to it!

34
INSTALL
View File

@ -1,30 +1,44 @@
Installation
============
LVM2 installation
=================
1) Generate custom makefiles.
1) Install device-mapper
Ensure the device-mapper has been installed on the machine.
The device-mapper should be in the kernel (look for 'device-mapper'
messages in the kernel logs) and /usr/include/libdevmapper.h
and libdevmapper.so should be present.
The device-mapper is available from:
ftp://ftp.sistina.com/pub/LVM2/device-mapper/
2) Generate custom makefiles.
Run the 'configure' script from the top directory.
If you wish to use the built-in LVM2 shell and have GNU readline
installed (http://www.gnu.org/directory/readline.html) use:
./configure --enable-readline
If you don't want to include the LVM1 backwards-compatibility code use:
./configure --with-lvm1=none
To separate the LVM1 support into a shared library loaded by lvm.conf use:
./configure --with-lvm1=shared
Use ./configure --help to see other options.
2) Build and install.
3) Build and install LVM2.
Run 'make' from the top directory to build everything you configured.
Run 'make install' to build and install everything you configured.
Run 'make install' from the top directory.
If you only want the device-mapper libraries and tools use
'make device-mapper' or 'make install_device-mapper'.
3) If using LVM2, create a configuration file.
4) Create a configuration file
The tools will work fine without a configuration file being
present, but you ought to review the example file in doc/example.conf.
For example, specifying the devices that LVM2 is to use can
make the tools run more efficiently - and avoid scanning /dev/cdrom!
Please also refer to the WHATS_NEW file and the manual pages for the
individual commands.

View File

@ -1,186 +1,35 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
# Copyright (C) 2001 Sistina Software
#
# This file is part of LVM2.
# This LVM library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
# This LVM library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# You should have received a copy of the GNU Library General Public
# License along with this LVM library; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
VPATH = @srcdir@
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
SUBDIRS = include man lib tools
ifeq ("@UDEV_RULES@", "yes")
SUBDIRS += udev
endif
ifeq ("@INTL@", "yes")
SUBDIRS += po
endif
ifeq ("@APPLIB@", "yes")
SUBDIRS += liblvm
endif
ifeq ("@PYTHON_BINDINGS@", "yes")
SUBDIRS += python
endif
ifeq ($(MAKECMDGOALS),clean)
SUBDIRS += test
endif
# FIXME Should use intermediate Makefiles here!
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = conf include man test scripts \
libdaemon lib tools daemons libdm \
udev po liblvm python \
unit-tests/datastruct unit-tests/mm unit-tests/regex
tools.distclean: test.distclean
SUBDIRS += lib/format1 \
test/mm test/device test/format1 test/regex test/filters
endif
DISTCLEAN_DIRS += lcov_reports*
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
include make.tmpl
libdm: include
libdaemon: include
lib: libdm libdaemon
liblvm: lib
daemons: lib libdaemon tools
tools: lib libdaemon device-mapper
po: tools daemons
scripts: liblvm libdm
lib: include
tools: include lib
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
liblvm.device-mapper: include.device-mapper
daemons.device-mapper: libdm.device-mapper
tools.device-mapper: libdm.device-mapper
scripts.device-mapper: include.device-mapper
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
ifeq ("@INTL@", "yes")
lib.pofile: include.pofile
tools.pofile: lib.pofile
daemons.pofile: lib.pofile
po.pofile: tools.pofile daemons.pofile
pofile: po.pofile
endif
ifeq ("@PYTHON_BINDINGS@", "yes")
python: liblvm
endif
ifneq ("$(CFLOW_CMD)", "")
tools.cflow: libdm.cflow lib.cflow
daemons.cflow: tools.cflow
cflow: include.cflow
endif
ifneq ("@CSCOPE_CMD@", "")
cscope.out:
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
all: cscope.out
endif
DISTCLEAN_TARGETS += cscope.out
check check_system check_cluster check_local check_lvmetad unit: all
$(MAKE) -C test $(@)
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
install_initscripts:
$(MAKE) -C scripts install_initscripts
install_systemd_generators:
$(MAKE) -C scripts install_systemd_generators
$(MAKE) -C man install_systemd_generators
install_systemd_units:
$(MAKE) -C scripts install_systemd_units
ifeq ("@PYTHON_BINDINGS@", "yes")
install_python_bindings:
$(MAKE) -C liblvm/python install_python_bindings
endif
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
LCOV_TRACES = libdm.info lib.info tools.info \
daemons/dmeventd.info daemons/clvmd.info
CLEAN_TARGETS += $(LCOV_TRACES)
ifneq ("$(LCOV)", "")
.PHONY: lcov-reset lcov lcov-dated $(LCOV_TRACES)
ifeq ($(MAKECMDGOALS),lcov-dated)
LCOV_REPORTS_DIR := lcov_reports-$(shell date +%Y%m%d%k%M%S)
lcov-dated: lcov
else
LCOV_REPORTS_DIR := lcov_reports
endif
lcov-reset:
$(LCOV) --zerocounters $(addprefix -d , $(basename $(LCOV_TRACES)))
# maybe use subdirs processing to create tracefiles...
$(LCOV_TRACES):
$(LCOV) -b $(basename $@) -d $(basename $@) \
--ignore-errors source -c -o - | $(SED) \
-e "s/\(dmeventd_lvm.[ch]\)/plugins\/lvm2\/\1/" \
-e "s/dmeventd_\(mirror\|snapshot\|thin\|raid\)\.c/plugins\/\1\/dmeventd_\1\.c/" \
>$@
ifneq ("$(GENHTML)", "")
lcov: $(LCOV_TRACES)
$(RM) -r $(LCOV_REPORTS_DIR)
$(MKDIR_P) $(LCOV_REPORTS_DIR)
for i in $(LCOV_TRACES); do \
test -s $$i && lc="$$lc $$i"; \
done; \
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
-o $(LCOV_REPORTS_DIR) $$lc
endif
endif
ifeq ("$(TESTING)", "yes")
# testing and report generation
RUBY=ruby1.9 -Ireport-generators/lib -Ireport-generators/test
.PHONY: unit-test ruby-test test-programs
# FIXME: put dependencies on libdm and liblvm
# FIXME: Should be handled by Makefiles in subdirs, not here at top level.
test-programs:
cd unit-tests/regex && $(MAKE)
cd unit-tests/datastruct && $(MAKE)
cd unit-tests/mm && $(MAKE)
unit-test: test-programs
$(RUBY) report-generators/unit_test.rb $(shell find . -name TESTS)
$(RUBY) report-generators/title_page.rb
memcheck: test-programs
$(RUBY) report-generators/memcheck.rb $(shell find . -name TESTS)
$(RUBY) report-generators/title_page.rb
ruby-test:
$(RUBY) report-generators/test/ts.rb
endif

40
README
View File

@ -1,33 +1,25 @@
This tree contains the LVM2 and device-mapper tools and libraries.
This directory contains a beta release of LVM2, the new version of
the userland LVM tools designed for the new device-mapper for
the Linux kernel.
For more information about LVM2 read the changelog in the WHATS_NEW file.
The device-mapper needs to be installed before compiling these LVM2 tools.
For more information about LVM2 read the WHATS_NEW file.
Installation instructions are in INSTALL.
This is beta-quality software, released for testing purposes only.
There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from:
ftp://sources.redhat.com/pub/lvm2/
ftp://ftp.sistina.com/pub/LVM2/tools/
ftp://ftp.sistina.com/pub/LVM2/device-mapper/
The source code is stored in git:
http://git.fedorahosted.org/git/lvm2.git
git clone git://git.fedorahosted.org/git/lvm2.git
To access the CVS tree use:
cvs -d :pserver:cvs@tech.sistina.com:/data/cvs login
CVS password: cvs1
cvs -d :pserver:cvs@tech.sistina.com:/data/cvs checkout LVM2
Mailing list for general discussion related to LVM2:
linux-lvm@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
Mailing lists for LVM2 development, patches and commits:
lvm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
Mailing list for device-mapper development, including kernel patches
and multipath-tools:
dm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
The source code repository used until 7th June 2012 is accessible here:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
Mailing list for discussion/bug reports etc.
lvm-devel@sistina.com
Subscribe from http://lists.sistina.com/mailman/listinfo/lvm-devel

View File

@ -1 +1 @@
2.02.112(2)-git (2014-09-01)
1.95.11-cvs (2002-11-18)

View File

@ -1 +0,0 @@
1.02.91-git (2014-09-01)

3720
WHATS_NEW

File diff suppressed because it is too large Load Diff

View File

@ -1,971 +0,0 @@
Version 1.02.91 -
====================================
Fix dm_is_dm_major to not issue error about missing /proc lines for dm module.
Version 1.02.90 - 1st September 2014
====================================
Restore proper buffer size for parsing mountinfo line (1.02.89)
Version 1.02.89 - 26th August 2014
==================================
Improve libdevmapper-event select() error handling.
Add extra check for matching transation_id after message submitting.
Add dm_report_field_string_list_unsorted for str. list report without sorting.
Support --deferred with dmsetup remove to defer removal of open devices.
Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
Add support for selection to match string list subset, recognize { } operator.
Fix string list selection with '[value]' to not match list that's superset.
Fix string list selection to match whole words only, not prefixes.
Version 1.02.88 - 5th August 2014
=================================
Add dm_tree_set_optional_uuid_suffixes to handle upgrades.
Version 1.02.87 - 23rd July 2014
================================
Fix dm_report_field_string_list to handle delimiter with multiple chars.
Add dm_report_field_reserved_value for per-field reserved value definition.
Version 1.02.86 - 23rd June 2014
================================
Make "help" and "?" reporting fields implicit.
Recognize implicit "selected" field if using dm_report_init_with_selection.
Add support for implicit reporting fields which are predefined in libdm.
Add DM_REPORT_FIELD_TYPE_PERCENT: separate number and percent fields.
Add dm_percent_range_t,dm_percent_to_float,dm_make_percent to libdm for reuse.
Add dm_report_reserved_value to libdevmapper for reserved value definition.
Also display field types when listing all fields in selection help.
Recognize "help" keyword in selection string to show brief help for selection.
Always order items reported as string list field lexicographically.
Add dm_report_field_string_list to libdevmapper for direct string list report.
Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
Add dm_str_list to libdevmapper for string list type definition and its reuse.
Add dmsetup -S/--select to define selection criteria for dmsetup reports.
Add dm_report_init_with_selection to intialize report with selection criteria.
Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
Use RemoveOnStop for dm-event.socket systemd unit.
Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.
Warn user about incorrect use of cookie with 'dmsetup remove --force'.
Also recognize 'help'/'?' as reserved sort key name to show help.
Add dm_units_to_factor for size unit parsing.
Increase bitset size for minors for thin dmeventd plugin.
Version 1.02.85 - 10th April 2014
=================================
Check for sprintf error when building internal device path.
Check for sprintf error when creating path for dm control node.
When buffer for dm_get_library_version() is too small, return error code.
Always reinitialize _name_mangling_mode in dm_lib_init().
Add tracking flag about implicitly added devices into dm_tree.
Stop timeout thread immediately when the last worker thread is finished.
Fix dmeventd logging with parallel wait event processing.
Reuse _node_send_messages() for validation of transaction_id in preload.
Transaction_id could be lower by one only when messages are prepared.
Do not call callback when preload fails.
Wrap is_selinux_enabled() to be called just once.
Use correctly signed 64b constant when working with raid volumes.
Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request.
Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol.
Do not use systemd's reload for dmeventd restart, use dmeventd -R instead.
Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them.
Version 1.02.84 - 20th January 2014
===================================
Revert activation of activated nodes if a node preload callback fails.
Avoid busy looping on CPU when dmeventd reads event DM_WAIT_RETRY.
Ensure global mutex is held when working with dmeventd thread.
Drop taking timeout mutex for un/registering dmeventd monitor.
Allow section names in config file data to be quoted strings.
Close fifos before exiting in dmeventd restart() error path.
Move printf format string directly into dm_asprintf args list.
Catch invalid use of string sort values when reporting numerical fields.
Version 1.02.83 - 13th November 2013
====================================
Consistently report on stderr when device is not found for dmsetup info.
Skip race errors when non-udev dmsetup build runs on udev-enabled system.
Skip error message when holders are not present in sysfs.
Use __linux__ instead of linux define to make libdevmapper.h C compliant.
Use mutex to avoid possible race while creating/destroying memory pools.
Require libpthread to build now.
Version 1.02.82 - 4th October 2013
==================================
Define symbolic names for subsystem udev flags in libdevmapper for easier use.
Make subsystem udev rules responsible for importing DM_SUBSYSTEM_UDEV_FLAG*.
Version 1.02.81 - 23rd September 2013
=====================================
Tidy dmeventd fifo initialisation.
Version 1.02.80 - 20th September 2013
=====================================
Detect invalid sector supplied to 'dmsetup message'.
Free any previously-set string if a dm_task_set_* function is called again.
Do not allow passing empty new name for dmsetup rename.
Display any output returned by 'dmsetup message'.
Add dm_task_get_message_response to libdevmapper.
Version 1.02.79 - 13th August 2013
==================================
Create dmeventd timeout threads as "detached" so exit status is freed.
Add DM_ABORT_ON_INTERNAL_ERRORS env var support to abort on internal errors.
Version 1.02.78 - 24th July 2013
================================
Process thin messages once to active thin pool target for dm_tree.
Optimize out setting the same value or read_ahead.
Add DM_ARRAY_SIZE public macro.
Move syslog code out of signal handle in dmeventd.
Add DM_TO_STRING public macro.
Always return success on dmeventd -V command call.
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
Add dm_get_status_snapshot() for parsing snapshot status.
Detecte mounted fs also via reading /proc/self/mountinfo.
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
Report error for nonexisting devices in dmeventd communication.
Prevent double free error after dmeventd call of _fill_device_data().
Update dmevent structure message_data to simplify/fix error path handling.
Validate passed params to dm_get_status_raid/thin/thin_pool().
Fix 'dmsetup splitname -o' to not fail if used without '-c' switch (1.02.68).
Add dm_config_write_{node_out/one_node_out} for enhanced config output.
Add dm_config_value_is_bool to check for boolean value in supported formats.
Fix config node lookup inside empty sections to not return the section itself.
Append discards and read-only fields to exported struct dm_status_thin_pool.
Fix segfault for truncated string token in config file after the first '"'.
Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
Fix resource leak in error path of dmeventd's umount of thin volume.
Automatically deactivate failed preloaded dm tree node.
Add DM_DISABLE_UDEV environment variable to manage dev nodes by libdm only.
Fix dm_task_set_cookie to properly process udev flags if udev_sync disabled.
Version 1.02.77 - 15th October 2012
===================================
Support unmount of thin volumes from pool above thin pool threshold.
Update man page to reflect that dm UUIDs are being mangled as well.
Apply 'dmsetup mangle' for dm UUIDs besides dm names.
Add 'mangled_uuid' and 'unmangled_uuid' fields to dmsetup info -c -o.
Mangle device UUID on dm_task_set_uuid/newuuid call if necessary.
Add dm_task_get_uuid_mangled/unmangled to libdevmapper.
Always reset delay_resume_if_new flag when stacking thin pool over anything.
Don't create value for dm_config_node and require dm_config_create_value call.
Check for existing new_name for dmsetup rename.
Fix memory leak in dmsetup _get_split_name() error path.
Version 1.02.76 - 7th August 2012
=================================
Add dm_vasprintf to libdevmapper.
Allow --noflush with dmsetup status and wait (for thin target).
Add dm_config_write_one_node to libdevmapper.
Support thin pool message release/reserve_metadata_snap in libdevmapper.
Support thin pool discards and external origin features in libdevmapper.
Add configure --enable-udev-rule-exec-detection to detect exec path in rules.
Use sbindir in udev rules by default and remove executable path detection.
Remove hard-coded paths for dmeventd fifos and use default-dm-run-dir.
Add configure --with-lvmetad-pidfile to remove hard-coded value.
Add configure --with-default-pid-dir for common directory with pid files.
Add configure --with-default-dm-run-dir to set run directory for dm tools.
Detect kernel_send() errors in cmirrord.
Add __attribute__ instrumentation to libdevmapper.h.
Print clean_bits instead of sync_bits in pull_state in cmirrord.
Add tests for errors from closedir(), close() in cmirrord.
Add documentation references in systemd units.
Remove veritysetup. Now maintained with cryptsetup.
Version 1.02.75 - 8th June 2012
===============================
Upstream source repo now fedorahosted.org git not sources.redhat.com CVS.
Remove unsupported udev_get_dev_path libudev call used for checking udev dir.
Set delay_resume_if_new on deptree snapshot origin.
Log value chosen in _find_config_bool like other variable types do.
Wait for dmeventd to exit after sending it DM_EVENT_CMD_DIE when restarting.
Append 'Used' to {Blk}DevNames/DevNos dmsetup report headers for clarity.
Add configure --with-veritysetup for independent veritysetup tool.
Properly support supplied dmevent path in dm_event_register_handler().
Remove dmeventd fifos on exit if they are not managed by systemd.
Use SD_ACTIVATION environment variable in systemd units to detect systemd.
Only start a new dmeventd instance on restart if one was already running.
Extend the time waited for input from dmeventd fifo to 5 secs. (1.02.73)
Version 1.02.74 - 6th March 2012
================================
Check for multiply-mangled names in auto mangling mode.
Fix dm_task_get_name_unmangled to not unmangle already unmangled name.
Check whether device names are properly mangled on ioctl return.
Deactivation of failed thin check on thin pool returns success.
Version 1.02.73 - 3rd March 2012
================================
Test _thread_registry list with holding mutex in dmeventd.
Add dm_tree_node_set_callback() for preload and deactivation hooks.
Drop unsupported TRIM message for thin pool.
Improve logging for fifo startup in dmeventd.
Better detection of missing dmeventd fifo connection (1.02.71).
Add a few pointer validations in dmsetup.
Support dm_task_get_driver_version() query without version string.
Log failure of pthread_join when cleaning unused threads in dmeventd.
Fix empty string warning logic in _find_config_str. (1.02.68)
Fix dm_task_set_name to properly resolve path to dm name (1.02.71).
Add dm_strncpy() function as a faster strncpy() replacement.
Version 1.02.72 - 23rd February 2012
====================================
Avoid memory reallocation for dm_asprintf.
Version 1.02.71 - 20th February 2012
====================================
Switch to using built-in blkid in 13-dm-disk.rules.
Add "watch" rule to 13-dm-disk.rules.
Detect failing fifo and skip 20s retry communication period.
Add DM_DEFAULT_NAME_MANGLING_MODE environment variable as an override.
Add dm_lib_init to automatically initialise device-mapper library on load.
Replace any '\' char with '\\' in dm table specification on input.
Add mangle command to dmsetup to provide renaming to correct mangled form.
Add 'mangled_name' and 'unmangled_name' fields to dmsetup info -c -o.
Add --manglename option to dmsetup to select the name mangling mode.
Add dm_task_get_name_mangled/unmangled to libdevmapper.
Mangle device name on dm_task_set_name/newname call if necessary.
Add dm_set/get_name_mangling_mode to set/get name mangling in libdevmapper.
Add configure --with-default-name-mangling for udev-friendly dev name charset.
Test for parsed words in _umount() dmeventd snapshot plugin.
Fix memory leak in fail path of parse_loop_device_name() in dmsetup.
Check for missing reply_uuid in dm_event_get_registered_device().
Check for allocation failure in dmeventd restart().
Add few missing allocation failures tests in dmsetup.
Fix potential risk of writing in front of buffer in _sysfs_get_dm_name().
Version 1.02.70 - 12th February 2012
====================================
Fix dm_event_get_version() check.
Add pointer test for dependency check in _add_dev().
Validate name and uuid params of dm_tree_add_new_dev_with_udev_flags().
Do not crash for dm_report_init() sort_key == NULL and behave like "".
Return error for failing allocation in dm_asprintf().
Add missing test for failing allocation in dm_realloc() code.
Add test for memory allocation failures in regex matcher code.
Simplify dm_task_set_geometry() and use dm_asprintf().
Set all parameters to 0 for dm_get_next_target() for NULL return.
Fix fd resource leak in error path for _udev_notify_sem_create().
Leave space for '\0' for readline() call in _sysfs_get_kernel_name().
Version 1.02.69 - 1st February 2012
===================================
Clean up dmeventd systemd unit ordering and requirements.
Version 1.02.68 - 26th January 2012
===================================
Reset all members of info struct in dm_tree_add_new_dev_with_udev_flags.
Add dmsetup wipe_table to replace table with one that uses error target.
Add 'blkdevname' and 'blkdevs_used' fields to dmsetup info -c -o.
Add 'blkdevname' option to dmsetup ls --tree to see block device names.
Add -o devno/blkdevname/devname to dmsetup deps and ls.
Add dm_device_get_name to get map name or block device name for given devno.
Remove empty devices when clearing left-over inactive tables in deptree.
Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix.
Improve dmsetup man page description of readahead parameter.
Use sysfs to set/get readahead if possible.
Fix lvm2-monitor init script to use normalized output when using vgs.
Add test for max length (DM_MAX_TYPE_NAME) of target type name.
Include a copy of kernel DM documentation in doc/kernel.
Improve man page style for dmsetup and mention more targets.
Fix _get_proc_number to be tolerant of malformed /proc/misc entries.
Fix missing thread list manipulation protection in dmeventd.
Add ExecReload to dm-event.service for systemd to reload dmeventd properly.
Add dm_config_tree_find_str_allow_empty and dm_config_find_str_allow_empty.
Fix compile-time pool memory locking with DEBUG_MEM.
Fix valgrind error reports in free of pool chunks with DEBUG_MEM.
Align size of structure chunk for fast pool allocator to 8 bytes.
Simplify some pointer operations in dm_free_aux() debug code.
Remove unused dbg_malloc.h file from source tree.
Cleanup backtraces for _create_and_load_v4().
Fix alignment warning in bitcount calculation for raid segment.
Allocate dm_tree structure from dm_tree pool.
Update debug logging for _resume_node.
Add functions to support thin provisioning target.
Improve libdm-config error path reporting.
Update dmsetup resume man with --addnodeonresume/create options.
Add dependency for dm man pages to man subdirectory make all target.
Add dm_tree_retry_remove to use retry logic for device removal in a dm_tree.
Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.
Add dm_device_has_holders fn to to check use of the device by another device.
Add dm_sysfs_dir to libdevmapper to retrieve sysfs location set.
Add dm_set_sysfs_dir to libdevmapper to set sysfs location.
Add --retry option for dmsetup remove to retry removal if not successful.
Add dm_task_retry_remove fn to use retry logic for device removal.
Remove unused passed parameters for _mirror_emit_segment_line().
Add dm_config and string character escaping functions to libdevmapper.
Mark unreleased memory pools as internal error.
Version 1.02.67 - 19th August 2011
==================================
Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked.
Version 1.02.66 - 12th August 2011
==================================
Release geometry buffer in dm_task_destroy.
Update udev rules to skip DM flags decoding for removed devices.
Add compile-time pool memory locking options (to debug shared VG structs).
Remove device name prefix from dmsetup line output if -j & -m or -u supplied.
Remove support for the original version 1 dm ioctls.
Add missing check for allocation failure _create_dir_recursive().
Add support for systemd file descriptor handover in dmeventd.
Fix memory leak in dmsetup _message() memory allocation error path.
Use new oom killer adjustment interface (oom_score_adj) when available.
Add systemd unit files for dmeventd.
Fix read-only identical table reload supression.
Version 1.02.65 - 8th July 2011
===============================
Remove dev name prefix from dmsetup line output if exactly one dev requested.
Report internal error if suspending a device using an already-suspended dev.
Report error if a table load requiring target parameters has none supplied.
Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
Add age_in_minutes parameter to dmsetup udevcomplete_all.
Return immediately from dm_lib_exit() if called more than once.
Disable udev fallback by default and add --verifyudev option to dmsetup.
Report internal error if any table is loaded while any dev is known suspended.
Add dm_get_suspended_counter() for number of devs in suspended state by lib.
Fix "all" report field prefix matching to include label fields with pv_all.
Delay resuming new preloaded mirror devices with core logs in deptree code.
Accept new kernel version 3 uname formats in initialisation.
Version 1.02.64 - 29th April 2011
==================================
Require libudev >= 143 when compiling with udev support.
Use word alignment for dm_pool_strdup() and dm_pool_strndup().
Use dm_snprintf() to fix signedness warning in dm_set_dev_dir().
Use unsigned loop counter to fix signedness warning in _other_node_ops().
Fix const cast in dmsetup calls of dm_report_field_string().
Streamline /dev/mapper/control node code for common cases.
Use hard-coded dm control node device number for 2.6.36 kernels and above.
Improve stack debug reporting in dm_task_create().
Fallback to control node creation only if node doesn't exist yet.
Change dm_hash binary functions to take void *key instead of char *.
Fix uninitialised memory use with empty params in _reload_with_suppression_v4.
Lower severity of selabel_lookup and matchpathcon failure to log_debug.
Add test for failed allocation from dm_task_set_uuid() in dmeventd.
Add dm_event_get_version to dmeventd for use with -R.
Avoid dmeventd core dumps when handling request with unknown command ID.
Have dmeventd -R start up even when no existing copy is running.
Accept multiple mapped device names on many dmsetup command lines.
Fix dm_udev_wait calls in dmsetup to occur before readahead display not after.
Include an implicit dm_task_update_nodes() within dm_udev_wait().
Fix _create_and_load_v4 not to lose the --addnodeoncreate setting (1.02.62).
Add inactive table query support for kernel driver >= 4.11.6 (RHEL 5.7).
Log debug open_count in _node_has_closed_parents().
Add a const to dm_report_field_string() data parameter.
Version 1.02.63 - 9th February 2011
===================================
Reinstate DEBUG_MEM as it's part of the API. (1.02.62)
Version 1.02.62 - 4th February 2011
===================================
Add configure --with-device-nodes-on=create for previous behaviour.
Move creation of device nodes from 'create' to 'resume'.
Add --addnodeonresume and --addnodeoncreate options to dmsetup.
Add dm_task_set_add_node to libdevmapper to control dev node creation time.
Add dm_task_secure_data to libdevmapper to wipe ioctl buffers in kernel.
Log debug message when expected uevent is not generated.
Only compile memory debugging code when DEBUG_MEM is set.
Set DM_UDEV_DISABLE_OTHER_RULES_FLAG for suspended DM devices in udev rules.
Begin a new pool object for each row in _output_as_rows() correctly.
Version 1.02.61 - 10th January 2011
===================================
Add DM_COOKIE_AUTO_CREATE to libdevmapper.h.
Export DM_CONTROL_NODE_UMASK and use it while creating /dev/mapper/control.
Version 1.02.60 - 20th December 2010
====================================
Check for unlink failure in remove_lockfile() in dmeventd.
Use dm_free for dm_malloc-ed areas in _clog_ctr/_clog_dtr in cmirrord.
Use char* arithmetic in _process_all() & _targets() in dmsetup.
Change dm_regex_create() API to accept const char * const *patterns.
Add new dm_prepare_selinux_context fn to libdevmapper and use it throughout.
Detect existence of new SELinux selabel interface during configure.
Version 1.02.59 - 6th December 2010
===================================
Add backtraces to _process_mapper_dir and _create_and_load_v4 error paths.
Remove superfluous checks for NULL before calling dm_free.
Version 1.02.58 - 22nd November 2010
====================================
Fix _output_field crash from field_id free with DEBUG_MEM. (1.02.57)
Version 1.02.57 - 8th November 2010
===================================
Fix regex optimiser not to ignore RHS of OR nodes in _find_leftmost_common.
Add dmeventd -R to restart dmeventd without losing monitoring state. (1.02.56)
Fix memory leak of field_id in _output_field function.
Allocate buffer for reporting functions dynamically to support long outputs.
Version 1.02.56 - 25th October 2010
===================================
Return const pointer from dm_basename() in libdevmapper.
Implement dmeventd -R to restart without state loss.
Add dm_zalloc and use it and dm_pool_zalloc throughout.
Add --setuuid to dmsetup rename.
Add dm_task_set_newuuid to set uuid of mapped device post-creation.
Version 1.02.55 - 24th September 2010
=====================================
Fix the way regions are marked complete to avoid slow --nosync cmirror I/O.
Add DM_REPORT_FIELD_TYPE_ID_LEN to libdevmapper.h.
Version 1.02.54 - 18th August 2010
==================================
Fix dm-mod autoloading logic to not assume control node is set correctly.
Add dmeventd/executable to lvm.conf to test alternative dmeventd.
Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
Generate libdevmapper-event exported symbols.
Remove superfluous NULL pointer tests before dm_free from dmeventd.
Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
Fix udev rules to support udev database content generated by older rules.
Reinstate detection of inappropriate uevent with DISK_RO set and suppress it.
Fix regex ttree off-by-one error.
Add --enable-valgrind-pool to configure.
Fix segfault in regex matcher with characters of ordinal value > 127.
Fix 'void*' arithmetic warnings in dbg_malloc.c and libdm-iface.c.
Wait for node creation before displaying debug info in dmsetup.
Fix return status 0 for "dmsetup info -c -o help".
Add check for kernel semaphore support and disable udev_sync if not available.
Version 1.02.53 - 28th July 2010
================================
Revert failed table load preparation after "create, load and resume".
Switch dmeventd to use dm_create_lockfile and drop duplicate code.
Add dm_create_lockfile to libdm to handle pidfiles for all daemons.
Replace lookup with next in struct dfa_state & calculate states on demand.
Improve the regex matcher, reducing the number of charset nodes used.
Add dm_regex_fingerprint to facilitate regex testing.
Skip ffs(0) in _test_word in bitset functions.
Use "nowatch" udev rule for inappropriate devices.
Version 1.02.52 - 6th July 2010
===============================
Fix dmlosetup snprintf %llu compiler warning.
Add parentheses to some libdevmapper.h macro arguments.
Add printf format attributes to dm_{sn,as}printf and fix a caller.
Move dmeventd man page from install_lvm2 to install_device-mapper. (1.02.50)
Version 1.02.51 - 30th June 2010
================================
Generate libdevmapper exported symbols from header file.
Version 1.02.50 - 23rd June 2010
================================
Fix INTERNAL_ERROR typo in ioctl iface unknown task message.
Fix udev rules to handle spurious events properly.
Use C99 [] not [0] in dm_ulog_request struct to avoid abort when fortified.
Allow use of devmapper header file in C++ mode (extern "C" and __typeof__).
Add dmeventd man page.
Version 1.02.49 - 4th June 2010
===============================
Support autoloading of dm-mod module for kernels from 2.6.35.
Document 'clear' in dmsetup man page.
Fix semctl parameter (union) to avoid misaligned parameter on some arches.
Add dm_tree_node_set_presuspend_node() to presuspend child when deactivating.
Initial support for replicator target.
Version 1.02.48 - 17th May 2010
================================
Use -d to control level of messages sent to syslog by dmeventd.
Change -d to -f to run dmeventd in foreground.
Do not print encryption key in message debug output (cryptsetup luksResume).
Fix dmeventd static build library dependencies.
Fix udev flags on remove in create_and_load error path.
Version 1.02.47 - 30th April 2010
=================================
Add support for new IMPORT{db} udev rule.
Add DM_UDEV_PRIMARY_SOURCE_FLAG udev flag to recognize proper DM events.
Also include udev libs in libdevmapper.pc when udev_sync is enabled.
Cache bitset locations to speed up _calc_states.
Add a regex optimisation pass for shared prefixes and suffixes.
Add dm_bit_and and dm_bitset_equal to libdevmapper.
Simplify dm_bitset_create.
Speed up dm_bit_get_next with ffs().
Version 1.02.46 - 14th April 2010
=================================
Change dm_tree_deactivate_children to fail if device is open.
Wipe memory buffers for dm-ioctl parameters before releasing.
Strictly require libudev if udev_sync is used.
Add support for ioctl's DM_UEVENT_GENERATED_FLAG.
Version 1.02.45 - 9th March 2010
================================
Add --showkeys parameter description to dmsetup man page.
Add --help option as synonym for help command.
Version 1.02.44 - 15th February 2010
====================================
Add DM_UDEV_DISABLE_LIBRARY_FALLBACK udev flag to rely on udev only.
Export dm_udev_create_cookie function to create new cookies on demand.
Add --udevcookie, udevcreatecookie and udevreleasecookie to dmsetup.
Set udev state automatically instead of using DM_UDEV_DISABLE_CHECKING.
Version 1.02.43 - 21st January 2010
===================================
Remove bitset, hash and pool headers superceded by libdevmapper.h.
Fix off-by-one error causing bad cluster mirror table construction.
Version 1.02.42 - 14th January 2010
===================================
Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
Introduce a third activation_priority level in dm_tree_activate_children.
Version 1.02.41 - 12th January 2010
===================================
If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
Add --noudevrules option for dmsetup to disable /dev node management by udev.
Fix 'dmsetup info -c -o all' to show all fields.
Return errors if dm_tree_*_children functions fail.
Fix coredump and memory leak for 'dmsetup help -c'.
Disable udev rules for change events with DISK_RO set.
Version 1.02.40 - 19th November 2009
====================================
Fix install_device-mapper Makefile target to not build dmeventd plugins.
Support udev flags even when udev_sync is disabled or not compiled in.
Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
Add dmsetup --inactive support.
Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
Fix hash lookup segfault when keys compared are different lengths.
Version 1.02.39 - 26th October 2009
===================================
Remove strict default permissions for DM devices from 95-dm-notify.rules.
Add dmsetup udevflags command to decode udev flags in given cookie value.
Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
Make libdm ABI consistent when built with/without selinux support.
Version 1.02.38 - 25th September 2009
=====================================
Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
Add several examples to 12-dm-permissions.rules.
Add splitname and --yes to dmsetup man page.
Fix _mirror_emit_segment_line return code.
Fix dmeventd _temporary_log_fn parameters. (2.02.50)
Version 1.02.37 - 15th September 2009
=====================================
Add dmsetup manpage entries for udevcomplete_all and udevcookies.
Check udev is running when processing cookies and retain state internally.
Add y|--yes option to dmsetup for default 'yes' answer to prompts.
Fix tools Makefile to process dmsetup sources separately.
Restore umask when device node creation fails.
Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
Add dm-log-userspace.h to tree for cmirrord builds.
Version 1.02.36 - 6th August 2009
=================================
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
Add libdevmapper functions to support synchronisation with udev.
Version 1.02.35 - 28th July 2009
================================
Add LOG_LINE_WITH_ERRNO macro.
Use log_error macro consistently throughout in place of log_err.
Version 1.02.34 - 15th July 2009
================================
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
Fix whitespace in linear target line to fix identical table line detection.
Add device number to more log messages during activation.
Version 1.02.33 - 30th June 2009
================================
Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
Do not fork daemon when dmeventd cannot be found.
Add crypt target handling to libdevmapper tree nodes.
Add splitname command to dmsetup.
Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
Make mempool optional in dm_split_lvm_name().
Version 1.02.32 - 21st May 2009
===============================
Only generate libdevmapper.a when configured to link statically.
Export dm_tree_node_size_changed() from libdevmapper.
Propagate the table size_changed property up the dm device tree.
Detect failure to free memory pools when releasing the library.
Fix segfault when getopt processes dmsetup -U, -G and -M options.
Version 1.02.31 - 3rd March 2009
================================
If kernel supports only one dm major number, use in place of any supplied.
Version 1.02.30 - 26th January 2009
====================================
Add "all" field to reports expanding to all fields of report type.
Enforce device name length and character limitations in libdm.
Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
Version 1.02.29 - 10th November 2008
====================================
Merge device-mapper into the LVM2 tree.
Split out dm-logging.h from log.h.
Use lvm-types.h.
Add usrsbindir to configure.
Version 1.02.28 - 18th September 2008
=====================================
Only resume devices in dm_tree_preload_children if size changes.
Extend deptree buffers so the largest possible device numbers fit.
Generate versioned libdevmapper-event.so.
Underline longer report help text headings.
Version 1.02.27 - 25th June 2008
================================
Align struct memblock in dbg_malloc for sparc.
Add --unquoted and --rows to dmsetup.
Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
Fix inverted no_flush debug message.
Remove --enable-jobs from configure. (Set at runtime instead.)
Bring configure.in and list.h into line with the lvm2 versions.
Version 1.02.26 - 6th June 2008
===============================
Initialise params buffer to empty string in _emit_segment.
Skip add_dev_node when ioctls disabled.
Make dm_hash_iter safe against deletion.
Accept a NULL pointer to dm_free silently.
Add tables_loaded, readonly and suspended columns to reports.
Add --nameprefixes to dmsetup.
Add field name prefix option to reporting functions.
Calculate string size within dm_pool_grow_object.
Version 1.02.25 - 10th April 2008
=================================
Remove redundant if-before-free tests.
Use log_warn for reporting field help text instead of log_print.
Change cluster mirror log type name (s/clustered_/clustered-/)
Version 1.02.24 - 20th December 2007
====================================
Fix deptree to pass new name to _resume_node after a rename.
Suppress other node operations if node is deleted.
Add node operation stack debug messages.
Report error when empty device name passed to readahead functions.
Fix minimum readahead debug message.
Version 1.02.23 - 5th December 2007
===================================
Update dm-ioctl.h after removal of compat code.
Add readahead support to libdevmapper and dmsetup.
Fix double free in a libdevmapper-event error path.
Fix configure --with-dmeventd-path substitution.
Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
Avoid static link failure with some SELinux libraries that require libpthread.
Remove obsolete dmfs code from tree and update INSTALL.
Version 1.02.22 - 21st August 2007
==================================
Fix inconsistent licence notices: executables are GPLv2; libraries LGPLv2.1.
Update to use autoconf 2.61, while still supporting 2.57.
Avoid repeated dm_task free on some dm_event_get_registered_device errors.
Introduce log_sys_* macros from LVM2.
Export dm_fclose and dm_create_dir; remove libdm-file.h.
Don't log EROFS mkdir failures in _create_dir_recursive (for LVM2).
Add fclose wrapper dm_fclose that catches write failures (using ferror).
Version 1.02.21 - 13th July 2007
================================
Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
Fix dmsetup -o devno string termination. (1.02.20)
Version 1.02.20 - 15th June 2007
================================
Fix default dmsetup report buffering and add --unbuffered.
Add tree-based and dependency fields to dmsetup reports.
Version 1.02.19 - 27th April 2007
=================================
Standardise protective include file #defines.
Add regex functions to library.
Avoid trailing separator in reports when there are hidden sort fields.
Fix segfault in 'dmsetup status' without --showkeys against crypt target.
Deal with some more compiler warnings.
Introduce _add_field() and _is_same_field() to libdm-report.c.
Fix some libdevmapper-event and dmeventd memory leaks.
Remove unnecessary memset() return value checks.
Fix a few leaks in reporting error paths. [1.02.15+]
Version 1.02.18 - 13th February 2007
====================================
Improve dmeventd messaging protocol: drain pipe and tag messages.
Version 1.02.17 - 29th January 2007
===================================
Add recent reporting options to dmsetup man page.
Revise some report fields names.
Add dmsetup 'help' command and update usage text.
Use fixed-size fields in report interface and reorder.
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.
Migrate dmsetup column-based output over to new libdevmapper report framework.
Add descriptions to reporting field definitions.
Add a dso-private variable to dmeventd dso interface.
Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
Add DM_LIB_VERSION definition to configure.h.
Suppress 'Unrecognised field' error if report field is 'help'.
Add --separator and --sort to dmsetup (unused).
Make alignment flag optional when specifying report fields.
Version 1.02.15 - 17th January 2007
===================================
Add basic reporting functions to libdevmapper.
Fix a malloc error path in dmsetup message.
More libdevmapper-event interface changes and fixes.
Rename dm_saprintf() to dm_asprintf().
Report error if NULL pointer is supplied to dm_strdup_aux().
Reinstate dm_event_get_registered_device.
Version 1.02.14 - 11th January 2007
===================================
Add dm_saprintf().
Use CFLAGS when linking so mixed sparc builds can supply -m64.
Add dm_tree_use_no_flush_suspend().
Lots of dmevent changes including revised interface.
Export dm_basename().
Cope with a trailing space when comparing tables prior to possible reload.
Fix dmeventd to cope if monitored device disappears.
Version 1.02.13 - 28 Nov 2006
=============================
Update dmsetup man page (setgeometry & message).
Fix dmsetup free after getline with debug.
Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
Version 1.02.12 - 13 Oct 2006
=============================
Avoid deptree attempting to suspend a device that's already suspended.
Version 1.02.11 - 12 Oct 2006
==============================
Add suspend noflush support.
Add basic dmsetup loop support.
Switch dmsetup to use dm_malloc and dm_free.
Version 1.02.10 - 19 Sep 2006
=============================
Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
Reorder mm bounds_check code to reduce window for a dmeventd race.
Version 1.02.09 - 15 Aug 2006
=============================
Add --table argument to dmsetup for a one-line table.
Abort if errors are found during cmdline option processing.
Add lockfs indicator to debug output.
Version 1.02.08 - 17 July 2006
==============================
Append full patch to check in emails.
Avoid duplicate dmeventd subdir with 'make distclean'.
Update dmsetup man page.
Add --force to dmsetup remove* to load error target.
dmsetup remove_all also performs mknodes.
Don't suppress identical table reloads if permission changes.
Fix corelog segment line.
Suppress some compiler warnings.
Version 1.02.07 - 11 May 2006
=============================
Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
Avoid a dmeventd compiler warning.
Version 1.02.06 - 10 May 2006
=============================
Move DEFS into configure.h.
Fix leaks in error paths found by coverity.
Remove dmsetup line buffer limitation.
Version 1.02.05 - 19 Apr 2006
=============================
Separate install_include target in makefiles.
Separate out DEFS from CFLAGS.
Support pkg-config.
Check for libsepol.
Version 1.02.04 - 14 Apr 2006
=============================
Bring dmsetup man page up-to-date.
Use name-based device refs if kernel doesn't support device number refs.
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
If _create_and_load_v4 fails part way through, revert the creation.
dmeventd thread/fifo fixes.
Add file & line to dm_strdup_aux().
Add setgeometry.
Version 1.02.03 - 7 Feb 2006
============================
Add exported functions to set uid, gid and mode.
Rename _log to dm_log and export.
Add dm_tree_skip_lockfs.
Fix dm_strdup debug definition.
Fix hash function to avoid using a negative array offset.
Don't inline _find in hash.c and tidy signed/unsigned etc.
Fix libdevmapper.h #endif.
Fix dmsetup version driver version.
Add sync, nosync and block_on_error mirror log parameters.
Add hweight32.
Fix dmeventd build.
Version 1.02.02 - 2 Dec 2005
============================
dmeventd added.
Export dm_task_update_nodes.
Use names instead of numbers in messages when ioctls fail.
Version 1.02.01 - 23 Nov 2005
=============================
Resume snapshot-origins last.
Drop leading zeros from dm_format_dev.
Suppress attempt to reload identical table.
Additional LVM- prefix matching for transitional period.
Version 1.02.00 - 10 Nov 2005
=============================
Added activation functions to library.
Added return macros.
Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
Export dm_set_selinux_context().
Add dm_driver_version().
Added dependency tree functions to library.
Added hash, bitset, pool, dbg_malloc to library.
Added ls --tree to dmsetup.
Added dmsetup --nolockfs support for suspend/reload.
Version 1.01.05 - 26 Sep 2005
=============================
Resync list.h with LVM2.
Remember increased buffer size and use for subsequent calls.
On 'buffer full' condition, double buffer size and repeat ioctl.
Fix termination of getopt_long() option array.
Report 'buffer full' condition with v4 ioctl as well as with v1.
Version 1.01.04 - 2 Aug 2005
============================
Fix dmsetup ls -j and status --target with empty table.
Version 1.01.03 - 13 Jun 2005
=============================
Use matchpathcon mode parameter.
Fix configure script to re-enable selinux.
Version 1.01.02 - 17 May 2005
=============================
Call dm_lib_exit() and dm_lib_release() automatically now.
Add --target <target_type> filter to dmsetup table/status/ls.
Add --exec <command> to dmsetup ls.
Fix dmsetup getopt_long usage.
Version 1.01.01 - 29 Mar 2005
=============================
Update dmsetup man page.
Drop-in devmap_name replacement.
Add option to compile without ioctl for testing.
Fix DM_LIB_VERSION sed.
Version 1.01.00 - 17 Jan 2005
=============================
Add dm_task_no_open_count() to skip getting open_count.
Version 1.00.21 - 7 Jan 2005
============================
Fix /proc/devices parsing.
Version 1.00.20 - 6 Jan 2005
============================
Attempt to fix /dev/mapper/control transparently if it's wrong.
Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
Add --noheadings columns option for colon-separated dmsetup output.
Support device referencing by uuid or major/minor.
Warn if kernel data didn't fit in buffer.
Fix a printf.
Version 1.00.19 - 3 July 2004
=============================
More autoconf fixes.
Fix a dmsetup newline.
Fix device number handling for 2.6 kernels.
Version 1.00.18 - 20 Jun 2004
=============================
Fix a uuid free in libdm-iface.
Fix a targets string size calc in driver.
Add -c to dmsetup for column-based output.
Add target message-passing ioctl.
Version 1.00.17 - 17 Apr 2004
=============================
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
Fix library selinux linking.
Version 1.00.16 - 16 Apr 2004
=============================
Ignore error setting selinux file context if fs doesn't support it.
Version 1.00.15 - 7 Apr 2004
============================
Fix status overflow check in kernel patches.
Version 1.00.14 - 6 Apr 2004
============================
Fix static selinux build.
Version 1.00.13 - 6 Apr 2004
============================
Add some basic selinux support.
Version 1.00.12 - 6 Apr 2004
============================
Fix dmsetup.static install.
Version 1.00.11 - 5 Apr 2004
============================
configure --enable-static_link does static build in addition to dynamic.
Moved Makefile library targets definition into template.
Version 1.00.10 - 2 Apr 2004
============================
Fix DESTDIR handling.
Static build installs to dmsetup.static.
Basic support for internationalisation.
Minor Makefile tidy-ups/fixes.
Version 1.00.09 - 31 Mar 2004
=============================
Update copyright notices to Red Hat.
Move full mknodes functionality from dmsetup into libdevmapper.
Avoid sscanf %as for uClibc compatibility.
Cope if DM_LIST_VERSIONS is not defined.
Add DM_LIST_VERSIONS functionality to kernel patches.
Generate new kernel patches for 2.4.26-rc1.
Version 1.00.08 - 27 Feb 2004
=============================
Added 'dmsetup targets'.
Added event_nr support to 'dmsetup wait'.
Updated dmsetup man page.
Allow logging function to be reset to use internal one.
Bring log macros in line with LVM2 ones.
Added 'make install_static_lib' which installs libdevmapper.a.
Made configure/makefiles closer to LVM2 versions.
Fixed DESTDIR for make install/install_static_lib.
Updated README/INSTALL to reflect move to sources.redhat.com.
Updated autoconf files to 2003-06-17.

View File

@ -1,59 +0,0 @@
dnl AC_GCC_VERSION
dnl check for compiler version
dnl sets COMPILER_VERSION and GCC_VERSION
AC_DEFUN([AC_CC_VERSION],
[
AC_MSG_CHECKING([C compiler version])
COMPILER_VERSION=`$CC -v 2>&1 | grep version`
case "$COMPILER_VERSION" in
*gcc*)
dnl Ok, how to turn $3 into the real $3
GCC_VERSION=`echo $COMPILER_VERSION | \
sed -e 's/[[^ ]]*\ [[^ ]]*\ \([[^ ]]*\)\ .*/\1/'` ;;
*) GCC_VERSION=unknown ;;
esac
AC_MSG_RESULT($GCC_VERSION)
])
dnl AC_TRY_CCFLAG([CCFLAG], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS])
dnl check if $CC supports a given flag
AC_DEFUN([AC_TRY_CCFLAG],
[
AC_REQUIRE([AC_PROG_CC])
ac_save_CFLAGS=$CFLAGS
CFLAGS=$1
AC_CACHE_CHECK([whether $CC accepts $1 flag], [ac_cv_flag_$2],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
[AS_VAR_SET([ac_cv_flag_$2], [yes])],
[AS_VAR_SET([ac_cv_flag_$2], [no])])])
CFLAGS=$ac_save_CFLAGS
$2=AS_VAR_GET([ac_cv_flag_$2])
if test "$2" = yes; then
ifelse([$3], [], [:], [$3])
else
ifelse([$4], [], [:], [$4])
fi
])
dnl AC_TRY_LDFLAGS([LDFLAGS], [VAR], [ACTION-IF-WORKS], [ACTION-IF-FAILS])
dnl check if $CC supports given ld flags
AC_DEFUN([AC_TRY_LDFLAGS],
[
AC_REQUIRE([AC_PROG_CC])
ac_save_LDFLAGS=$LDFLAGS
LDFLAGS=$1
AC_CACHE_CHECK([whether $CC accepts $1 ld flags], [ac_cv_flag_$2],
[AC_LINK_IFELSE([AC_LANG_PROGRAM()],
[AS_VAR_SET([ac_cv_flag_$2], [yes])],
[AS_VAR_SET([ac_cv_flag_$2], [no])])])
LDFLAGS=$ac_save_LDFLAGS
$2=AS_VAR_GET([ac_cv_flag_$2])
if test "$2" = yes; then
ifelse([$3], [], [:], [$3])
else
ifelse([$4], [], [:], [$4])
fi
])

230
aclocal.m4 vendored
View File

@ -1,230 +0,0 @@
# generated automatically by aclocal 1.13.4 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 1 (pkg-config-0.24)
#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
# ----------------------------------
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
fi
if test -n "$PKG_CONFIG"; then
_pkg_min_version=m4_default([$1], [0.9.0])
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
fi[]dnl
])# PKG_PROG_PKG_CONFIG
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# Check to see whether a particular set of modules exists. Similar
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
#
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
# only at the first occurence in configure.ac, so if the first place
# it's called might be skipped (such as if it is within an "if", you
# have to call PKG_CHECK_EXISTS manually
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
m4_default([$2], [:])
m4_ifvaln([$3], [else
$3])dnl
fi])
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
elif test -n "$PKG_CONFIG"; then
PKG_CHECK_EXISTS([$3],
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes ],
[pkg_failed=yes])
else
pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
# _PKG_SHORT_ERRORS_SUPPORTED
# -----------------------------
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi[]dnl
])# _PKG_SHORT_ERRORS_SUPPORTED
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
# [ACTION-IF-NOT-FOUND])
#
#
# Note that if there is a possibility the first call to
# PKG_CHECK_MODULES might not happen, you should be sure to include an
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
#
#
# --------------------------------------------------------------
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $1])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
_PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
$3
fi[]dnl
])# PKG_CHECK_MODULES
# PKG_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable pkgconfigdir as the location where a module
# should install pkg-config .pc files. By default the directory is
# $libdir/pkgconfig, but the default can be changed by passing
# DIRECTORY. The user can override through the --with-pkgconfigdir
# parameter.
AC_DEFUN([PKG_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
m4_pushdef([pkg_description],
[pkg-config installation directory @<:@]pkg_default[@:>@])
AC_ARG_WITH([pkgconfigdir],
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
[with_pkgconfigdir=]pkg_default)
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_INSTALLDIR
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
# -------------------------
# Substitutes the variable noarch_pkgconfigdir as the location where a
# module should install arch-independent pkg-config .pc files. By
# default the directory is $datadir/pkgconfig, but the default can be
# changed by passing DIRECTORY. The user can override through the
# --with-noarch-pkgconfigdir parameter.
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
m4_pushdef([pkg_description],
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
AC_ARG_WITH([noarch-pkgconfigdir],
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
[with_noarch_pkgconfigdir=]pkg_default)
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_NOARCH_INSTALLDIR
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
m4_include([acinclude.m4])

1652
autoconf/config.guess vendored

File diff suppressed because it is too large Load Diff

911
autoconf/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +1,36 @@
#!/bin/sh
#
# install - install a program, script, or datafile
scriptversion=2006-10-14.15
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright (C) 1994 X Consortium
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
@ -67,441 +41,211 @@ stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
posix_glob=
posix_mkdir=
# Desired mode of installed file.
mode=0755
chmodcmd=$chmodprog
chowncmd=
chgrpcmd=
stripcmd=
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
src=""
dst=""
dir_arg=""
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
-d) dir_arg=true
shift
continue;;
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
while test $# -ne 0; do
case $1 in
-c) shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-d) dir_arg=true
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
--help) echo "$usage"; exit $?;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
-m) mode=$2
shift
shift
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
-T) no_target_directory=true
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
done
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
trap '(exit $?); exit' 1 2 13 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src ;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dstarg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
*) if [ x"$src" = x ]
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
src=$1
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
trap '' 0;;
esac;;
shift
continue;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix=/ ;;
-*) prefix=./ ;;
*) prefix= ;;
esac
case $posix_glob in
'')
if (set -f) 2>/dev/null; then
posix_glob=true
else
posix_glob=false
fi ;;
esac
oIFS=$IFS
IFS=/
$posix_glob && set -f
set fnord $dstdir
shift
$posix_glob && set +f
IFS=$oIFS
prefixes=
for d
do
test -z "$d" && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dst"; then
$doit $rmcmd -f "$dst" 2>/dev/null \
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|| {
echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
} || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

View File

@ -1,40 +0,0 @@
#
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CONFSRC=example.conf
CONFDEST=lvm.conf
PROFILE_TEMPLATES=command_profile_template.profile metadata_profile_template.profile
PROFILES=$(PROFILE_TEMPLATES) $(srcdir)/thin-generic.profile $(srcdir)/thin-performance.profile
include $(top_builddir)/make.tmpl
install_conf: $(CONFSRC)
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \
fi
install_profiles: $(PROFILES)
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR)
$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/
install_lvm2: install_conf install_profiles
install: install_lvm2
DISTCLEAN_TARGETS += $(CONFSRC) $(PROFILE_TEMPLATES)

View File

@ -1,48 +0,0 @@
# This is a command profile template for the LVM2 system.
#
# It contains all configuration settings that are customizable by command
# profiles. To create a new command profile, select the settings you want
# to customize and add them in a new file named <profile_name>.profile.
# Then install the new profile in a directory as defined by config/profile_dir
# setting found in @DEFAULT_SYS_DIR@/lvm.conf file.
#
# Command profiles can be referenced by using the --commandprofile option then.
#
# Refer to 'man lvm.conf' for further information about profiles and
# general configuration file layout.
#
global {
units="h"
si_unit_consistency=1
suffix=1
lvdisplay_shows_full_device_path=0
}
report {
aligned=1
buffered=1
headings=1
separator=" "
list_item_separator=","
prefixes=0
quoted=1
colums_as_rows=0
binary_values_as_numeric=0
devtypes_sort="devtype_name"
devtypes_cols="devtype_name,devtype_max_partitions,devtype_description"
devtypes_cols_verbose="devtype_name,devtype_max_partitions,devtype_description"
lvs_sort="vg_name,lv_name"
lvs_cols="lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,data_percent,metadata_percent,move_pv,mirror_log,copy_percent,convert_lv"
lvs_cols_verbose="lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,pool_lv,origin,data_percent,metadata_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid,lv_profile"
vgs_sort="vg_name"
vgs_cols="vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
vgs_cols_verbose="vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid,vg_profile"
pvs_sort="pv_name"
pvs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
pvs_cols_verbose="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
segs_sort="vg_name,lv_name,seg_start"
segs_cols="lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
segs_cols_verbose="lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
pvsegs_sort="pv_name,pvseg_start"
pvsegs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
pvsegs_cols_verbose="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
# This is a metadata profile template for the LVM2 system.
#
# It contains all configuration settings that are customizable by metadata
# profiles. To create a new metadata profile, select the settings you want
# to customize and add them in a new file named <profile_name>.profile.
# Then install the new profile in a directory as defined by config/profile_dir
# setting found in @DEFAULT_SYS_DIR@/lvm.conf file.
#
# Metadata profiles can be referenced by using the --metadataprofile LVM2
# command line option.
#
# Refer to 'man lvm.conf' for further information about profiles and
# general configuration file layout.
#
allocation {
thin_pool_zero=1
thin_pool_discards="passdown"
thin_pool_chunk_size_policy="generic"
# thin_pool_chunk_size=64
}
activation {
thin_pool_autoextend_threshold=100
thin_pool_autoextend_percent=20
}

View File

@ -1,4 +0,0 @@
allocation {
thin_pool_chunk_size_policy = "generic"
thin_pool_zero = 1
}

View File

@ -1,4 +0,0 @@
allocation {
thin_pool_chunk_size_policy = "performance"
thin_pool_zero = 0
}

14890
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
#
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
.PHONY: dmeventd clvmd cmirrord lvmetad
ifneq ("@CLVMD@", "none")
SUBDIRS += clvmd
endif
ifeq ("@BUILD_CMIRRORD@", "yes")
SUBDIRS += cmirrord
endif
ifeq ("@BUILD_DMEVENTD@", "yes")
SUBDIRS += dmeventd
ifneq ("$(CFLOW_CMD)", "")
daemons.cflow: dmeventd.cflow
endif
endif
ifeq ("@BUILD_LVMETAD@", "yes")
SUBDIRS += lvmetad
endif
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = clvmd cmirrord dmeventd lvmetad
endif
include $(top_builddir)/make.tmpl
ifeq ("@BUILD_DMEVENTD@", "yes")
device-mapper: dmeventd.device-mapper
endif

View File

@ -1,107 +0,0 @@
#
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CMAN_LIBS = @CMAN_LIBS@
CMAN_CFLAGS = @CMAN_CFLAGS@
CMAP_LIBS = @CMAP_LIBS@
CMAP_CFLAGS = @CMAP_CFLAGS@
CONFDB_LIBS = @CONFDB_LIBS@
CONFDB_CFLAGS = @CONFDB_CFLAGS@
CPG_LIBS = @CPG_LIBS@
CPG_CFLAGS = @CPG_CFLAGS@
DLM_LIBS = @DLM_LIBS@
DLM_CFLAGS = @DLM_CFLAGS@
QUORUM_LIBS = @QUORUM_LIBS@
QUORUM_CFLAGS = @QUORUM_CFLAGS@
SALCK_LIBS = @SALCK_LIBS@
SALCK_CFLAGS = @SALCK_CFLAGS@
SOURCES = \
clvmd-command.c \
clvmd.c \
lvm-functions.c \
refresh_clvmd.c
ifeq ("@DEBUG@", "yes")
DEFS += -DDEBUG
endif
ifneq (,$(findstring cman,, "@CLVMD@,"))
SOURCES += clvmd-cman.c
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
DEFS += -DUSE_CMAN
endif
ifneq (,$(findstring openais,, "@CLVMD@,"))
SOURCES += clvmd-openais.c
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
DEFS += -DUSE_OPENAIS
endif
ifneq (,$(findstring corosync,, "@CLVMD@,"))
SOURCES += clvmd-corosync.c
LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
DEFS += -DUSE_COROSYNC
endif
ifneq (,$(findstring singlenode,, &quot;@CLVMD@,&quot;))
SOURCES += clvmd-singlenode.c
DEFS += -DUSE_SINGLENODE
endif
ifeq ($(MAKECMDGOALS),distclean)
SOURCES += clvmd-cman.c
SOURCES += clvmd-openais.c
SOURCES += clvmd-corosync.c
SOURCES += clvmd-singlenode.c
endif
TARGETS = \
clvmd
LVMLIBS = $(LVMINTERNAL_LIBS)
ifeq ("@DMEVENTD@", "yes")
LVMLIBS += -ldevmapper-event
endif
include $(top_builddir)/make.tmpl
LVMLIBS += -ldevmapper
LIBS += $(PTHREAD_LIBS)
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
INSTALL_TARGETS = \
install_clvmd
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
$(LVMLIBS) $(LMLIBS) $(LIBS)
.PHONY: install_clvmd
install_clvmd: $(TARGETS)
$(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd
install: $(INSTALL_TARGETS)
install_cluster: $(INSTALL_TARGETS)

View File

@ -1,83 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Definitions for CLVMD server and clients */
/*
* The protocol spoken over the cluster and across the local socket.
*/
#ifndef _CLVM_H
#define _CLVM_H
#include "configure.h"
#include <inttypes.h>
struct clvm_header {
uint8_t cmd; /* See below */
uint8_t flags; /* See below */
uint16_t xid; /* Transaction ID */
uint32_t clientid; /* Only used in Daemon->Daemon comms */
int32_t status; /* For replies, whether request succeeded */
uint32_t arglen; /* Length of argument below.
If >1500 then it will be passed
around the cluster in the system LV */
char node[1]; /* Actually a NUL-terminated string, node name.
If this is empty then the command is
forwarded to all cluster nodes unless
FLAG_LOCAL or FLAG_REMOTE is also set. */
char args[1]; /* Arguments for the command follow the
node name, This member is only
valid if the node name is empty */
} __attribute__ ((packed));
/* Flags */
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
/* Name of the local socket to communicate between lvm and clvmd */
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
/* Internal commands & replies */
#define CLVMD_CMD_REPLY 1
#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
an incompatible version */
#define CLVMD_CMD_TEST 4 /* Just for mucking about */
#define CLVMD_CMD_LOCK 30
#define CLVMD_CMD_UNLOCK 31
/* Lock/Unlock commands */
#define CLVMD_CMD_LOCK_LV 50
#define CLVMD_CMD_LOCK_VG 51
#define CLVMD_CMD_LOCK_QUERY 52
/* Misc functions */
#define CLVMD_CMD_REFRESH 40
#define CLVMD_CMD_GET_CLUSTERNAME 41
#define CLVMD_CMD_SET_DEBUG 42
#define CLVMD_CMD_VG_BACKUP 43
#define CLVMD_CMD_RESTART 44
#define CLVMD_CMD_SYNC_NAMES 45
/* Used internally by some callers, but not part of the protocol.*/
#define NODE_ALL "*"
#define NODE_LOCAL "."
#define NODE_REMOTE "^"
#endif

View File

@ -1,505 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* CMAN communication layer for clvmd.
*/
#include "clvmd-common.h"
#include <pthread.h>
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "lvm-functions.h"
#include <libdlm.h>
#include <syslog.h>
#define LOCKSPACE_NAME "clvmd"
struct clvmd_node
{
struct cman_node *node;
int clvmd_up;
};
static int num_nodes;
static struct cman_node *nodes = NULL;
static struct cman_node this_node;
static int count_nodes; /* size of allocated nodes array */
static struct dm_hash_table *node_updown_hash;
static dlm_lshandle_t *lockspace;
static cman_handle_t c_handle;
static void count_clvmds_running(void);
static void get_members(void);
static int nodeid_from_csid(const char *csid);
static int name_from_nodeid(int nodeid, char *name);
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
static void data_callback(cman_handle_t handle, void *private,
char *buf, int len, uint8_t port, int nodeid);
struct lock_wait {
pthread_cond_t cond;
pthread_mutex_t mutex;
struct dlm_lksb lksb;
};
static int _init_cluster(void)
{
node_updown_hash = dm_hash_create(100);
/* Open the cluster communication socket */
c_handle = cman_init(NULL);
if (!c_handle) {
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
return -1;
}
DEBUGLOG("Connected to CMAN\n");
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
syslog(LOG_ERR, "Can't bind cluster socket: %m");
return -1;
}
if (cman_start_notification(c_handle, event_callback)) {
syslog(LOG_ERR, "Can't start cluster event listening");
return -1;
}
/* Get the cluster members list */
get_members();
count_clvmds_running();
DEBUGLOG("CMAN initialisation complete\n");
/* Create a lockspace for LV & VG locks to live in */
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
if (!lockspace) {
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
if (!lockspace) {
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
return -1;
}
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
} else
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
dlm_ls_pthread_init(lockspace);
DEBUGLOG("DLM initialisation complete\n");
return 0;
}
static void _cluster_init_completed(void)
{
clvmd_cluster_init_completed();
}
static int _get_main_cluster_fd(void)
{
return cman_get_fd(c_handle);
}
static int _get_num_nodes(void)
{
int i;
int nnodes = 0;
/* return number of ACTIVE nodes */
for (i=0; i<num_nodes; i++) {
if (nodes[i].cn_member && nodes[i].cn_nodeid)
nnodes++;
}
return nnodes;
}
/* send_message with the fd check removed */
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
int nodeid = 0;
if (csid)
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
{
log_error("%s", errtext);
}
return msglen;
}
static void _get_our_csid(char *csid)
{
if (this_node.cn_nodeid == 0) {
cman_get_node(c_handle, 0, &this_node);
}
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
}
/* Call a callback routine for each node is that known (down means not running a clvmd) */
static int _cluster_do_node_callback(struct local_client *client,
void (*callback) (struct local_client *,
const char *,
int))
{
int i;
int somedown = 0;
for (i = 0; i < _get_num_nodes(); i++) {
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
callback(client, (char *)&nodes[i].cn_nodeid, up);
if (!up)
somedown = -1;
}
}
return somedown;
}
/* Process OOB messages from the cluster socket */
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
{
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
switch (reason) {
case CMAN_REASON_PORTCLOSED:
name_from_nodeid(arg, namebuf);
log_notice("clvmd on node %s has died\n", namebuf);
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
break;
case CMAN_REASON_STATECHANGE:
DEBUGLOG("Got state change message, re-reading members list\n");
get_members();
break;
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
case CMAN_REASON_PORTOPENED:
/* Ignore this, wait for startup message from clvmd itself */
break;
case CMAN_REASON_TRY_SHUTDOWN:
DEBUGLOG("Got try shutdown, sending OK\n");
cman_replyto_shutdown(c_handle, 1);
break;
#endif
default:
/* ERROR */
DEBUGLOG("Got unknown event callback message: %d\n", reason);
break;
}
}
static struct local_client *cman_client;
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
/* Save this for data_callback */
cman_client = fd;
/* We never return a new client */
*new_client = NULL;
return cman_dispatch(c_handle, 0);
}
static void data_callback(cman_handle_t handle, void *private,
char *buf, int len, uint8_t port, int nodeid)
{
/* Ignore looped back messages */
if (nodeid == this_node.cn_nodeid)
return;
process_message(cman_client, buf, len, (char *)&nodeid);
}
static void _add_up_node(const char *csid)
{
/* It's up ! */
int nodeid = nodeid_from_csid(csid);
dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
DEBUGLOG("Added new node %d to updown list\n", nodeid);
}
static void _cluster_closedown(void)
{
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
cman_finish(c_handle);
}
static int is_listening(int nodeid)
{
int status;
do {
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
if (status < 0 && errno == EBUSY) { /* Don't busywait */
sleep(1);
errno = EBUSY; /* In case sleep trashes it */
}
}
while (status < 0 && errno == EBUSY);
return status;
}
/* Populate the list of CLVMDs running.
called only at startup time */
static void count_clvmds_running(void)
{
int i;
for (i = 0; i < num_nodes; i++) {
int nodeid = nodes[i].cn_nodeid;
if (is_listening(nodeid) == 1)
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
else
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
}
}
/* Get a list of active cluster members */
static void get_members(void)
{
int retnodes;
int status;
int i;
int high_nodeid = 0;
num_nodes = cman_get_node_count(c_handle);
if (num_nodes == -1) {
log_error("Unable to get node count");
return;
}
/* Not enough room for new nodes list ? */
if (num_nodes > count_nodes && nodes) {
free(nodes);
nodes = NULL;
}
if (nodes == NULL) {
count_nodes = num_nodes + 10; /* Overallocate a little */
nodes = malloc(count_nodes * sizeof(struct cman_node));
if (!nodes) {
log_error("Unable to allocate nodes array\n");
exit(5);
}
}
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
if (status < 0) {
log_error("Unable to get node details");
exit(6);
}
/* Get the highest nodeid */
for (i=0; i<retnodes; i++) {
if (nodes[i].cn_nodeid > high_nodeid)
high_nodeid = nodes[i].cn_nodeid;
}
}
/* Convert a node name to a CSID */
static int _csid_from_name(char *csid, const char *name)
{
int i;
for (i = 0; i < num_nodes; i++) {
if (strcmp(name, nodes[i].cn_name) == 0) {
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
return 0;
}
}
return -1;
}
/* Convert a CSID to a node name */
static int _name_from_csid(const char *csid, char *name)
{
int i;
for (i = 0; i < num_nodes; i++) {
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
strcpy(name, nodes[i].cn_name);
return 0;
}
}
/* Who?? */
strcpy(name, "Unknown");
return -1;
}
/* Convert a node ID to a node name */
static int name_from_nodeid(int nodeid, char *name)
{
int i;
for (i = 0; i < num_nodes; i++) {
if (nodeid == nodes[i].cn_nodeid) {
strcpy(name, nodes[i].cn_name);
return 0;
}
}
/* Who?? */
strcpy(name, "Unknown");
return -1;
}
/* Convert a CSID to a node ID */
static int nodeid_from_csid(const char *csid)
{
int nodeid;
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
return nodeid;
}
static int _is_quorate(void)
{
return cman_is_quorate(c_handle);
}
static void sync_ast_routine(void *arg)
{
struct lock_wait *lwait = arg;
pthread_mutex_lock(&lwait->mutex);
pthread_cond_signal(&lwait->cond);
pthread_mutex_unlock(&lwait->mutex);
}
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
struct lock_wait lwait;
if (!lockid) {
errno = EINVAL;
return -1;
}
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
/* Conversions need the lockid in the LKSB */
if (flags & LKF_CONVERT)
lwait.lksb.sb_lkid = *lockid;
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
status = dlm_ls_lock(lockspace,
mode,
&lwait.lksb,
flags,
resource,
strlen(resource),
0, sync_ast_routine, &lwait, NULL, NULL);
if (status)
return status;
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
*lockid = lwait.lksb.sb_lkid;
errno = lwait.lksb.sb_status;
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
if (lwait.lksb.sb_status)
return -1;
else
return 0;
}
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
{
int status;
struct lock_wait lwait;
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
pthread_cond_init(&lwait.cond, NULL);
pthread_mutex_init(&lwait.mutex, NULL);
pthread_mutex_lock(&lwait.mutex);
status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
if (status)
return status;
/* Wait for it to complete */
pthread_cond_wait(&lwait.cond, &lwait.mutex);
pthread_mutex_unlock(&lwait.mutex);
errno = lwait.lksb.sb_status;
if (lwait.lksb.sb_status != EUNLOCK)
return -1;
else
return 0;
}
static int _get_cluster_name(char *buf, int buflen)
{
cman_cluster_t cluster_info;
int status;
status = cman_get_cluster(c_handle, &cluster_info);
if (!status) {
strncpy(buf, cluster_info.ci_name, buflen);
}
return status;
}
static struct cluster_ops _cluster_cman_ops = {
.name = "cman",
.cluster_init_completed = _cluster_init_completed,
.cluster_send_message = _cluster_send_message,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};
struct cluster_ops *init_cman_cluster(void)
{
if (!_init_cluster())
return &_cluster_cman_ops;
else
return NULL;
}

View File

@ -1,414 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
CLVMD Cluster LVM daemon command processor.
To add commands to the daemon simply add a processor in do_command and return
and messages back in buf and the length in *retlen. The initial value of
buflen is the maximum size of the buffer. if buf is not large enough then it
may be reallocated by the functions in here to a suitable size bearing in
mind that anything larger than the passed-in size will have to be returned
using the system LV and so performance will suffer.
The status return will be negated and passed back to the originating node.
pre- and post- command routines are called only on the local node. The
purpose is primarily to get and release locks, though the pre- routine should
also do any other local setups required by the command (if any) and can
return a failure code that prevents the command from being distributed around
the cluster
The pre- and post- routines are run in their own thread so can block as long
they like, do_command is run in the main clvmd thread so should not block for
too long. If the pre-command returns an error code (!=0) then the command
will not be propogated around the cluster but the post-command WILL be called
Also note that the pre and post routine are *always* called on the local
node, even if the command to be executed was only requested to run on a
remote node. It may peek inside the client structure to check the status of
the command.
The clients of the daemon must, naturally, understand the return messages and
codes.
Routines in here may only READ the values in the client structure passed in
apart from client->private which they are free to do what they like with.
*/
#include "clvmd-common.h"
#include "clvmd-comms.h"
#include "clvm.h"
#include "clvmd.h"
#include "lvm-globals.h"
#include "lvm-functions.h"
#include "locking.h"
#include <sys/utsname.h>
extern struct cluster_ops *clops;
static int restart_clvmd(void);
/* This is where all the real work happens:
NOTE: client will be NULL when this is executed on a remote node */
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
char **buf, int buflen, int *retlen)
{
char *args = msg->node + strlen(msg->node) + 1;
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
int status = 0;
char *lockname;
const char *locktype;
struct utsname nodeinfo;
unsigned char lock_cmd;
unsigned char lock_flags;
/* Do the command */
switch (msg->cmd) {
/* Just a test message */
case CLVMD_CMD_TEST:
if (arglen > buflen) {
char *new_buf;
buflen = arglen + 200;
new_buf = realloc(*buf, buflen);
if (new_buf == NULL) {
status = errno;
free (*buf);
}
*buf = new_buf;
}
if (*buf) {
if (uname(&nodeinfo))
memset(&nodeinfo, 0, sizeof(nodeinfo));
*retlen = 1 + dm_snprintf(*buf, buflen,
"TEST from %s: %s v%s",
nodeinfo.nodename, args,
nodeinfo.release);
}
break;
case CLVMD_CMD_LOCK_VG:
lock_cmd = args[0];
lock_flags = args[1];
lockname = &args[2];
/* Check to see if the VG is in use by LVM1 */
status = do_check_lvm1(lockname);
do_lock_vg(lock_cmd, lock_flags, lockname);
break;
case CLVMD_CMD_LOCK_LV:
/* This is the biggie */
lock_cmd = args[0];
lock_flags = args[1];
lockname = &args[2];
status = do_lock_lv(lock_cmd, lock_flags, lockname);
/* Replace EIO with something less scary */
if (status == EIO) {
*retlen = 1 + dm_snprintf(*buf, buflen, "%s",
get_last_lvm_error());
return EIO;
}
break;
case CLVMD_CMD_LOCK_QUERY:
lockname = &args[2];
if (buflen < 3)
return EIO;
if ((locktype = do_lock_query(lockname)))
*retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
break;
case CLVMD_CMD_REFRESH:
do_refresh_cache();
break;
case CLVMD_CMD_SYNC_NAMES:
lvm_do_fs_unlock();
break;
case CLVMD_CMD_SET_DEBUG:
clvmd_set_debug((debug_t) args[0]);
break;
case CLVMD_CMD_RESTART:
status = restart_clvmd();
break;
case CLVMD_CMD_GET_CLUSTERNAME:
status = clops->get_cluster_name(*buf, buflen);
if (!status)
*retlen = strlen(*buf)+1;
break;
case CLVMD_CMD_VG_BACKUP:
/*
* Do not run backup on local node, caller should do that.
*/
if (!client)
lvm_do_backup(&args[2]);
break;
default:
/* Won't get here because command is validated in pre_command */
break;
}
/* Check the status of the command and return the error text */
if (status) {
*retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
strerror(status)) : -1);
}
return status;
}
static int lock_vg(struct local_client *client)
{
struct dm_hash_table *lock_hash;
struct clvm_header *header =
(struct clvm_header *) client->bits.localsock.cmd;
unsigned char lock_cmd;
int lock_mode;
char *args = header->node + strlen(header->node) + 1;
int lkid;
int status;
char *lockname;
/*
* Keep a track of VG locks in our own hash table. In current
* practice there should only ever be more than two VGs locked
* if a user tries to merge lots of them at once
*/
if (!client->bits.localsock.private) {
if (!(lock_hash = dm_hash_create(3)))
return ENOMEM;
client->bits.localsock.private = (void *) lock_hash;
} else
lock_hash = (struct dm_hash_table *) client->bits.localsock.private;
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
lock_mode = ((int) lock_cmd & LCK_TYPE_MASK);
/* lock_flags = args[1]; */
lockname = &args[2];
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
if (lock_mode == LCK_UNLOCK) {
if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
return EINVAL;
if ((status = sync_unlock(lockname, lkid)))
status = errno;
else
dm_hash_remove(lock_hash, lockname);
} else {
/* Read locks need to be PR; other modes get passed through */
if (lock_mode == LCK_READ)
lock_mode = LCK_PREAD;
if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid)))
status = errno;
else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid))
return ENOMEM;
}
return status;
}
/* Pre-command is a good place to get locks that are needed only for the duration
of the commands around the cluster (don't forget to free them in post-command),
and to sanity check the command arguments */
int do_pre_command(struct local_client *client)
{
struct clvm_header *header =
(struct clvm_header *) client->bits.localsock.cmd;
unsigned char lock_cmd;
unsigned char lock_flags;
char *args = header->node + strlen(header->node) + 1;
int lockid = 0;
int status = 0;
char *lockname;
switch (header->cmd) {
case CLVMD_CMD_TEST:
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
client->bits.localsock.private = (void *)(long)lockid;
break;
case CLVMD_CMD_LOCK_VG:
lockname = &args[2];
/* We take out a real lock unless LCK_CACHE was set */
if (!strncmp(lockname, "V_", 2) ||
!strncmp(lockname, "P_#", 3))
status = lock_vg(client);
break;
case CLVMD_CMD_LOCK_LV:
lock_cmd = args[0];
lock_flags = args[1];
lockname = &args[2];
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
break;
case CLVMD_CMD_REFRESH:
case CLVMD_CMD_GET_CLUSTERNAME:
case CLVMD_CMD_SET_DEBUG:
case CLVMD_CMD_VG_BACKUP:
case CLVMD_CMD_SYNC_NAMES:
case CLVMD_CMD_LOCK_QUERY:
case CLVMD_CMD_RESTART:
break;
default:
log_error("Unknown command %d received\n", header->cmd);
status = EINVAL;
}
return status;
}
/* Note that the post-command routine is called even if the pre-command or the real command
failed */
int do_post_command(struct local_client *client)
{
struct clvm_header *header =
(struct clvm_header *) client->bits.localsock.cmd;
int status = 0;
unsigned char lock_cmd;
unsigned char lock_flags;
char *args = header->node + strlen(header->node) + 1;
char *lockname;
switch (header->cmd) {
case CLVMD_CMD_TEST:
status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
client->bits.localsock.private = NULL;
break;
case CLVMD_CMD_LOCK_LV:
lock_cmd = args[0];
lock_flags = args[1];
lockname = &args[2];
status = post_lock_lv(lock_cmd, lock_flags, lockname);
break;
default:
/* Nothing to do here */
break;
}
return status;
}
/* Called when the client is about to be deleted */
void cmd_client_cleanup(struct local_client *client)
{
struct dm_hash_node *v;
struct dm_hash_table *lock_hash;
int lkid;
char *lockname;
if (!client->bits.localsock.private)
return;
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
dm_hash_iterate(v, lock_hash) {
lkid = (int)(long)dm_hash_get_data(lock_hash, v);
lockname = dm_hash_get_key(lock_hash, v);
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
(void) sync_unlock(lockname, lkid);
}
dm_hash_destroy(lock_hash);
client->bits.localsock.private = NULL;
}
static int restart_clvmd(void)
{
const char **argv;
char *lv_name;
int argc = 0, max_locks = 0;
struct dm_hash_node *hn = NULL;
char debug_arg[16];
const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH;
DEBUGLOG("clvmd restart requested\n");
/* Count exclusively-open LVs */
do {
hn = get_next_excl_lock(hn, &lv_name);
if (lv_name) {
max_locks++;
if (!*lv_name)
break; /* FIXME: Is this error ? */
}
} while (hn);
/* clvmd + locks (-E uuid) + debug (-d X) + NULL */
if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv))))
goto_out;
/*
* Build the command-line
*/
argv[argc++] = "clvmd";
/* Propagate debug options */
if (clvmd_get_debug()) {
if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0)
goto_out;
argv[argc++] = debug_arg;
}
/* Propagate foreground options */
if (clvmd_get_foreground())
argv[argc++] = "-f";
argv[argc++] = "-I";
argv[argc++] = clops->name;
/* Now add the exclusively-open LVs */
hn = NULL;
do {
hn = get_next_excl_lock(hn, &lv_name);
if (lv_name) {
if (!*lv_name)
break; /* FIXME: Is this error ? */
argv[argc++] = "-E";
argv[argc++] = lv_name;
DEBUGLOG("excl lock: %s\n", lv_name);
}
} while (hn);
argv[argc] = NULL;
/* Exec new clvmd */
DEBUGLOG("--- Restarting %s ---\n", clvmd);
for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]);
/* NOTE: This will fail when downgrading! */
execvp(clvmd, (char **)argv);
out:
/* We failed */
DEBUGLOG("Restart of clvmd failed.\n");
free(argv);
return EIO;
}

View File

@ -1,32 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This file must be included first by every clvmd source file.
*/
#ifndef _LVM_CLVMD_COMMON_H
#define _LVM_CLVMD_COMMON_H
#include "configure.h"
#define _REENTRANT
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include "libdevmapper.h"
#include "lvm-logging.h"
#include <unistd.h>
#endif

View File

@ -1,119 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Abstraction layer for clvmd cluster communications
*/
#ifndef _CLVMD_COMMS_H
#define _CLVMD_COMMS_H
struct local_client;
struct cluster_ops {
const char *name;
void (*cluster_init_completed) (void);
int (*cluster_send_message) (const void *buf, int msglen,
const char *csid,
const char *errtext);
int (*name_from_csid) (const char *csid, char *name);
int (*csid_from_name) (char *csid, const char *name);
int (*get_num_nodes) (void);
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client);
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
int (*cluster_do_node_callback) (struct local_client *client,
void (*callback) (struct local_client *,
const char *csid,
int node_up));
int (*is_quorate) (void);
void (*get_our_csid) (char *csid);
void (*add_up_node) (const char *csid);
void (*reread_config) (void);
void (*cluster_closedown) (void);
int (*get_cluster_name)(char *buf, int buflen);
int (*sync_lock) (const char *resource, int mode,
int flags, int *lockid);
int (*sync_unlock) (const char *resource, int lockid);
};
#ifdef USE_CMAN
# include <netinet/in.h>
# include "libcman.h"
# define CMAN_MAX_CSID_LEN 4
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
# endif
# undef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
# define CMAN_MAX_CLUSTER_MESSAGE 1500
# define CLUSTER_PORT_CLVMD 11
struct cluster_ops *init_cman_cluster(void);
#endif
#ifdef USE_OPENAIS
# include <openais/saAis.h>
# include <corosync/totem/totem.h>
# define OPENAIS_CSID_LEN (sizeof(int))
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
# endif
# ifndef CMAN_MAX_CLUSTER_MESSAGE
# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
# endif
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN sizeof(int)
# endif
struct cluster_ops *init_openais_cluster(void);
#endif
#ifdef USE_COROSYNC
# include <corosync/corotypes.h>
# define COROSYNC_CSID_LEN (sizeof(int))
# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
# endif
# ifndef CMAN_MAX_CLUSTER_MESSAGE
# define CMAN_MAX_CLUSTER_MESSAGE 65535
# endif
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN sizeof(int)
# endif
struct cluster_ops *init_corosync_cluster(void);
#endif
#ifdef USE_SINGLENODE
# define SINGLENODE_CSID_LEN (sizeof(int))
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
# define MAX_CLUSTER_MEMBER_NAME_LEN 64
# endif
# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535
# ifndef MAX_CSID_LEN
# define MAX_CSID_LEN sizeof(int)
# endif
struct cluster_ops *init_singlenode_cluster(void);
#endif
#endif

View File

@ -1,658 +0,0 @@
/*
* Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This provides the interface between clvmd and corosync/DLM as the cluster
* and lock manager.
*/
#include "clvmd-common.h"
#include <pthread.h>
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#include "lvm-functions.h"
#include "locking.h"
#include <corosync/cpg.h>
#include <corosync/quorum.h>
#ifdef HAVE_COROSYNC_CONFDB_H
# include <corosync/confdb.h>
#elif defined HAVE_COROSYNC_CMAP_H
# include <corosync/cmap.h>
#else
# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined."
#endif
#include <libdlm.h>
#include <syslog.h>
/* Timeout value for several corosync calls */
#define LOCKSPACE_NAME "clvmd"
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
const struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
size_t msg_len);
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
const struct cpg_name *groupName,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries);
static void _cluster_closedown(void);
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;
/* Number of active nodes */
static int num_nodes;
static unsigned int our_nodeid;
static struct local_client *cluster_client;
/* Corosync handles */
static cpg_handle_t cpg_handle;
static quorum_handle_t quorum_handle;
/* DLM Handle */
static dlm_lshandle_t *lockspace;
static struct cpg_name cpg_group_name;
/* Corosync callback structs */
cpg_callbacks_t corosync_cpg_callbacks = {
.cpg_deliver_fn = corosync_cpg_deliver_callback,
.cpg_confchg_fn = corosync_cpg_confchg_callback,
};
quorum_callbacks_t quorum_callbacks = {
.quorum_notify_fn = NULL,
};
struct node_info
{
enum {NODE_DOWN, NODE_CLVMD} state;
int nodeid;
};
/* Set errno to something approximating the right value and return 0 or -1 */
static int cs_to_errno(cs_error_t err)
{
switch(err)
{
case CS_OK:
return 0;
case CS_ERR_LIBRARY:
errno = EINVAL;
break;
case CS_ERR_VERSION:
errno = EINVAL;
break;
case CS_ERR_INIT:
errno = EINVAL;
break;
case CS_ERR_TIMEOUT:
errno = ETIME;
break;
case CS_ERR_TRY_AGAIN:
errno = EAGAIN;
break;
case CS_ERR_INVALID_PARAM:
errno = EINVAL;
break;
case CS_ERR_NO_MEMORY:
errno = ENOMEM;
break;
case CS_ERR_BAD_HANDLE:
errno = EINVAL;
break;
case CS_ERR_BUSY:
errno = EBUSY;
break;
case CS_ERR_ACCESS:
errno = EPERM;
break;
case CS_ERR_NOT_EXIST:
errno = ENOENT;
break;
case CS_ERR_NAME_TOO_LONG:
errno = ENAMETOOLONG;
break;
case CS_ERR_EXIST:
errno = EEXIST;
break;
case CS_ERR_NO_SPACE:
errno = ENOSPC;
break;
case CS_ERR_INTERRUPT:
errno = EINTR;
break;
case CS_ERR_NAME_NOT_FOUND:
errno = ENOENT;
break;
case CS_ERR_NO_RESOURCES:
errno = ENOMEM;
break;
case CS_ERR_NOT_SUPPORTED:
errno = EOPNOTSUPP;
break;
case CS_ERR_BAD_OPERATION:
errno = EINVAL;
break;
case CS_ERR_FAILED_OPERATION:
errno = EIO;
break;
case CS_ERR_MESSAGE_ERROR:
errno = EIO;
break;
case CS_ERR_QUEUE_FULL:
errno = EXFULL;
break;
case CS_ERR_QUEUE_NOT_AVAILABLE:
errno = EINVAL;
break;
case CS_ERR_BAD_FLAGS:
errno = EINVAL;
break;
case CS_ERR_TOO_BIG:
errno = E2BIG;
break;
case CS_ERR_NO_SECTIONS:
errno = ENOMEM;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
static char *print_corosync_csid(const char *csid)
{
static char buf[128];
int id;
memcpy(&id, csid, sizeof(int));
sprintf(buf, "%d", id);
return buf;
}
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
const struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
size_t msg_len)
{
int target_nodeid;
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
our_nodeid, nodeid, target_nodeid, msg_len-4);
if (nodeid != our_nodeid)
if (target_nodeid == our_nodeid || target_nodeid == 0)
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
}
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
const struct cpg_name *groupName,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries)
{
int i;
struct node_info *ninfo;
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
joined_list_entries, left_list_entries, member_list_entries);
for (i=0; i<joined_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&joined_list[i].nodeid,
COROSYNC_CSID_LEN);
if (!ninfo) {
ninfo = malloc(sizeof(struct node_info));
if (!ninfo) {
break;
}
else {
ninfo->nodeid = joined_list[i].nodeid;
dm_hash_insert_binary(node_hash,
(char *)&ninfo->nodeid,
COROSYNC_CSID_LEN, ninfo);
}
}
ninfo->state = NODE_CLVMD;
}
for (i=0; i<left_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&left_list[i].nodeid,
COROSYNC_CSID_LEN);
if (ninfo)
ninfo->state = NODE_DOWN;
}
num_nodes = member_list_entries;
}
static int _init_cluster(void)
{
cs_error_t err;
#ifdef QUORUM_SET /* corosync/quorum.h */
uint32_t quorum_type;
#endif
node_hash = dm_hash_create(100);
err = cpg_initialize(&cpg_handle,
&corosync_cpg_callbacks);
if (err != CS_OK) {
syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
err);
DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
return cs_to_errno(err);
}
#ifdef QUORUM_SET
err = quorum_initialize(&quorum_handle,
&quorum_callbacks,
&quorum_type);
if (quorum_type != QUORUM_SET) {
syslog(LOG_ERR, "Corosync quorum service is not configured");
DEBUGLOG("Corosync quorum service is not configured");
return EINVAL;
}
#else
err = quorum_initialize(&quorum_handle,
&quorum_callbacks);
#endif
if (err != CS_OK) {
syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
err);
DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
return cs_to_errno(err);
}
/* Create a lockspace for LV & VG locks to live in */
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
if (!lockspace) {
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
if (!lockspace) {
syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m");
return -1;
}
DEBUGLOG("Created DLM lockspace for CLVMD.\n");
} else
DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n");
dlm_ls_pthread_init(lockspace);
DEBUGLOG("DLM initialisation complete\n");
/* Connect to the clvmd group */
strcpy((char *)cpg_group_name.value, "clvmd");
cpg_group_name.length = strlen((char *)cpg_group_name.value);
err = cpg_join(cpg_handle, &cpg_group_name);
if (err != CS_OK) {
cpg_finalize(cpg_handle);
quorum_finalize(quorum_handle);
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
syslog(LOG_ERR, "Cannot join clvmd process group");
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
return cs_to_errno(err);
}
err = cpg_local_get(cpg_handle,
&our_nodeid);
if (err != CS_OK) {
cpg_finalize(cpg_handle);
quorum_finalize(quorum_handle);
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
syslog(LOG_ERR, "Cannot get local node id\n");
return cs_to_errno(err);
}
DEBUGLOG("Our local node id is %d\n", our_nodeid);
DEBUGLOG("Connected to Corosync\n");
return 0;
}
static void _cluster_closedown(void)
{
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
cpg_finalize(cpg_handle);
quorum_finalize(quorum_handle);
}
static void _get_our_csid(char *csid)
{
memcpy(csid, &our_nodeid, sizeof(int));
}
/* Corosync doesn't really have nmode names so we
just use the node ID in hex instead */
static int _csid_from_name(char *csid, const char *name)
{
int nodeid;
struct node_info *ninfo;
if (sscanf(name, "%x", &nodeid) == 1) {
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
if (ninfo)
return nodeid;
}
return -1;
}
static int _name_from_csid(const char *csid, char *name)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
if (!ninfo)
{
sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
return -1;
}
sprintf(name, "%x", ninfo->nodeid);
return 0;
}
static int _get_num_nodes(void)
{
DEBUGLOG("num_nodes = %d\n", num_nodes);
return num_nodes;
}
/* Node is now known to be running a clvmd */
static void _add_up_node(const char *csid)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
if (!ninfo) {
DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
print_corosync_csid(csid));
return;
}
DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
ninfo->state = NODE_CLVMD;
return;
}
/* Call a callback for each node, so the caller knows whether it's up or down */
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *,
const char *csid, int node_up))
{
struct dm_hash_node *hn;
struct node_info *ninfo;
dm_hash_iterate(hn, node_hash)
{
char csid[COROSYNC_CSID_LEN];
ninfo = dm_hash_get_data(node_hash, hn);
memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
ninfo->state);
if (ninfo->state == NODE_CLVMD)
callback(master_client, csid, 1);
}
return 0;
}
/* Real locking */
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
{
struct dlm_lksb lksb;
int err;
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
if (flags & LKF_CONVERT)
lksb.sb_lkid = *lockid;
err = dlm_ls_lock_wait(lockspace,
mode,
&lksb,
flags,
resource,
strlen(resource),
0,
NULL, NULL, NULL);
if (err != 0)
{
DEBUGLOG("dlm_ls_lock returned %d\n", errno);
return err;
}
if (lksb.sb_status != 0)
{
DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
errno = lksb.sb_status;
return -1;
}
DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
*lockid = lksb.sb_lkid;
return 0;
}
static int _unlock_resource(const char *resource, int lockid)
{
struct dlm_lksb lksb;
int err;
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
lksb.sb_lkid = lockid;
err = dlm_ls_unlock_wait(lockspace,
lockid,
0,
&lksb);
if (err != 0)
{
DEBUGLOG("Unlock returned %d\n", err);
return err;
}
if (lksb.sb_status != EUNLOCK)
{
DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
errno = lksb.sb_status;
return -1;
}
return 0;
}
static int _is_quorate(void)
{
int quorate;
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
return quorate;
else
return 0;
}
static int _get_main_cluster_fd(void)
{
int select_fd;
cpg_fd_get(cpg_handle, &select_fd);
return select_fd;
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
cluster_client = fd;
*new_client = NULL;
cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
return 1;
}
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
struct iovec iov[2];
cs_error_t err;
int target_node;
if (csid)
memcpy(&target_node, csid, COROSYNC_CSID_LEN);
else
target_node = 0;
iov[0].iov_base = &target_node;
iov[0].iov_len = sizeof(int);
iov[1].iov_base = (char *)buf;
iov[1].iov_len = msglen;
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
return cs_to_errno(err);
}
#ifdef HAVE_COROSYNC_CONFDB_H
/*
* We are not necessarily connected to a Red Hat Cluster system,
* but if we are, this returns the cluster name from cluster.conf.
* I've used confdb rather than ccs to reduce the inter-package
* dependancies as well as to allow people to set a cluster name
* for themselves even if they are not running on RH cluster.
*/
static int _get_cluster_name(char *buf, int buflen)
{
confdb_handle_t handle;
int result;
size_t namelen = buflen;
hdb_handle_t cluster_handle;
confdb_callbacks_t callbacks = {
.confdb_key_change_notify_fn = NULL,
.confdb_object_create_change_notify_fn = NULL,
.confdb_object_delete_change_notify_fn = NULL
};
/* This is a default in case everything else fails */
strncpy(buf, "Corosync", buflen);
/* Look for a cluster name in confdb */
result = confdb_initialize (&handle, &callbacks);
if (result != CS_OK)
return 0;
result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
if (result != CS_OK)
goto out;
result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
if (result != CS_OK)
goto out;
result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
if (result != CS_OK)
goto out;
buf[namelen] = '\0';
out:
confdb_finalize(handle);
return 0;
}
#elif defined HAVE_COROSYNC_CMAP_H
static int _get_cluster_name(char *buf, int buflen)
{
cmap_handle_t cmap_handle = 0;
int result;
char *name = NULL;
/* This is a default in case everything else fails */
strncpy(buf, "Corosync", buflen);
/* Look for a cluster name in cmap */
result = cmap_initialize(&cmap_handle);
if (result != CS_OK)
return 0;
result = cmap_get_string(cmap_handle, "totem.cluster_name", &name);
if (result != CS_OK)
goto out;
memset(buf, 0, buflen);
strncpy(buf, name, buflen - 1);
out:
if (name)
free(name);
cmap_finalize(cmap_handle);
return 0;
}
#endif
static struct cluster_ops _cluster_corosync_ops = {
.name = "corosync",
.cluster_init_completed = NULL,
.cluster_send_message = _cluster_send_message,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.reread_config = NULL,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _lock_resource,
.sync_unlock = _unlock_resource,
};
struct cluster_ops *init_corosync_cluster(void)
{
if (!_init_cluster())
return &_cluster_corosync_ops;
else
return NULL;
}

View File

@ -1,689 +0,0 @@
/*
* Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This provides the interface between clvmd and OpenAIS as the cluster
* and lock manager.
*/
#include "clvmd-common.h"
#include <pthread.h>
#include <fcntl.h>
#include <syslog.h>
#include <openais/saAis.h>
#include <openais/saLck.h>
#include <corosync/corotypes.h>
#include <corosync/cpg.h>
#include "locking.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "lvm-functions.h"
#include "clvmd.h"
/* Timeout value for several openais calls */
#define TIMEOUT 10
static void openais_cpg_deliver_callback (cpg_handle_t handle,
const struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
size_t msg_len);
static void openais_cpg_confchg_callback(cpg_handle_t handle,
const struct cpg_name *groupName,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries);
static void _cluster_closedown(void);
/* Hash list of nodes in the cluster */
static struct dm_hash_table *node_hash;
/* For associating lock IDs & resource handles */
static struct dm_hash_table *lock_hash;
/* Number of active nodes */
static int num_nodes;
static unsigned int our_nodeid;
static struct local_client *cluster_client;
/* OpenAIS handles */
static cpg_handle_t cpg_handle;
static SaLckHandleT lck_handle;
static struct cpg_name cpg_group_name;
/* Openais callback structs */
cpg_callbacks_t openais_cpg_callbacks = {
.cpg_deliver_fn = openais_cpg_deliver_callback,
.cpg_confchg_fn = openais_cpg_confchg_callback,
};
struct node_info
{
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
int nodeid;
};
struct lock_info
{
SaLckResourceHandleT res_handle;
SaLckLockIdT lock_id;
SaNameT lock_name;
};
/* Set errno to something approximating the right value and return 0 or -1 */
static int ais_to_errno(SaAisErrorT err)
{
switch(err)
{
case SA_AIS_OK:
return 0;
case SA_AIS_ERR_LIBRARY:
errno = EINVAL;
break;
case SA_AIS_ERR_VERSION:
errno = EINVAL;
break;
case SA_AIS_ERR_INIT:
errno = EINVAL;
break;
case SA_AIS_ERR_TIMEOUT:
errno = ETIME;
break;
case SA_AIS_ERR_TRY_AGAIN:
errno = EAGAIN;
break;
case SA_AIS_ERR_INVALID_PARAM:
errno = EINVAL;
break;
case SA_AIS_ERR_NO_MEMORY:
errno = ENOMEM;
break;
case SA_AIS_ERR_BAD_HANDLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BUSY:
errno = EBUSY;
break;
case SA_AIS_ERR_ACCESS:
errno = EPERM;
break;
case SA_AIS_ERR_NOT_EXIST:
errno = ENOENT;
break;
case SA_AIS_ERR_NAME_TOO_LONG:
errno = ENAMETOOLONG;
break;
case SA_AIS_ERR_EXIST:
errno = EEXIST;
break;
case SA_AIS_ERR_NO_SPACE:
errno = ENOSPC;
break;
case SA_AIS_ERR_INTERRUPT:
errno = EINTR;
break;
case SA_AIS_ERR_NAME_NOT_FOUND:
errno = ENOENT;
break;
case SA_AIS_ERR_NO_RESOURCES:
errno = ENOMEM;
break;
case SA_AIS_ERR_NOT_SUPPORTED:
errno = EOPNOTSUPP;
break;
case SA_AIS_ERR_BAD_OPERATION:
errno = EINVAL;
break;
case SA_AIS_ERR_FAILED_OPERATION:
errno = EIO;
break;
case SA_AIS_ERR_MESSAGE_ERROR:
errno = EIO;
break;
case SA_AIS_ERR_QUEUE_FULL:
errno = EXFULL;
break;
case SA_AIS_ERR_QUEUE_NOT_AVAILABLE:
errno = EINVAL;
break;
case SA_AIS_ERR_BAD_FLAGS:
errno = EINVAL;
break;
case SA_AIS_ERR_TOO_BIG:
errno = E2BIG;
break;
case SA_AIS_ERR_NO_SECTIONS:
errno = ENOMEM;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
static char *print_openais_csid(const char *csid)
{
static char buf[128];
int id;
memcpy(&id, csid, sizeof(int));
sprintf(buf, "%d", id);
return buf;
}
static int add_internal_client(int fd, fd_callback_t callback)
{
struct local_client *client;
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
if (!(client = dm_zalloc(sizeof(*client)))) {
DEBUGLOG("malloc failed\n");
return -1;
}
client->fd = fd;
client->type = CLUSTER_INTERNAL;
client->callback = callback;
add_client(client);
/* Set Close-on-exec */
fcntl(fd, F_SETFD, 1);
return 0;
}
static void openais_cpg_deliver_callback (cpg_handle_t handle,
const struct cpg_name *groupName,
uint32_t nodeid,
uint32_t pid,
void *msg,
size_t msg_len)
{
int target_nodeid;
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n",
our_nodeid, nodeid, target_nodeid, msg_len-4);
if (nodeid != our_nodeid)
if (target_nodeid == our_nodeid || target_nodeid == 0)
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
}
static void openais_cpg_confchg_callback(cpg_handle_t handle,
const struct cpg_name *groupName,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries)
{
int i;
struct node_info *ninfo;
DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
"%" PRIsize_t " left, %" PRIsize_t " members\n",
joined_list_entries, left_list_entries, member_list_entries);
for (i=0; i<joined_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&joined_list[i].nodeid,
OPENAIS_CSID_LEN);
if (!ninfo) {
ninfo = malloc(sizeof(struct node_info));
if (!ninfo) {
break;
}
else {
ninfo->nodeid = joined_list[i].nodeid;
dm_hash_insert_binary(node_hash,
(char *)&ninfo->nodeid,
OPENAIS_CSID_LEN, ninfo);
}
}
ninfo->state = NODE_CLVMD;
}
for (i=0; i<left_list_entries; i++) {
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&left_list[i].nodeid,
OPENAIS_CSID_LEN);
if (ninfo)
ninfo->state = NODE_DOWN;
}
for (i=0; i<member_list_entries; i++) {
if (member_list[i].nodeid == 0) continue;
ninfo = dm_hash_lookup_binary(node_hash,
(char *)&member_list[i].nodeid,
OPENAIS_CSID_LEN);
if (!ninfo) {
ninfo = malloc(sizeof(struct node_info));
if (!ninfo) {
break;
}
else {
ninfo->nodeid = member_list[i].nodeid;
dm_hash_insert_binary(node_hash,
(char *)&ninfo->nodeid,
OPENAIS_CSID_LEN, ninfo);
}
}
ninfo->state = NODE_CLVMD;
}
num_nodes = member_list_entries;
}
static int lck_dispatch(struct local_client *client, char *buf, int len,
const char *csid, struct local_client **new_client)
{
*new_client = NULL;
saLckDispatch(lck_handle, SA_DISPATCH_ONE);
return 1;
}
static int _init_cluster(void)
{
SaAisErrorT err;
SaVersionT ver = { 'B', 1, 1 };
int select_fd;
node_hash = dm_hash_create(100);
lock_hash = dm_hash_create(10);
err = cpg_initialize(&cpg_handle,
&openais_cpg_callbacks);
if (err != SA_AIS_OK) {
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err);
return ais_to_errno(err);
}
err = saLckInitialize(&lck_handle,
NULL,
&ver);
if (err != SA_AIS_OK) {
cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
err);
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
return ais_to_errno(err);
}
/* Connect to the clvmd group */
strcpy((char *)cpg_group_name.value, "clvmd");
cpg_group_name.length = strlen((char *)cpg_group_name.value);
err = cpg_join(cpg_handle, &cpg_group_name);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
syslog(LOG_ERR, "Cannot join clvmd process group");
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
return ais_to_errno(err);
}
err = cpg_local_get(cpg_handle,
&our_nodeid);
if (err != SA_AIS_OK) {
cpg_finalize(cpg_handle);
saLckFinalize(lck_handle);
syslog(LOG_ERR, "Cannot get local node id\n");
return ais_to_errno(err);
}
DEBUGLOG("Our local node id is %d\n", our_nodeid);
saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd);
add_internal_client(select_fd, lck_dispatch);
DEBUGLOG("Connected to OpenAIS\n");
return 0;
}
static void _cluster_closedown(void)
{
saLckFinalize(lck_handle);
cpg_finalize(cpg_handle);
}
static void _get_our_csid(char *csid)
{
memcpy(csid, &our_nodeid, sizeof(int));
}
/* OpenAIS doesn't really have nmode names so we
just use the node ID in hex instead */
static int _csid_from_name(char *csid, const char *name)
{
int nodeid;
struct node_info *ninfo;
if (sscanf(name, "%x", &nodeid) == 1) {
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (ninfo)
return nodeid;
}
return -1;
}
static int _name_from_csid(const char *csid, char *name)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo)
{
sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
return -1;
}
sprintf(name, "%x", ninfo->nodeid);
return 0;
}
static int _get_num_nodes()
{
DEBUGLOG("num_nodes = %d\n", num_nodes);
return num_nodes;
}
/* Node is now known to be running a clvmd */
static void _add_up_node(const char *csid)
{
struct node_info *ninfo;
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
if (!ninfo) {
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
print_openais_csid(csid));
return;
}
DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid);
ninfo->state = NODE_CLVMD;
return;
}
/* Call a callback for each node, so the caller knows whether it's up or down */
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *,
const char *csid, int node_up))
{
struct dm_hash_node *hn;
struct node_info *ninfo;
int somedown = 0;
dm_hash_iterate(hn, node_hash)
{
char csid[OPENAIS_CSID_LEN];
ninfo = dm_hash_get_data(node_hash, hn);
memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN);
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
ninfo->state);
if (ninfo->state != NODE_DOWN)
callback(master_client, csid, ninfo->state == NODE_CLVMD);
if (ninfo->state != NODE_CLVMD)
somedown = -1;
}
return somedown;
}
/* Real locking */
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
{
struct lock_info *linfo;
SaLckResourceHandleT res_handle;
SaAisErrorT err;
SaLckLockIdT lock_id;
SaLckLockStatusT lockStatus;
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
linfo = malloc(sizeof(struct lock_info));
if (!linfo)
return -1;
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
linfo->lock_name.length = strlen(resource)+1;
strcpy((char *)linfo->lock_name.value, resource);
err = saLckResourceOpen(lck_handle, &linfo->lock_name,
SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle);
if (err != SA_AIS_OK)
{
DEBUGLOG("ResourceOpen returned %d\n", err);
free(linfo);
return ais_to_errno(err);
}
err = saLckResourceLock(
res_handle,
&lock_id,
mode,
flags,
0,
SA_TIME_END,
&lockStatus);
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
{
free(linfo);
saLckResourceClose(res_handle);
return ais_to_errno(err);
}
/* Wait for it to complete */
DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n",
err, lock_id);
linfo->lock_id = lock_id;
linfo->res_handle = res_handle;
dm_hash_insert(lock_hash, resource, linfo);
return ais_to_errno(err);
}
static int _unlock_resource(char *resource, int lockid)
{
SaAisErrorT err;
struct lock_info *linfo;
DEBUGLOG("unlock_resource %s\n", resource);
linfo = dm_hash_lookup(lock_hash, resource);
if (!linfo)
return 0;
DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id);
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
if (err != SA_AIS_OK)
{
DEBUGLOG("Unlock returned %d\n", err);
return ais_to_errno(err);
}
/* Release the resource */
dm_hash_remove(lock_hash, resource);
saLckResourceClose(linfo->res_handle);
free(linfo);
return ais_to_errno(err);
}
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
{
int status;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
switch (mode)
{
case LCK_EXCL:
status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
/* If we can't get this lock too then bail out */
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK,
lockid);
if (status == SA_LCK_LOCK_NOT_QUEUED)
{
_unlock_resource(lock1, *lockid);
status = -1;
errno = EAGAIN;
}
break;
case LCK_PREAD:
case LCK_READ:
status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock2, *lockid);
break;
case LCK_WRITE:
status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid);
if (status)
goto out;
_unlock_resource(lock1, *lockid);
break;
default:
status = -1;
errno = EINVAL;
break;
}
out:
*lockid = mode;
return status;
}
static int _sync_unlock(const char *resource, int lockid)
{
int status = 0;
char lock1[strlen(resource)+3];
char lock2[strlen(resource)+3];
snprintf(lock1, sizeof(lock1), "%s-1", resource);
snprintf(lock2, sizeof(lock2), "%s-2", resource);
_unlock_resource(lock1, lockid);
_unlock_resource(lock2, lockid);
return status;
}
/* We are always quorate ! */
static int _is_quorate()
{
return 1;
}
static int _get_main_cluster_fd(void)
{
int select_fd;
cpg_fd_get(cpg_handle, &select_fd);
return select_fd;
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
cluster_client = fd;
*new_client = NULL;
cpg_dispatch(cpg_handle, SA_DISPATCH_ONE);
return 1;
}
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
const char *errtext)
{
struct iovec iov[2];
SaAisErrorT err;
int target_node;
if (csid)
memcpy(&target_node, csid, OPENAIS_CSID_LEN);
else
target_node = 0;
iov[0].iov_base = &target_node;
iov[0].iov_len = sizeof(int);
iov[1].iov_base = (char *)buf;
iov[1].iov_len = msglen;
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
return ais_to_errno(err);
}
/* We don't have a cluster name to report here */
static int _get_cluster_name(char *buf, int buflen)
{
strncpy(buf, "OpenAIS", buflen);
return 0;
}
static struct cluster_ops _cluster_openais_ops = {
.name = "openais",
.cluster_init_completed = NULL,
.cluster_send_message = _cluster_send_message,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.reread_config = NULL,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _sync_lock,
.sync_unlock = _sync_unlock,
};
struct cluster_ops *init_openais_cluster(void)
{
if (!_init_cluster())
return &_cluster_openais_ops;
return NULL;
}

View File

@ -1,382 +0,0 @@
/*
* Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "clvmd-common.h"
#include <pthread.h>
#include "locking.h"
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#include <sys/un.h>
#include <sys/socket.h>
#include <fcntl.h>
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
static int listen_fd = -1;
static struct dm_hash_table *_locks;
static int _lockid;
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Using one common condition for all locks for simplicity */
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
struct lock {
struct dm_list list;
int lockid;
int mode;
};
static void close_comms(void)
{
if (listen_fd != -1 && close(listen_fd))
stack;
(void)unlink(SINGLENODE_CLVMD_SOCKNAME);
listen_fd = -1;
}
static int init_comms(void)
{
mode_t old_mask;
struct sockaddr_un addr = { .sun_family = AF_UNIX };
if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
sizeof(addr.sun_path))) {
DEBUGLOG("%s: singlenode socket name too long.",
SINGLENODE_CLVMD_SOCKNAME);
return -1;
}
close_comms();
(void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK);
old_mask = umask(0077);
listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0) {
DEBUGLOG("Can't create local socket: %s\n", strerror(errno));
goto error;
}
/* Set Close-on-exec */
if (fcntl(listen_fd, F_SETFD, 1)) {
DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno));
goto error;
}
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
goto error;
}
if (listen(listen_fd, 10) < 0) {
DEBUGLOG("Can't listen local socket: %s\n", strerror(errno));
goto error;
}
umask(old_mask);
(void) dm_prepare_selinux_context(NULL, 0);
return 0;
error:
umask(old_mask);
(void) dm_prepare_selinux_context(NULL, 0);
close_comms();
return -1;
}
static int _init_cluster(void)
{
int r;
if (!(_locks = dm_hash_create(128))) {
DEBUGLOG("Failed to allocate single-node hash table.\n");
return 1;
}
r = init_comms();
if (r) {
dm_hash_destroy(_locks);
_locks = NULL;
return r;
}
DEBUGLOG("Single-node cluster initialised.\n");
return 0;
}
static void _cluster_closedown(void)
{
close_comms();
/* If there is any awaited resource, kill it softly */
pthread_mutex_lock(&_lock_mutex);
dm_hash_destroy(_locks);
_locks = NULL;
_lockid = 0;
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
pthread_mutex_unlock(&_lock_mutex);
}
static void _get_our_csid(char *csid)
{
int nodeid = 1;
memcpy(csid, &nodeid, sizeof(int));
}
static int _csid_from_name(char *csid, const char *name)
{
return 1;
}
static int _name_from_csid(const char *csid, char *name)
{
strcpy(name, "SINGLENODE");
return 0;
}
static int _get_num_nodes(void)
{
return 1;
}
/* Node is now known to be running a clvmd */
static void _add_up_node(const char *csid)
{
}
/* Call a callback for each node, so the caller knows whether it's up or down */
static int _cluster_do_node_callback(struct local_client *master_client,
void (*callback)(struct local_client *,
const char *csid, int node_up))
{
return 0;
}
int _lock_file(const char *file, uint32_t flags);
static const char *_get_mode(int mode)
{
switch (mode) {
case LCK_NULL: return "NULL";
case LCK_READ: return "READ";
case LCK_PREAD: return "PREAD";
case LCK_WRITE: return "WRITE";
case LCK_EXCL: return "EXCLUSIVE";
case LCK_UNLOCK: return "UNLOCK";
default: return "????";
}
}
/* Real locking */
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
{
/* DLM table of allowed transition states */
static const int _dlm_table[6][6] = {
/* Mode NL CR CW PR PW EX */
/* NL */ { 1, 1, 1, 1, 1, 1},
/* CR */ { 1, 1, 1, 1, 1, 0},
/* CW */ { 1, 1, 1, 0, 0, 0},
/* PR */ { 1, 1, 0, 1, 0, 0},
/* PW */ { 1, 1, 0, 0, 0, 0},
/* EX */ { 1, 0, 0, 0, 0, 0}
};
struct lock *lck = NULL, *lckt;
struct dm_list *head;
DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
resource, flags,
(flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
(LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
(flags & LCKF_CONVERT) ? "CONVERT" : "",
_get_mode(mode), mode);
mode &= LCK_TYPE_MASK;
pthread_mutex_lock(&_lock_mutex);
retry:
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
if (!(head = dm_hash_lookup(_locks, resource))) {
if (flags & LCKF_CONVERT) {
/* In real DLM, lock is identified only by lockid, resource is not used */
DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
goto_bad;
}
/* Add new locked resource */
if (!(head = dm_malloc(sizeof(struct dm_list))) ||
!dm_hash_insert(_locks, resource, head)) {
dm_free(head);
goto_bad;
}
dm_list_init(head);
} else /* Update/convert locked resource */
dm_list_iterate_items(lck, head) {
/* Check is all locks are compatible with requested lock */
if (flags & LCKF_CONVERT) {
if (lck->lockid != *lockid)
continue;
DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
dm_list_iterate_items(lckt, head) {
if ((lckt->lockid != *lockid) &&
!_dlm_table[mode][lckt->mode]) {
if (!(flags & LCKF_NOQUEUE) &&
/* TODO: Real dlm uses here conversion queues */
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
_locks) /* End of the game? */
goto retry;
goto bad;
}
}
lck->mode = mode; /* Lock is now converted */
goto out;
} else if (!_dlm_table[mode][lck->mode]) {
DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
resource, lck->lockid, _get_mode(lck->mode));
if (!(flags & LCKF_NOQUEUE) &&
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
_locks) { /* End of the game? */
DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
resource, _get_mode(mode));
goto retry;
}
goto bad;
}
}
if (!(flags & LCKF_CONVERT)) {
if (!(lck = dm_malloc(sizeof(struct lock))))
goto_bad;
*lockid = lck->lockid = ++_lockid;
lck->mode = mode;
dm_list_add(head, &lck->list);
}
out:
pthread_mutex_unlock(&_lock_mutex);
DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
resource, lck->lockid, _get_mode(lck->mode));
return 0;
bad:
pthread_mutex_unlock(&_lock_mutex);
DEBUGLOG("Failed to lock resource %s\n", resource);
return 1; /* fail */
}
static int _unlock_resource(const char *resource, int lockid)
{
struct lock *lck;
struct dm_list *head;
int r = 1;
if (lockid < 0) {
DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
resource, lockid);
return 1;
}
DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
pthread_mutex_lock(&_lock_mutex);
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
if (!(head = dm_hash_lookup(_locks, resource))) {
pthread_mutex_unlock(&_lock_mutex);
DEBUGLOG("Resource %s is not locked.\n", resource);
return 1;
}
dm_list_iterate_items(lck, head)
if (lck->lockid == lockid) {
dm_list_del(&lck->list);
dm_free(lck);
r = 0;
goto out;
}
DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid);
out:
if (dm_list_empty(head)) {
//DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid);
dm_hash_remove(_locks, resource);
dm_free(head);
}
pthread_mutex_unlock(&_lock_mutex);
return r;
}
static int _is_quorate(void)
{
return 1;
}
static int _get_main_cluster_fd(void)
{
return listen_fd;
}
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
const char *csid,
struct local_client **new_client)
{
return 1;
}
static int _cluster_send_message(const void *buf, int msglen,
const char *csid,
const char *errtext)
{
return 0;
}
static int _get_cluster_name(char *buf, int buflen)
{
return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1;
}
static struct cluster_ops _cluster_singlenode_ops = {
.name = "singlenode",
.cluster_init_completed = NULL,
.cluster_send_message = _cluster_send_message,
.name_from_csid = _name_from_csid,
.csid_from_name = _csid_from_name,
.get_num_nodes = _get_num_nodes,
.cluster_fd_callback = _cluster_fd_callback,
.get_main_cluster_fd = _get_main_cluster_fd,
.cluster_do_node_callback = _cluster_do_node_callback,
.is_quorate = _is_quorate,
.get_our_csid = _get_our_csid,
.add_up_node = _add_up_node,
.reread_config = NULL,
.cluster_closedown = _cluster_closedown,
.get_cluster_name = _get_cluster_name,
.sync_lock = _lock_resource,
.sync_unlock = _unlock_resource,
};
struct cluster_ops *init_singlenode_cluster(void)
{
if (!_init_cluster())
return &_cluster_singlenode_ops;
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CLVMD_H
#define _CLVMD_H
#define CLVMD_MAJOR_VERSION 0
#define CLVMD_MINOR_VERSION 2
#define CLVMD_PATCH_VERSION 1
/* Default time (in seconds) we will wait for all remote commands to execute
before declaring them dead */
#define DEFAULT_CMD_TIMEOUT 60
/* One of these for each reply we get from command execution on a node */
struct node_reply {
char node[MAX_CLUSTER_MEMBER_NAME_LEN];
char *replymsg;
int status;
struct node_reply *next;
};
typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t;
/*
* These exist for the use of local sockets only when we are
* collecting responses from all cluster nodes
*/
struct localsock_bits {
struct node_reply *replies;
int num_replies;
int expected_replies;
time_t sent_time; /* So we can check for timeouts */
int in_progress; /* Only execute one cmd at a time per client */
int sent_out; /* Flag to indicate that a command was sent
to remote nodes */
void *private; /* Private area for command processor use */
void *cmd; /* Whole command as passed down local socket */
int cmd_len; /* Length of above */
int pipe; /* Pipe to send PRE completion status down */
int finished; /* Flag to tell subthread to exit */
int all_success; /* Set to 0 if any node (or the pre_command)
failed */
int cleanup_needed; /* helper for cleanup_zombie */
struct local_client *pipe_client;
pthread_t threadid;
enum { PRE_COMMAND, POST_COMMAND } state;
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
pthread_cond_t cond;
};
/* Entries for PIPE clients */
struct pipe_bits {
struct local_client *client; /* Actual (localsock) client */
pthread_t threadid; /* Our own copy of the thread id */
};
/* Entries for Network socket clients */
struct netsock_bits {
void *private;
int flags;
};
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
const char *csid,
struct local_client ** new_client);
/* One of these for each fd we are listening on */
struct local_client {
int fd;
enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
struct local_client *next;
unsigned short xid;
fd_callback_t callback;
uint8_t removeme;
union {
struct localsock_bits localsock;
struct pipe_bits pipe;
struct netsock_bits net;
} bits;
};
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args)
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
/* The real command processor is in clvmd-command.c */
extern int do_command(struct local_client *client, struct clvm_header *msg,
int msglen, char **buf, int buflen, int *retlen);
/* Pre and post command routines are called only on the local node */
extern int do_pre_command(struct local_client *client);
extern int do_post_command(struct local_client *client);
extern void cmd_client_cleanup(struct local_client *client);
extern int add_client(struct local_client *new_client);
extern void clvmd_cluster_init_completed(void);
extern void process_message(struct local_client *client, char *buf,
int len, const char *csid);
extern void debuglog(const char *fmt, ... )
__attribute__ ((format(printf, 1, 2)));
void clvmd_set_debug(debug_t new_de);
debug_t clvmd_get_debug(void);
int clvmd_get_foreground(void);
int sync_lock(const char *resource, int mode, int flags, int *lockid);
int sync_unlock(const char *resource, int lockid);
#endif

View File

@ -1,932 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "clvmd-common.h"
#include <pthread.h>
#include "clvm.h"
#include "clvmd-comms.h"
#include "clvmd.h"
#include "lvm-functions.h"
/* LVM2 headers */
#include "toolcontext.h"
#include "lvmcache.h"
#include "lvm-globals.h"
#include "activate.h"
#include "archiver.h"
#include "memlock.h"
#include <syslog.h>
static struct cmd_context *cmd = NULL;
static struct dm_hash_table *lv_hash = NULL;
static pthread_mutex_t lv_hash_lock;
static pthread_mutex_t lvm_lock;
static char last_error[1024];
struct lv_info {
int lock_id;
int lock_mode;
};
static const char *decode_full_locking_cmd(uint32_t cmdl)
{
static char buf[128];
const char *type;
const char *scope;
const char *command;
switch (cmdl & LCK_TYPE_MASK) {
case LCK_NULL:
type = "NULL";
break;
case LCK_READ:
type = "READ";
break;
case LCK_PREAD:
type = "PREAD";
break;
case LCK_WRITE:
type = "WRITE";
break;
case LCK_EXCL:
type = "EXCL";
break;
case LCK_UNLOCK:
type = "UNLOCK";
break;
default:
type = "unknown";
break;
}
switch (cmdl & LCK_SCOPE_MASK) {
case LCK_VG:
scope = "VG";
command = "LCK_VG";
break;
case LCK_LV:
scope = "LV";
switch (cmdl & LCK_MASK) {
case LCK_LV_EXCLUSIVE & LCK_MASK:
command = "LCK_LV_EXCLUSIVE";
break;
case LCK_LV_SUSPEND & LCK_MASK:
command = "LCK_LV_SUSPEND";
break;
case LCK_LV_RESUME & LCK_MASK:
command = "LCK_LV_RESUME";
break;
case LCK_LV_ACTIVATE & LCK_MASK:
command = "LCK_LV_ACTIVATE";
break;
case LCK_LV_DEACTIVATE & LCK_MASK:
command = "LCK_LV_DEACTIVATE";
break;
default:
command = "unknown";
break;
}
break;
default:
scope = "unknown";
command = "unknown";
break;
}
sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope,
cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
cmdl & LCK_HOLD ? "|HOLD" : "",
cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
cmdl & LCK_CACHE ? "|CACHE" : "");
return buf;
}
/*
* Only processes 8 bits: excludes LCK_CACHE.
*/
static const char *decode_locking_cmd(unsigned char cmdl)
{
return decode_full_locking_cmd((uint32_t) cmdl);
}
static const char *decode_flags(unsigned char flags)
{
static char buf[128];
int len;
len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s%s)", flags,
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
flags & LCK_TEST_MODE ? "TEST|" : "",
flags & LCK_CONVERT ? "CONVERT|" : "",
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
flags & LCK_REVERT_MODE ? "REVERT|" : "");
if (len > 1)
buf[len - 2] = ' ';
else
buf[0] = '\0';
return buf;
}
char *get_last_lvm_error(void)
{
return last_error;
}
/*
* Hash lock info helpers
*/
static struct lv_info *lookup_info(const char *resource)
{
struct lv_info *lvi;
pthread_mutex_lock(&lv_hash_lock);
lvi = dm_hash_lookup(lv_hash, resource);
pthread_mutex_unlock(&lv_hash_lock);
return lvi;
}
static int insert_info(const char *resource, struct lv_info *lvi)
{
int ret;
pthread_mutex_lock(&lv_hash_lock);
ret = dm_hash_insert(lv_hash, resource, lvi);
pthread_mutex_unlock(&lv_hash_lock);
return ret;
}
static void remove_info(const char *resource)
{
int num_open;
pthread_mutex_lock(&lv_hash_lock);
dm_hash_remove(lv_hash, resource);
/* When last lock is remove, validate there are not left opened devices */
if (!dm_hash_get_first(lv_hash)) {
if (critical_section())
log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section.");
if ((num_open = dev_cache_check_for_open_devices()))
log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open);
}
pthread_mutex_unlock(&lv_hash_lock);
}
/*
* Return the mode a lock is currently held at (or -1 if not held)
*/
static int get_current_lock(char *resource)
{
struct lv_info *lvi;
if ((lvi = lookup_info(resource)))
return lvi->lock_mode;
return -1;
}
void init_lvhash(void)
{
/* Create hash table for keeping LV locks & status */
lv_hash = dm_hash_create(1024);
pthread_mutex_init(&lv_hash_lock, NULL);
pthread_mutex_init(&lvm_lock, NULL);
}
/* Called at shutdown to tidy the lockspace */
void destroy_lvhash(void)
{
struct dm_hash_node *v;
struct lv_info *lvi;
char *resource;
int status;
pthread_mutex_lock(&lv_hash_lock);
dm_hash_iterate(v, lv_hash) {
lvi = dm_hash_get_data(lv_hash, v);
resource = dm_hash_get_key(lv_hash, v);
if ((status = sync_unlock(resource, lvi->lock_id)))
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
status, strerror(errno));
dm_free(lvi);
}
dm_hash_destroy(lv_hash);
lv_hash = NULL;
pthread_mutex_unlock(&lv_hash_lock);
}
/* Gets a real lock and keeps the info in the hash table */
static int hold_lock(char *resource, int mode, int flags)
{
int status;
int saved_errno;
struct lv_info *lvi;
/* Mask off invalid options */
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
lvi = lookup_info(resource);
if (lvi) {
if (lvi->lock_mode == mode) {
DEBUGLOG("hold_lock, lock mode %d already held\n",
mode);
return 0;
}
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
"ignoring LCK_WRITE request\n");
return 0;
}
}
/* Only allow explicit conversions */
if (lvi && !(flags & LCKF_CONVERT)) {
errno = EBUSY;
return -1;
}
if (lvi) {
/* Already exists - convert it */
status = sync_lock(resource, mode, flags, &lvi->lock_id);
saved_errno = errno;
if (!status)
lvi->lock_mode = mode;
else
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
strerror(errno));
errno = saved_errno;
} else {
if (!(lvi = dm_malloc(sizeof(struct lv_info)))) {
errno = ENOMEM;
return -1;
}
lvi->lock_mode = mode;
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
saved_errno = errno;
if (status) {
dm_free(lvi);
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
strerror(errno));
} else
if (!insert_info(resource, lvi)) {
errno = ENOMEM;
return -1;
}
errno = saved_errno;
}
return status;
}
/* Unlock and remove it from the hash table */
static int hold_unlock(char *resource)
{
struct lv_info *lvi;
int status;
int saved_errno;
if (!(lvi = lookup_info(resource))) {
DEBUGLOG("hold_unlock, lock not already held\n");
return 0;
}
status = sync_unlock(resource, lvi->lock_id);
saved_errno = errno;
if (!status) {
remove_info(resource);
dm_free(lvi);
} else {
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
strerror(errno));
}
errno = saved_errno;
return status;
}
/* Watch the return codes here.
liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
libdlm API functions return 0 for success, -1 for failure and do set errno.
These functions here return 0 for success or >0 for failure (where the retcode is errno)
*/
/* Activate LV exclusive or non-exclusive */
static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode)
{
int oldmode;
int status;
int activate_lv;
int exclusive = 0;
struct lvinfo lvi;
/* Is it already open ? */
oldmode = get_current_lock(resource);
if (oldmode == mode && (command & LCK_CLUSTER_VG)) {
DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
return 0; /* Nothing to do */
}
/* Does the config file want us to activate this LV ? */
if (!lv_activation_filter(cmd, resource, &activate_lv, NULL))
return EIO;
if (!activate_lv)
return 0; /* Success, we did nothing! */
/* Do we need to activate exclusively? */
if ((activate_lv == 2) || (mode == LCK_EXCL)) {
exclusive = 1;
mode = LCK_EXCL;
}
/*
* Try to get the lock if it's a clustered volume group.
* Use lock conversion only if requested, to prevent implicit conversion
* of exclusive lock to shared one during activation.
*/
if (!test_mode() && command & LCK_CLUSTER_VG) {
status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
if (status) {
/* Return an LVM-sensible error for this.
* Forcing EIO makes the upper level return this text
* rather than the strerror text for EAGAIN.
*/
if (errno == EAGAIN) {
sprintf(last_error, "Volume is busy on another node");
errno = EIO;
}
return errno;
}
}
/* If it's suspended then resume it */
if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0))
goto error;
if (lvi.suspended) {
critical_section_inc(cmd, "resuming");
if (!lv_resume(cmd, resource, 0, NULL)) {
critical_section_dec(cmd, "resumed");
goto error;
}
}
/* Now activate it */
if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
goto error;
return 0;
error:
if (!test_mode() && (oldmode == -1 || oldmode != mode))
(void)hold_unlock(resource);
return EIO;
}
/* Resume the LV if it was active */
static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags)
{
int oldmode, origin_only, exclusive, revert;
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
DEBUGLOG("do_resume_lv, lock not already held\n");
return 0; /* We don't need to do anything */
}
origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert, NULL))
return EIO;
return 0;
}
/* Suspend the device if active */
static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags)
{
int oldmode;
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
unsigned exclusive;
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
DEBUGLOG("do_suspend_lv, lock not already held\n");
return 0; /* Not active, so it's OK */
}
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
/* Always call lv_suspend to read commited and precommited data */
if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive, NULL, NULL))
return EIO;
return 0;
}
static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags)
{
int oldmode;
int status;
/* Is it open ? */
oldmode = get_current_lock(resource);
if (oldmode == -1 && (command & LCK_CLUSTER_VG)) {
DEBUGLOG("do_deactivate_lock, lock not already held\n");
return 0; /* We don't need to do anything */
}
if (!lv_deactivate(cmd, resource, NULL))
return EIO;
if (!test_mode() && command & LCK_CLUSTER_VG) {
status = hold_unlock(resource);
if (status)
return errno;
}
return 0;
}
const char *do_lock_query(char *resource)
{
int mode;
const char *type;
mode = get_current_lock(resource);
switch (mode) {
case LCK_NULL: type = "NL"; break;
case LCK_READ: type = "CR"; break;
case LCK_PREAD:type = "PR"; break;
case LCK_WRITE:type = "PW"; break;
case LCK_EXCL: type = "EX"; break;
default: type = NULL;
}
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "--");
return type;
}
/* This is the LOCK_LV part that happens on all nodes in the cluster -
it is responsible for the interaction with device-mapper and LVM */
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
{
int status = 0;
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
if (!cmd->config_initialized || config_files_changed(cmd)) {
/* Reinitialise various settings inc. logging, filters */
if (do_refresh_cache()) {
log_error("Updated config file invalid. Aborting.");
return EINVAL;
}
}
pthread_mutex_lock(&lvm_lock);
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE)
init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
else {
if (lock_flags & LCK_DMEVENTD_MONITOR_MODE)
init_dmeventd_monitor(1);
else
init_dmeventd_monitor(0);
}
cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
/* clvmd should never try to read suspended device */
init_ignore_suspended_devices(1);
switch (command & LCK_MASK) {
case LCK_LV_EXCLUSIVE:
status = do_activate_lv(resource, command, lock_flags, LCK_EXCL);
break;
case LCK_LV_SUSPEND:
status = do_suspend_lv(resource, command, lock_flags);
break;
case LCK_UNLOCK:
case LCK_LV_RESUME: /* if active */
status = do_resume_lv(resource, command, lock_flags);
break;
case LCK_LV_ACTIVATE:
status = do_activate_lv(resource, command, lock_flags, LCK_READ);
break;
case LCK_LV_DEACTIVATE:
status = do_deactivate_lv(resource, command, lock_flags);
break;
default:
DEBUGLOG("Invalid LV command 0x%x\n", command);
status = EINVAL;
break;
}
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(0);
cmd->partial_activation = 0;
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
init_test(0);
pthread_mutex_unlock(&lvm_lock);
DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
return status;
}
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
{
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
lock out on this node (because we are the node modifying the metadata)
before suspending cluster-wide.
LCKF_CONVERT is used always, local node is going to modify metadata
*/
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
(command & LCK_CLUSTER_VG)) {
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
resource, decode_locking_cmd(command), decode_flags(lock_flags));
if (!(lock_flags & LCK_TEST_MODE) &&
hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
return errno;
}
return 0;
}
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
int post_lock_lv(unsigned char command, unsigned char lock_flags,
char *resource)
{
int status;
unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0;
/* Opposite of above, done on resume after a metadata update */
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
(command & LCK_CLUSTER_VG)) {
int oldmode;
DEBUGLOG("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
resource, decode_locking_cmd(command), decode_flags(lock_flags));
/* If the lock state is PW then restore it to what it was */
oldmode = get_current_lock(resource);
if (oldmode == LCK_WRITE) {
struct lvinfo lvi;
pthread_mutex_lock(&lvm_lock);
status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0);
pthread_mutex_unlock(&lvm_lock);
if (!status)
return EIO;
if (!(lock_flags & LCK_TEST_MODE)) {
if (lvi.exists) {
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
return errno;
} else if (hold_unlock(resource))
return errno;
}
}
}
return 0;
}
/* Check if a VG is in use by LVM1 so we don't stomp on it */
int do_check_lvm1(const char *vgname)
{
int status;
status = check_lvm1_vg_inactive(cmd, vgname);
return status == 1 ? 0 : EBUSY;
}
int do_refresh_cache(void)
{
DEBUGLOG("Refreshing context\n");
log_notice("Refreshing context");
pthread_mutex_lock(&lvm_lock);
if (!refresh_toolcontext(cmd)) {
pthread_mutex_unlock(&lvm_lock);
return -1;
}
init_full_scan_done(0);
init_ignore_suspended_devices(1);
lvmcache_label_scan(cmd, 2);
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
return 0;
}
/*
* Handle VG lock - drop metadata or update lvmcache state
*/
void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
{
uint32_t lock_cmd = command;
char *vgname = resource + 2;
lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
/*
* Check if LCK_CACHE should be set. All P_ locks except # are cache related.
*/
if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
lock_cmd |= LCK_CACHE;
DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section());
/* P_#global causes a full cache refresh */
if (!strcmp(resource, "P_" VG_GLOBAL)) {
do_refresh_cache();
return;
}
pthread_mutex_lock(&lvm_lock);
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
switch (lock_cmd) {
case LCK_VG_COMMIT:
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
lvmcache_commit_metadata(vgname);
break;
case LCK_VG_REVERT:
DEBUGLOG("vg_revert notification for VG %s\n", vgname);
lvmcache_drop_metadata(vgname, 1);
break;
case LCK_VG_DROP_CACHE:
default:
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
lvmcache_drop_metadata(vgname, 0);
}
init_test(0);
pthread_mutex_unlock(&lvm_lock);
}
/*
* Ideally, clvmd should be started before any LVs are active
* but this may not be the case...
* I suppose this also comes in handy if clvmd crashes, not that it would!
*/
static int get_initial_state(struct dm_hash_table *excl_uuid)
{
int lock_mode;
char lv[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */
char uuid[65];
char line[255];
char *lvs_cmd;
const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH;
FILE *lvs;
if (dm_asprintf(&lvs_cmd, "%s lvs --config 'log{command_names=0 prefix=\"\"}' "
"--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
lvm_binary) < 0)
return_0;
/* FIXME: Maybe link and use liblvm2cmd directly instead of fork */
if (!(lvs = popen(lvs_cmd, "r"))) {
dm_free(lvs_cmd);
return 0;
}
while (fgets(line, sizeof(line), lvs)) {
if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) {
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
if (strlen(vg) == 38 && /* is is a valid UUID ? */
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
vg_flags[5] == 'c') { /* is it clustered ? */
/* Convert hyphen-separated UUIDs into one */
memcpy(&uuid[0], &vg[0], 6);
memcpy(&uuid[6], &vg[7], 4);
memcpy(&uuid[10], &vg[12], 4);
memcpy(&uuid[14], &vg[17], 4);
memcpy(&uuid[18], &vg[22], 4);
memcpy(&uuid[22], &vg[27], 4);
memcpy(&uuid[26], &vg[32], 6);
memcpy(&uuid[32], &lv[0], 6);
memcpy(&uuid[38], &lv[7], 4);
memcpy(&uuid[42], &lv[12], 4);
memcpy(&uuid[46], &lv[17], 4);
memcpy(&uuid[50], &lv[22], 4);
memcpy(&uuid[54], &lv[27], 4);
memcpy(&uuid[58], &lv[32], 6);
uuid[64] = '\0';
/* Look for this lock in the list of EX locks
we were passed on the command-line */
lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ?
LCK_EXCL : LCK_READ;
DEBUGLOG("getting initial lock for %s\n", uuid);
if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE))
DEBUGLOG("Failed to hold lock %s\n", uuid);
}
}
}
if (pclose(lvs))
DEBUGLOG("lvs pclose failed: %s\n", strerror(errno));
dm_free(lvs_cmd);
return 1;
}
static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
const char *message)
{
/* Send messages to the normal LVM2 logging system too,
so we get debug output when it's asked for.
We need to NULL the function ptr otherwise it will just call
back into here! */
init_log_fn(NULL);
print_log(level, file, line, dm_errno, "%s", message);
init_log_fn(lvm2_log_fn);
/*
* Ignore non-error messages, but store the latest one for returning
* to the user.
*/
if (level != _LOG_ERR && level != _LOG_FATAL)
return;
strncpy(last_error, message, sizeof(last_error));
last_error[sizeof(last_error)-1] = '\0';
}
/* This checks some basic cluster-LVM configuration stuff */
static void check_config(void)
{
int locking_type;
locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
if (locking_type == 3) /* compiled-in cluster support */
return;
if (locking_type == 2) { /* External library, check name */
const char *libname;
libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL);
if (libname && strstr(libname, "liblvm2clusterlock.so"))
return;
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
return;
}
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
}
/* Backups up the LVM metadata if it's changed */
void lvm_do_backup(const char *vgname)
{
struct volume_group * vg;
int consistent = 0;
DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname);
pthread_mutex_lock(&lvm_lock);
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 1, &consistent);
if (vg && consistent)
check_current_backup(vg);
else
log_error("Error backing up metadata, can't find VG for group %s", vgname);
release_vg(vg);
dm_pool_empty(cmd->mem);
pthread_mutex_unlock(&lvm_lock);
}
struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name)
{
struct lv_info *lvi;
*name = NULL;
if (!v)
v = dm_hash_get_first(lv_hash);
do {
if (v) {
lvi = dm_hash_get_data(lv_hash, v);
DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode);
if (lvi->lock_mode == LCK_EXCL) {
*name = dm_hash_get_key(lv_hash, v);
}
v = dm_hash_get_next(lv_hash, v);
}
} while (v && !*name);
if (*name)
DEBUGLOG("returning EXclusive UUID %s\n", *name);
return v;
}
void lvm_do_fs_unlock(void)
{
pthread_mutex_lock(&lvm_lock);
DEBUGLOG("Syncing device names\n");
fs_unlock();
pthread_mutex_unlock(&lvm_lock);
}
/* Called to initialise the LVM context of the daemon */
int init_clvm(struct dm_hash_table *excl_uuid)
{
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
init_syslog(LOG_DAEMON);
openlog("clvmd", LOG_PID, LOG_DAEMON);
/* Initialise already held locks */
if (!get_initial_state(excl_uuid))
log_error("Cannot load initial lock states.");
if (!(cmd = create_toolcontext(1, NULL, 0, 1))) {
log_error("Failed to allocate command context");
return 0;
}
if (stored_errno()) {
destroy_toolcontext(cmd);
return 0;
}
cmd->cmd_line = "clvmd";
/* Check lvm.conf is setup for cluster-LVM */
check_config();
init_ignore_suspended_devices(1);
/* Trap log messages so we can pass them back to the user */
init_log_fn(lvm2_log_fn);
memlock_inc_daemon(cmd);
return 1;
}
void destroy_lvm(void)
{
if (cmd) {
memlock_dec_daemon(cmd);
destroy_toolcontext(cmd);
cmd = NULL;
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Functions in lvm-functions.c */
#ifndef _LVM_FUNCTIONS_H
#define _LVM_FUNCTIONS_H
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern const char *do_lock_query(char *resource);
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
char *resource);
extern int do_check_lvm1(const char *vgname);
extern int do_refresh_cache(void);
extern int init_clvm(struct dm_hash_table *excl_uuid);
extern void destroy_lvm(void);
extern void init_lvhash(void);
extern void destroy_lvhash(void);
extern void lvm_do_backup(const char *vgname);
extern char *get_last_lvm_error(void);
extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
char *resource);
extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name);
void lvm_do_fs_unlock(void);
#endif

View File

@ -1,382 +0,0 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* FIXME Remove duplicated functions from this file. */
/*
* Send a command to a running clvmd from the command-line
*/
#include "clvmd-common.h"
#include "clvm.h"
#include "refresh_clvmd.h"
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>
typedef struct lvm_response {
char node[255];
char *response;
int status;
int len;
} lvm_response_t;
/*
* This gets stuck at the start of memory we allocate so we
* can sanity-check it at deallocation time
*/
#define LVM_SIGNATURE 0x434C564D
static int _clvmd_sock = -1;
/* Open connection to the clvm daemon */
static int _open_local_sock(void)
{
int local_socket;
struct sockaddr_un sockaddr = { .sun_family = AF_UNIX };
if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) {
fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME);
return -1;
}
/* Open local socket */
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
return -1;
}
if (connect(local_socket,(struct sockaddr *) &sockaddr,
sizeof(sockaddr))) {
int saved_errno = errno;
fprintf(stderr, "connect() failed on local socket: %s\n",
strerror(errno));
if (close(local_socket))
return -1;
errno = saved_errno;
return -1;
}
return local_socket;
}
/* Send a request and return the status */
static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response)
{
char outbuf[PIPE_BUF];
struct clvm_header *outheader = (struct clvm_header *) outbuf;
int len;
unsigned off;
int buflen;
int err;
/* Send it to CLVMD */
rewrite:
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
if (err == -1 && errno == EINTR)
goto rewrite;
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
return 0;
}
if (no_response)
return 1;
/* Get the response */
reread:
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
if (errno == EINTR)
goto reread;
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
return 0;
}
if (len == 0) {
fprintf(stderr, "EOF reading CLVMD");
errno = ENOTCONN;
return 0;
}
/* Allocate buffer */
buflen = len + outheader->arglen;
*retbuf = dm_malloc(buflen);
if (!*retbuf) {
errno = ENOMEM;
return 0;
}
/* Copy the header */
memcpy(*retbuf, outbuf, len);
outheader = (struct clvm_header *) *retbuf;
/* Read the returned values */
off = 1; /* we've already read the first byte */
while (off <= outheader->arglen && len > 0) {
len = read(_clvmd_sock, outheader->args + off,
buflen - off - offsetof(struct clvm_header, args));
if (len > 0)
off += len;
}
/* Was it an error ? */
if (outheader->status != 0) {
errno = outheader->status;
/* Only return an error here if there are no node-specific
errors present in the message that might have more detail */
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
return 0;
}
}
return 1;
}
/* Build the structure header and parse-out wildcard node names */
static void _build_header(struct clvm_header *head, int cmd, const char *node,
unsigned int len)
{
head->cmd = cmd;
head->status = 0;
head->flags = 0;
head->xid = 0;
head->clientid = 0;
if (len)
/* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */
head->arglen = len - 1;
else {
head->arglen = 0;
*head->args = '\0';
}
/*
* Translate special node names.
*/
if (!node || !strcmp(node, NODE_ALL))
head->node[0] = '\0';
else if (!strcmp(node, NODE_LOCAL)) {
head->node[0] = '\0';
head->flags = CLVMD_FLAG_LOCAL;
} else
strcpy(head->node, node);
}
/*
* Send a message to a(or all) node(s) in the cluster and wait for replies
*/
static int _cluster_request(char cmd, const char *node, void *data, int len,
lvm_response_t ** response, int *num, int no_response)
{
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
char *inptr;
char *retbuf = NULL;
int status;
int i;
int num_responses = 0;
struct clvm_header *head = (struct clvm_header *) outbuf;
lvm_response_t *rarray;
*num = 0;
if (_clvmd_sock == -1)
_clvmd_sock = _open_local_sock();
if (_clvmd_sock == -1)
return 0;
_build_header(head, cmd, node, len);
if (len)
memcpy(head->node + strlen(head->node) + 1, data, len);
status = _send_request(outbuf, sizeof(struct clvm_header) +
strlen(head->node) + len, &retbuf, no_response);
if (!status || no_response)
goto out;
/* Count the number of responses we got */
head = (struct clvm_header *) retbuf;
inptr = head->args;
while (inptr[0]) {
num_responses++;
inptr += strlen(inptr) + 1;
inptr += sizeof(int);
inptr += strlen(inptr) + 1;
}
/*
* Allocate response array.
* With an extra pair of INTs on the front to sanity
* check the pointer when we are given it back to free
*/
*response = NULL;
if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses +
sizeof(int) * 2))) {
errno = ENOMEM;
status = 0;
goto out;
}
/* Unpack the response into an lvm_response_t array */
inptr = head->args;
i = 0;
while (inptr[0]) {
strcpy(rarray[i].node, inptr);
inptr += strlen(inptr) + 1;
memcpy(&rarray[i].status, inptr, sizeof(int));
inptr += sizeof(int);
rarray[i].response = dm_malloc(strlen(inptr) + 1);
if (rarray[i].response == NULL) {
/* Free up everything else and return error */
int j;
for (j = 0; j < i; j++)
dm_free(rarray[i].response);
dm_free(rarray);
errno = ENOMEM;
status = 0;
goto out;
}
strcpy(rarray[i].response, inptr);
rarray[i].len = strlen(inptr);
inptr += strlen(inptr) + 1;
i++;
}
*num = num_responses;
*response = rarray;
out:
dm_free(retbuf);
return status;
}
/* Free reply array */
static int _cluster_free_request(lvm_response_t * response, int num)
{
int i;
for (i = 0; i < num; i++) {
dm_free(response[i].response);
}
dm_free(response);
return 1;
}
int refresh_clvmd(int all_nodes)
{
int num_responses;
char args[1]; // No args really.
lvm_response_t *response = NULL;
int saved_errno;
int status;
int i;
status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0);
/* If any nodes were down then display them and return an error */
for (i = 0; i < num_responses; i++) {
if (response[i].status == EHOSTDOWN) {
fprintf(stderr, "clvmd not running on node %s",
response[i].node);
status = 0;
errno = response[i].status;
} else if (response[i].status) {
fprintf(stderr, "Error resetting node %s: %s",
response[i].node,
response[i].response[0] ?
response[i].response :
strerror(response[i].status));
status = 0;
errno = response[i].status;
}
}
saved_errno = errno;
_cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
}
int restart_clvmd(int all_nodes)
{
int dummy, status;
status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1);
/*
* FIXME: we cannot receive response, clvmd re-exec before it.
* but also should not close socket too early (the whole rq is dropped then).
* FIXME: This should be handled this way:
* - client waits for RESTART ack (and socket close)
* - server restarts
* - client checks that server is ready again (VERSION command?)
*/
usleep(500000);
return status;
}
int debug_clvmd(int level, int clusterwide)
{
int num_responses;
char args[1];
const char *nodes;
lvm_response_t *response = NULL;
int saved_errno;
int status;
int i;
args[0] = level;
if (clusterwide)
nodes = NODE_ALL;
else
nodes = NODE_LOCAL;
status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0);
/* If any nodes were down then display them and return an error */
for (i = 0; i < num_responses; i++) {
if (response[i].status == EHOSTDOWN) {
fprintf(stderr, "clvmd not running on node %s",
response[i].node);
status = 0;
errno = response[i].status;
} else if (response[i].status) {
fprintf(stderr, "Error setting debug on node %s: %s",
response[i].node,
response[i].response[0] ?
response[i].response :
strerror(response[i].status));
status = 0;
errno = response[i].status;
}
}
saved_errno = errno;
_cluster_free_request(response, num_responses);
errno = saved_errno;
return status;
}

View File

@ -1,19 +0,0 @@
/*
* Copyright (C) 2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
int refresh_clvmd(int all_nodes);
int restart_clvmd(int all_nodes);
int debug_clvmd(int level, int clusterwide);

View File

@ -1,39 +0,0 @@
#
# Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CPG_LIBS = @CPG_LIBS@
CPG_CFLAGS = @CPG_CFLAGS@
SACKPT_LIBS = @SACKPT_LIBS@
SACKPT_CFLAGS = @SACKPT_CFLAGS@
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
TARGETS = cmirrord
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LVMLIBS) $(LMLIBS) $(LIBS)
install: $(TARGETS)
$(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord

View File

@ -1,256 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "logging.h"
#include "common.h"
#include "functions.h"
#include "link_mon.h"
#include "local.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
static volatile sig_atomic_t exit_now = 0;
/* FIXME Review signal handling. Should be volatile sig_atomic_t */
static sigset_t signal_mask;
static volatile sig_atomic_t signal_received;
static void process_signals(void);
static void daemonize(void);
static void init_all(void);
static void cleanup_all(void);
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
{
daemonize();
init_all();
/* Parent can now exit, we're ready to handle requests */
kill(getppid(), SIGTERM);
LOG_PRINT("Starting cmirrord:");
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
LOG_DBG(" Compiled with debugging.");
while (!exit_now) {
links_monitor();
links_issue_callbacks();
process_signals();
}
exit(EXIT_SUCCESS);
}
/*
* parent_exit_handler: exit the parent
* @sig: the signal
*
*/
static void parent_exit_handler(int sig __attribute__((unused)))
{
exit_now = 1;
}
static void sig_handler(int sig)
{
/* FIXME Races - don't touch signal_mask here. */
sigaddset(&signal_mask, sig);
signal_received = 1;
}
static void process_signal(int sig){
int r = 0;
switch(sig) {
case SIGINT:
case SIGQUIT:
case SIGTERM:
case SIGHUP:
r += log_status();
break;
case SIGUSR1:
case SIGUSR2:
log_debug();
/*local_debug();*/
cluster_debug();
return;
default:
LOG_PRINT("Unknown signal received... ignoring");
return;
}
if (!r) {
LOG_DBG("No current cluster logs... safe to exit.");
cleanup_all();
exit(EXIT_SUCCESS);
}
LOG_ERROR("Cluster logs exist. Refusing to exit.");
}
static void process_signals(void)
{
int x;
if (!signal_received)
return;
signal_received = 0;
for (x = 1; x < _NSIG; x++) {
if (sigismember(&signal_mask, x)) {
sigdelset(&signal_mask, x);
process_signal(x);
}
}
}
static void remove_lockfile(void)
{
if (unlink(CMIRRORD_PIDFILE))
LOG_ERROR("Unable to remove \"" CMIRRORD_PIDFILE "\" %s", strerror(errno));
}
/*
* daemonize
*
* Performs the steps necessary to become a daemon.
*/
static void daemonize(void)
{
int pid;
int status;
int devnull;
if ((devnull = open("/dev/null", O_RDWR)) == -1) {
LOG_ERROR("Can't open /dev/null: %s", strerror(errno));
exit(EXIT_FAILURE);
}
signal(SIGTERM, &parent_exit_handler);
pid = fork();
if (pid < 0) {
LOG_ERROR("Unable to fork()");
exit(EXIT_FAILURE);
}
if (pid) {
/* Parent waits here for child to get going */
while (!waitpid(pid, &status, WNOHANG) && !exit_now);
if (exit_now)
exit(EXIT_SUCCESS);
switch (WEXITSTATUS(status)) {
case EXIT_LOCKFILE:
LOG_ERROR("Failed to create lockfile");
LOG_ERROR("Process already running?");
break;
case EXIT_KERNEL_SOCKET:
LOG_ERROR("Unable to create netlink socket");
break;
case EXIT_KERNEL_BIND:
LOG_ERROR("Unable to bind to netlink socket");
break;
case EXIT_KERNEL_SETSOCKOPT:
LOG_ERROR("Unable to setsockopt on netlink socket");
break;
case EXIT_CLUSTER_CKPT_INIT:
LOG_ERROR("Unable to initialize checkpoint service");
LOG_ERROR("Has the cluster infrastructure been started?");
break;
case EXIT_FAILURE:
LOG_ERROR("Failed to start: Generic error");
break;
default:
LOG_ERROR("Failed to start: Unknown error");
break;
}
exit(EXIT_FAILURE);
}
setsid();
if (chdir("/")) {
LOG_ERROR("Failed to chdir /: %s", strerror(errno));
exit(EXIT_FAILURE);
}
umask(0);
if (close(0) || close(1) || close(2)) {
LOG_ERROR("Failed to close terminal FDs");
exit(EXIT_FAILURE);
}
if ((dup2(devnull, 0) < 0) || /* reopen stdin */
(dup2(devnull, 1) < 0) || /* reopen stdout */
(dup2(devnull, 2) < 0)) /* reopen stderr */
exit(EXIT_FAILURE);
if ((devnull > STDERR_FILENO) && close(devnull)) {
LOG_ERROR("Failed to close descriptor %d: %s",
devnull, strerror(errno));
exit(EXIT_FAILURE);
}
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
exit(EXIT_LOCKFILE);
(void) dm_prepare_selinux_context(NULL, 0);
atexit(remove_lockfile);
/* FIXME Replace with sigaction. (deprecated) */
signal(SIGINT, &sig_handler);
signal(SIGQUIT, &sig_handler);
signal(SIGTERM, &sig_handler);
signal(SIGHUP, &sig_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1, &sig_handler);
signal(SIGUSR2, &sig_handler);
sigemptyset(&signal_mask);
signal_received = 0;
}
/*
* init_all
*
* Initialize modules. Exit on failure.
*/
static void init_all(void)
{
int r;
if ((r = init_local()) ||
(r = init_cluster())) {
exit(r);
}
}
/*
* cleanup_all
*
* Clean up before exiting
*/
static void cleanup_all(void)
{
cleanup_local();
cleanup_cluster();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_CLUSTER_H
#define _LVM_CLOG_CLUSTER_H
#include "dm-log-userspace.h"
#include "libdevmapper.h"
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
#define DM_ULOG_CHECKPOINT_READY 21
#define DM_ULOG_MEMBER_JOIN 22
/*
* There is other information in addition to what can
* be found in the dm_ulog_request structure that we
* need for processing. 'clog_request' is the wrapping
* structure we use to make the additional fields
* available.
*/
struct clog_request {
/*
* If we don't use a union, the structure size will
* vary between 32-bit and 64-bit machines. So, we
* pack two 64-bit version numbers in there to force
* the size of the structure to be the same.
*
* The two version numbers also help us with endian
* issues. The first is always little endian, while
* the second is in native format of the sending
* machine. If the two are equal, there is no need
* to do endian conversions.
*/
union {
uint64_t version[2]; /* LE version and native version */
struct dm_list list;
} u;
/*
* 'originator' is the machine from which the requests
* was made.
*/
uint32_t originator;
/*
* 'pit_server' is the "point-in-time" server for the
* request. (I.e. The machine that was the server at
* the time the request was issued - only important during
* startup.
*/
uint32_t pit_server;
/*
* The request from the kernel that is being processed
*/
struct dm_ulog_request u_rq;
};
int init_cluster(void);
void cleanup_cluster(void);
void cluster_debug(void);
int create_cluster_cpg(char *uuid, uint64_t luid);
int destroy_cluster_cpg(char *uuid);
int cluster_send(struct clog_request *rq);
#endif /* _LVM_CLOG_CLUSTER_H */

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_COMMON_H
#define _LVM_CLOG_COMMON_H
/*
* If there are problems when forking off to become a daemon,
* the child will exist with one of these codes. This allows
* the parent to know the reason for the failure and print it
* to the launching terminal.
*
* #define EXIT_SUCCESS 0 (from stdlib.h)
* #define EXIT_FAILURE 1 (from stdlib.h)
*/
#define EXIT_LOCKFILE 2
#define EXIT_KERNEL_SOCKET 3 /* Failed netlink socket create */
#define EXIT_KERNEL_BIND 4
#define EXIT_KERNEL_SETSOCKOPT 5
#define EXIT_CLUSTER_CKPT_INIT 6 /* Failed to init checkpoint */
#define EXIT_QUEUE_NOMEM 7
#define DM_ULOG_REQUEST_SIZE 1024
#endif /* _LVM_CLOG_COMMON_H */

View File

@ -1,211 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*/
#include "logging.h"
#include "cluster.h"
#include "compat.h"
#include "xlate.h"
#include <errno.h>
/*
* Older versions of the log daemon communicate with different
* versions of the inter-machine communication structure, which
* varies in size and fields. The older versions append the
* standard upstream version of the structure to every request.
* COMPAT_OFFSET is where the upstream structure starts.
*/
#define COMPAT_OFFSET 256
static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute__((unused)))
{
int i, end;
int64_t *pi64;
uint64_t *pu64;
uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
switch (rq_type) {
case DM_ULOG_CTR:
case DM_ULOG_DTR:
LOG_ERROR("Invalid response type in endian switch");
exit(EXIT_FAILURE);
case DM_ULOG_PRESUSPEND:
case DM_ULOG_POSTSUSPEND:
case DM_ULOG_RESUME:
case DM_ULOG_FLUSH:
case DM_ULOG_MARK_REGION:
case DM_ULOG_CLEAR_REGION:
case DM_ULOG_SET_REGION_SYNC:
case DM_ULOG_CHECKPOINT_READY:
case DM_ULOG_MEMBER_JOIN:
case DM_ULOG_STATUS_INFO:
case DM_ULOG_STATUS_TABLE:
/* No outbound data */
break;
case DM_ULOG_GET_REGION_SIZE:
case DM_ULOG_GET_SYNC_COUNT:
pu64 = (uint64_t *)rq->u_rq.data;
*pu64 = xlate64(*pu64);
break;
case DM_ULOG_IS_CLEAN:
case DM_ULOG_IN_SYNC:
pi64 = (int64_t *)rq->u_rq.data;
*pi64 = xlate64(*pi64);
break;
case DM_ULOG_GET_RESYNC_WORK:
case DM_ULOG_IS_REMOTE_RECOVERING:
pi64 = (int64_t *)rq->u_rq.data;
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
*pi64 = xlate64(*pi64);
*pu64 = xlate64(*pu64);
break;
default:
LOG_ERROR("Unknown request type, %u", rq_type);
return;
}
} else {
switch (rq_type) {
case DM_ULOG_CTR:
case DM_ULOG_DTR:
LOG_ERROR("Invalid request type in endian switch");
exit(EXIT_FAILURE);
case DM_ULOG_PRESUSPEND:
case DM_ULOG_POSTSUSPEND:
case DM_ULOG_RESUME:
case DM_ULOG_GET_REGION_SIZE:
case DM_ULOG_FLUSH:
case DM_ULOG_GET_RESYNC_WORK:
case DM_ULOG_GET_SYNC_COUNT:
case DM_ULOG_STATUS_INFO:
case DM_ULOG_STATUS_TABLE:
case DM_ULOG_CHECKPOINT_READY:
case DM_ULOG_MEMBER_JOIN:
/* No incoming data */
break;
case DM_ULOG_IS_CLEAN:
case DM_ULOG_IN_SYNC:
case DM_ULOG_IS_REMOTE_RECOVERING:
pu64 = (uint64_t *)rq->u_rq.data;
*pu64 = xlate64(*pu64);
break;
case DM_ULOG_MARK_REGION:
case DM_ULOG_CLEAR_REGION:
end = rq->u_rq.data_size/sizeof(uint64_t);
pu64 = (uint64_t *)rq->u_rq.data;
for (i = 0; i < end; i++)
pu64[i] = xlate64(pu64[i]);
break;
case DM_ULOG_SET_REGION_SYNC:
pu64 = (uint64_t *)rq->u_rq.data;
pi64 = ((int64_t *)rq->u_rq.data) + 1;
*pu64 = xlate64(*pu64);
*pi64 = xlate64(*pi64);
break;
default:
LOG_ERROR("Unknown request type, %u", rq_type);
exit(EXIT_FAILURE);
}
}
}
static int v5_endian_to_network(struct clog_request *rq)
{
int size;
struct dm_ulog_request *u_rq = &rq->u_rq;
size = sizeof(*rq) + u_rq->data_size;
u_rq->error = xlate32(u_rq->error);
u_rq->seq = xlate32(u_rq->seq);
rq->originator = xlate32(rq->originator);
v5_data_endian_switch(rq, 1);
u_rq->request_type = xlate32(u_rq->request_type);
u_rq->data_size = xlate32(u_rq->data_size);
return size;
}
int clog_request_to_network(struct clog_request *rq)
{
int r;
/* FIXME: Remove this safety check */
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
LOG_ERROR("Programmer error: version[0] must be LE");
exit(EXIT_FAILURE);
}
/*
* Are we already running in the endian mode we send
* over the wire?
*/
if (rq->u.version[0] == rq->u.version[1])
return 0;
r = v5_endian_to_network(rq);
if (r < 0)
return r;
return 0;
}
static int v5_endian_from_network(struct clog_request *rq)
{
int size;
struct dm_ulog_request *u_rq = &rq->u_rq;
u_rq->error = xlate32(u_rq->error);
u_rq->seq = xlate32(u_rq->seq);
u_rq->request_type = xlate32(u_rq->request_type);
u_rq->data_size = xlate32(u_rq->data_size);
rq->originator = xlate32(rq->originator);
size = sizeof(*rq) + u_rq->data_size;
v5_data_endian_switch(rq, 0);
return size;
}
int clog_request_from_network(void *data, size_t data_len)
{
uint64_t *vp = data;
uint64_t version = xlate64(vp[0]);
uint64_t unconverted_version = vp[1];
struct clog_request *rq = data;
switch (version) {
case 5: /* Upstream */
if (version == vp[0])
return 0;
break;
case 4: /* RHEL 5.[45] */
case 3: /* RHEL 5.3 */
case 2: /* RHEL 5.2 */
/* FIXME: still need to account for payload */
if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
return -ENOSPC;
rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
break;
default:
LOG_ERROR("Unable to process cluster message: "
"Incompatible version");
return -EINVAL;
}
v5_endian_from_network(rq);
return 0;
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*/
#ifndef _LVM_CLOG_COMPAT_H
#define _LVM_CLOG_COMPAT_H
/*
* The intermachine communication structure version are:
* 0: Unused
* 1: Never in the wild
* 2: RHEL 5.2
* 3: RHEL 5.3
* 4: RHEL 5.4, RHEL 5.5
* 5: RHEL 6, Current Upstream Format
*/
#define CLOG_TFR_VERSION 5
int clog_request_to_network(struct clog_request *rq);
int clog_request_from_network(void *data, size_t data_len);
#endif /* _LVM_CLOG_COMPAT_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_FUNCTIONS_H
#define _LVM_CLOG_FUNCTIONS_H
#include "dm-log-userspace.h"
#include "cluster.h"
#define LOG_RESUMED 1
#define LOG_SUSPENDED 2
int local_resume(struct dm_ulog_request *rq);
int cluster_postsuspend(char *, uint64_t);
int do_request(struct clog_request *rq, int server);
int push_state(const char *uuid, uint64_t luid,
const char *which, char **buf, uint32_t debug_who);
int pull_state(const char *uuid, uint64_t luid,
const char *which, char *buf, int size);
int log_get_state(struct dm_ulog_request *rq);
int log_status(void);
void log_debug(void);
#endif /* _LVM_CLOG_FUNCTIONS_H */

View File

@ -1,151 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "logging.h"
#include "link_mon.h"
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
struct link_callback {
int fd;
const char *name;
void *data;
int (*callback)(void *data);
struct link_callback *next;
};
static unsigned used_pfds = 0;
static unsigned free_pfds = 0;
static struct pollfd *pfds = NULL;
static struct link_callback *callbacks = NULL;
int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
{
unsigned i;
struct link_callback *lc;
for (i = 0; i < used_pfds; i++) {
if (fd == pfds[i].fd) {
LOG_ERROR("links_register: Duplicate file descriptor");
return -EINVAL;
}
}
lc = malloc(sizeof(*lc));
if (!lc)
return -ENOMEM;
lc->fd = fd;
lc->name = name;
lc->data = data;
lc->callback = callback;
if (!free_pfds) {
struct pollfd *tmp;
tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
if (!tmp) {
free(lc);
return -ENOMEM;
}
pfds = tmp;
free_pfds = used_pfds + 1;
}
free_pfds--;
pfds[used_pfds].fd = fd;
pfds[used_pfds].events = POLLIN;
pfds[used_pfds].revents = 0;
used_pfds++;
lc->next = callbacks;
callbacks = lc;
LOG_DBG("Adding %s/%d", lc->name, lc->fd);
LOG_DBG(" used_pfds = %u, free_pfds = %u",
used_pfds, free_pfds);
return 0;
}
int links_unregister(int fd)
{
unsigned i;
struct link_callback *p, *c;
for (i = 0; i < used_pfds; i++)
if (fd == pfds[i].fd) {
/* entire struct is copied (overwritten) */
pfds[i] = pfds[used_pfds - 1];
used_pfds--;
free_pfds++;
}
for (p = NULL, c = callbacks; c; p = c, c = c->next)
if (fd == c->fd) {
LOG_DBG("Freeing up %s/%d", c->name, c->fd);
LOG_DBG(" used_pfds = %u, free_pfds = %u",
used_pfds, free_pfds);
if (p)
p->next = c->next;
else
callbacks = c->next;
free(c);
break;
}
return 0;
}
int links_monitor(void)
{
unsigned i;
int r;
for (i = 0; i < used_pfds; i++) {
pfds[i].revents = 0;
}
r = poll(pfds, used_pfds, -1);
if (r <= 0)
return r;
r = 0;
/* FIXME: handle POLLHUP */
for (i = 0; i < used_pfds; i++)
if (pfds[i].revents & POLLIN) {
LOG_DBG("Data ready on %d", pfds[i].fd);
/* FIXME: Add this back return 1;*/
r++;
}
return r;
}
int links_issue_callbacks(void)
{
unsigned i;
struct link_callback *lc;
for (i = 0; i < used_pfds; i++)
if (pfds[i].revents & POLLIN)
for (lc = callbacks; lc; lc = lc->next)
if (pfds[i].fd == lc->fd) {
LOG_DBG("Issuing callback on %s/%d",
lc->name, lc->fd);
lc->callback(lc->data);
break;
}
return 0;
}

View File

@ -1,20 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_LINK_MON_H
#define _LVM_CLOG_LINK_MON_H
int links_register(int fd, const char *name, int (*callback)(void *data), void *data);
int links_unregister(int fd);
int links_monitor(void);
int links_issue_callbacks(void);
#endif /* _LVM_CLOG_LINK_MON_H */

View File

@ -1,424 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "logging.h"
#include "common.h"
#include "functions.h"
#include "link_mon.h"
#include "local.h"
#include <errno.h>
#include <sys/socket.h>
#include <linux/connector.h>
#include <linux/netlink.h>
#include <unistd.h>
#ifndef CN_IDX_DM
/* Kernel 2.6.31 is required to run this code */
#define CN_IDX_DM 0x7 /* Device Mapper */
#define CN_VAL_DM_USERSPACE_LOG 0x1
#endif
static int cn_fd = -1; /* Connector (netlink) socket fd */
static char recv_buf[2048];
static char send_buf[2048];
/* FIXME: merge this function with kernel_send_helper */
static int kernel_ack(uint32_t seq, int error)
{
int r;
struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
struct cn_msg *msg = NLMSG_DATA(nlh);
if (error < 0) {
LOG_ERROR("Programmer error: error codes must be positive");
return -EINVAL;
}
memset(send_buf, 0, sizeof(send_buf));
nlh->nlmsg_seq = 0;
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
nlh->nlmsg_flags = 0;
msg->len = 0;
msg->id.idx = CN_IDX_DM;
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
msg->seq = seq;
msg->ack = error;
r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
/* FIXME: do better error processing */
if (r <= 0)
return -EBADE;
return 0;
}
/*
* kernel_recv
* @rq: the newly allocated request from kernel
*
* Read requests from the kernel and allocate space for the new request.
* If there is no request from the kernel, *rq is NULL.
*
* This function is not thread safe due to returned stack pointer. In fact,
* the returned pointer must not be in-use when this function is called again.
*
* Returns: 0 on success, -EXXX on error
*/
static int kernel_recv(struct clog_request **rq)
{
int r = 0;
ssize_t len;
char *foo;
struct cn_msg *msg;
struct dm_ulog_request *u_rq;
struct nlmsghdr *nlmsg_h;
*rq = NULL;
memset(recv_buf, 0, sizeof(recv_buf));
len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
if (len < 0) {
LOG_ERROR("Failed to recv message from kernel");
r = -errno;
goto fail;
}
nlmsg_h = (struct nlmsghdr *)recv_buf;
switch (nlmsg_h->nlmsg_type) {
case NLMSG_ERROR:
LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
r = -EBADE;
goto fail;
case NLMSG_DONE:
msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
len -= (ssize_t)sizeof(struct nlmsghdr);
if (len < (ssize_t)sizeof(struct cn_msg)) {
LOG_ERROR("Incomplete request from kernel received");
r = -EBADE;
goto fail;
}
if (msg->len > DM_ULOG_REQUEST_SIZE) {
LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
msg->len, DM_ULOG_REQUEST_SIZE);
r = -EBADE;
goto fail;
}
if (!msg->len)
LOG_ERROR("Zero length message received");
len -= (ssize_t)sizeof(struct cn_msg);
if (len < msg->len)
LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
u_rq = (struct dm_ulog_request *)msg->data;
if (!u_rq->request_type) {
LOG_DBG("Bad transmission, requesting resend [%u]",
msg->seq);
r = -EAGAIN;
if (kernel_ack(msg->seq, EAGAIN)) {
LOG_ERROR("Failed to NACK kernel transmission [%u]",
msg->seq);
r = -EBADE;
}
}
/*
* Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
* worth of space that precede the request structure from the
* kernel. Since that space isn't going to be used again, we
* can take it for our purposes; rather than allocating a whole
* new structure and doing a memcpy.
*
* We should really make sure 'clog_request' doesn't grow
* beyond what is available to us, but we need only check it
* once... perhaps at compile time?
*/
foo = (char *)u_rq;
foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
*rq = (struct clog_request *) foo;
/* Clear the wrapper container fields */
memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
break;
default:
LOG_ERROR("Unknown nlmsg_type");
r = -EBADE;
}
fail:
if (r)
*rq = NULL;
return (r == -EAGAIN) ? 0 : r;
}
static int kernel_send_helper(void *data, uint16_t out_size)
{
int r;
struct nlmsghdr *nlh;
struct cn_msg *msg;
memset(send_buf, 0, sizeof(send_buf));
nlh = (struct nlmsghdr *)send_buf;
nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
nlh->nlmsg_pid = getpid();
nlh->nlmsg_type = NLMSG_DONE;
nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
nlh->nlmsg_flags = 0;
msg = NLMSG_DATA(nlh);
memcpy(msg->data, data, out_size);
msg->len = out_size;
msg->id.idx = CN_IDX_DM;
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
msg->seq = 0;
r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
/* FIXME: do better error processing */
if (r <= 0)
return -EBADE;
return 0;
}
/*
* do_local_work
*
* Any processing errors are placed in the 'rq'
* structure to be reported back to the kernel.
* It may be pointless for this function to
* return an int.
*
* Returns: 0 on success, -EXXX on failure
*/
static int do_local_work(void *data __attribute__((unused)))
{
int r;
struct clog_request *rq;
struct dm_ulog_request *u_rq = NULL;
r = kernel_recv(&rq);
if (r)
return r;
if (!rq)
return 0;
u_rq = &rq->u_rq;
LOG_DBG("[%s] Request from kernel received: [%s/%u]",
SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
u_rq->seq);
switch (u_rq->request_type) {
case DM_ULOG_CTR:
case DM_ULOG_DTR:
case DM_ULOG_GET_REGION_SIZE:
case DM_ULOG_IN_SYNC:
case DM_ULOG_GET_SYNC_COUNT:
case DM_ULOG_STATUS_TABLE:
case DM_ULOG_PRESUSPEND:
/* We do not specify ourselves as server here */
r = do_request(rq, 0);
if (r)
LOG_DBG("Returning failed request to kernel [%s]",
RQ_TYPE(u_rq->request_type));
r = kernel_send(u_rq);
if (r)
LOG_ERROR("Failed to respond to kernel [%s]",
RQ_TYPE(u_rq->request_type));
break;
case DM_ULOG_RESUME:
/*
* Resume is a special case that requires a local
* component to join the CPG, and a cluster component
* to handle the request.
*/
r = local_resume(u_rq);
if (r) {
LOG_DBG("Returning failed request to kernel [%s]",
RQ_TYPE(u_rq->request_type));
r = kernel_send(u_rq);
if (r)
LOG_ERROR("Failed to respond to kernel [%s]",
RQ_TYPE(u_rq->request_type));
break;
}
/* ELSE, fall through */
case DM_ULOG_IS_CLEAN:
case DM_ULOG_FLUSH:
case DM_ULOG_MARK_REGION:
case DM_ULOG_GET_RESYNC_WORK:
case DM_ULOG_SET_REGION_SYNC:
case DM_ULOG_STATUS_INFO:
case DM_ULOG_IS_REMOTE_RECOVERING:
case DM_ULOG_POSTSUSPEND:
r = cluster_send(rq);
if (r) {
u_rq->data_size = 0;
u_rq->error = r;
if (kernel_send(u_rq))
LOG_ERROR("Failed to respond to kernel [%s]",
RQ_TYPE(u_rq->request_type));
}
break;
case DM_ULOG_CLEAR_REGION:
r = kernel_ack(u_rq->seq, 0);
r = cluster_send(rq);
if (r) {
/*
* FIXME: store error for delivery on flush
* This would allow us to optimize MARK_REGION
* too.
*/
}
break;
default:
LOG_ERROR("Invalid log request received (%u), ignoring.",
u_rq->request_type);
return 0;
}
if (r && !u_rq->error)
u_rq->error = r;
return r;
}
/*
* kernel_send
* @u_rq: result to pass back to kernel
*
* This function returns the u_rq structure
* (containing the results) to the kernel.
* It then frees the structure.
*
* WARNING: should the structure be freed if
* there is an error? I vote 'yes'. If the
* kernel doesn't get the response, it should
* resend the request.
*
* Returns: 0 on success, -EXXX on failure
*/
int kernel_send(struct dm_ulog_request *u_rq)
{
int r;
uint16_t size;
if (!u_rq)
return -EINVAL;
size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
if (!u_rq->data_size && !u_rq->error) {
/* An ACK is all that is needed */
/* FIXME: add ACK code */
} else if (size > DM_ULOG_REQUEST_SIZE) {
/*
* If we gotten here, we've already overrun
* our allotted space somewhere.
*
* We must do something, because the kernel
* is waiting for a response.
*/
LOG_ERROR("Not enough space to respond to server");
u_rq->error = -ENOSPC;
size = sizeof(struct dm_ulog_request);
}
r = kernel_send_helper(u_rq, size);
if (r)
LOG_ERROR("Failed to send msg to kernel.");
return r;
}
/*
* init_local
*
* Initialize kernel communication socket (netlink)
*
* Returns: 0 on success, values from common.h on failure
*/
int init_local(void)
{
int r = 0;
unsigned opt;
struct sockaddr_nl addr;
cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
if (cn_fd < 0)
return EXIT_KERNEL_SOCKET;
/* memset to fix valgrind complaint */
memset(&addr, 0, sizeof(struct sockaddr_nl));
addr.nl_family = AF_NETLINK;
addr.nl_groups = CN_IDX_DM;
addr.nl_pid = 0;
r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
if (r < 0) {
if (close(cn_fd))
LOG_ERROR("Failed to close socket: %s",
strerror(errno));
return EXIT_KERNEL_BIND;
}
opt = addr.nl_groups;
r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
if (r) {
if (close(cn_fd))
LOG_ERROR("Failed to close socket: %s",
strerror(errno));
return EXIT_KERNEL_SETSOCKOPT;
}
/*
r = fcntl(cn_fd, F_SETFL, FNDELAY);
*/
links_register(cn_fd, "local", do_local_work, NULL);
return 0;
}
/*
* cleanup_local
*
* Clean up before exiting
*/
void cleanup_local(void)
{
links_unregister(cn_fd);
if (cn_fd >= 0 && close(cn_fd))
LOG_ERROR("Failed to close socket: %s",
strerror(errno));
}

View File

@ -1,20 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_LOCAL_H
#define _LVM_CLOG_LOCAL_H
int init_local(void);
void cleanup_local(void);
int kernel_send(struct dm_ulog_request *rq);
#endif /* _LVM_CLOG_LOCAL_H */

View File

@ -1,57 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "logging.h"
const char *__rq_types_off_by_one[] = {
"DM_ULOG_CTR",
"DM_ULOG_DTR",
"DM_ULOG_PRESUSPEND",
"DM_ULOG_POSTSUSPEND",
"DM_ULOG_RESUME",
"DM_ULOG_GET_REGION_SIZE",
"DM_ULOG_IS_CLEAN",
"DM_ULOG_IN_SYNC",
"DM_ULOG_FLUSH",
"DM_ULOG_MARK_REGION",
"DM_ULOG_CLEAR_REGION",
"DM_ULOG_GET_RESYNC_WORK",
"DM_ULOG_SET_REGION_SYNC",
"DM_ULOG_GET_SYNC_COUNT",
"DM_ULOG_STATUS_INFO",
"DM_ULOG_STATUS_TABLE",
"DM_ULOG_IS_REMOTE_RECOVERING",
NULL
};
int log_tabbing = 0;
int log_is_open = 0;
/*
* Variables for various conditional logging
*/
#ifdef MEMB
int log_membership_change = 1;
#else
int log_membership_change = 0;
#endif
#ifdef CKPT
int log_checkpoint = 1;
#else
int log_checkpoint = 0;
#endif
#ifdef RESEND
int log_resend_requests = 1;
#else
int log_resend_requests = 0;
#endif

View File

@ -1,77 +0,0 @@
/*
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_CLOG_LOGGING_H
#define _LVM_CLOG_LOGGING_H
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include "configure.h"
#include <stdio.h>
#include <stdint.h>
#include <syslog.h>
/* SHORT_UUID - print last 8 chars of a string */
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
extern const char *__rq_types_off_by_one[];
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
extern int log_tabbing;
extern int log_is_open;
extern int log_membership_change;
extern int log_checkpoint;
extern int log_resend_requests;
#define LOG_OPEN(ident, option, facility) do { \
openlog(ident, option, facility); \
log_is_open = 1; \
} while (0)
#define LOG_CLOSE(void) do { \
log_is_open = 0; \
closelog(); \
} while (0)
#define LOG_OUTPUT(level, f, arg...) do { \
int __i; \
char __buffer[16]; \
FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
if (log_is_open) { \
for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
__buffer[__i] = '\t'; \
__buffer[__i] = '\0'; \
syslog(level, "%s" f "\n", __buffer, ## arg); \
} else { \
for (__i = 0; __i < log_tabbing; __i++) \
fprintf(fp, "\t"); \
fprintf(fp, f "\n", ## arg); \
} \
} while (0)
#ifdef DEBUG
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
#else /* DEBUG */
#define LOG_DBG(f, arg...) do {} while (0)
#endif /* DEBUG */
#define LOG_COND(__X, f, arg...) do {\
if (__X) { \
LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
} \
} while (0)
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
#endif /* _LVM_CLOG_LOGGING_H */

View File

@ -1,4 +0,0 @@
init_fifos
fini_fifos
daemon_talk
dm_event_get_version

View File

@ -1,110 +0,0 @@
#
# Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
#
# This file is part of the device-mapper userspace tools.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU Lesser General Public License v.2.1.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = libdevmapper-event.c
SOURCES2 = dmeventd.c
TARGETS = dmeventd
.PHONY: install_lib_dynamic install_lib_static install_include \
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
install_lib install_dmeventd
INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
INSTALL_LIB_TARGETS = install_lib_dynamic
LIB_NAME = libdevmapper-event
ifeq ("@STATIC_LINK@", "yes")
LIB_STATIC = $(LIB_NAME).a
TARGETS += $(LIB_STATIC) dmeventd.static
INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
INSTALL_LIB_TARGETS += install_lib_static
endif
LIB_VERSION = $(LIB_VERSION_DM)
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
ifneq ($(MAKECMDGOALS),device-mapper)
SUBDIRS+=plugins
endif
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = dmeventd
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
EXPORTED_FN_PREFIX = dm_event
include $(top_builddir)/make.tmpl
all: device-mapper
device-mapper: $(TARGETS)
LIBS += -ldevmapper
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
dmeventd: $(LIB_SHARED) dmeventd.o
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
INSTALL_LIB_TARGETS += install_pkgconfig
endif
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-include $(top_builddir)/libdm/libdevmapper.cflow
-include $(top_builddir)/lib/liblvm-internal.cflow
-include $(top_builddir)/lib/liblvm2cmd.cflow
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
endif
install_include: $(srcdir)/libdevmapper-event.h
$(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc
$(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
install_lib_dynamic: install_lib_shared
install_lib_static: $(LIB_STATIC)
$(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
install_lib: $(INSTALL_LIB_TARGETS)
install_dmeventd_dynamic: dmeventd
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmeventd_static: dmeventd.static
$(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
install: install_include install_lib install_dmeventd
install_device-mapper: install_include install_lib install_dmeventd
DISTCLEAN_TARGETS += libdevmapper-event.pc

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __DMEVENTD_DOT_H__
#define __DMEVENTD_DOT_H__
/* FIXME This stuff must be configurable. */
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
#define DM_EVENT_FIFO_SERVER DEFAULT_DM_RUN_DIR "/dmeventd-server"
#define DM_EVENT_DEFAULT_TIMEOUT 10
/* Commands for the daemon passed in the message below. */
enum dm_event_command {
DM_EVENT_CMD_ACTIVE = 1,
DM_EVENT_CMD_REGISTER_FOR_EVENT,
DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
DM_EVENT_CMD_SET_TIMEOUT,
DM_EVENT_CMD_GET_TIMEOUT,
DM_EVENT_CMD_HELLO,
DM_EVENT_CMD_DIE,
DM_EVENT_CMD_GET_STATUS,
DM_EVENT_CMD_GET_PARAMETERS,
};
/* Message passed between client and daemon. */
struct dm_event_daemon_message {
uint32_t cmd;
uint32_t size;
char *data;
};
/* FIXME Is this meant to be exported? I can't see where the
interface uses it. */
/* Fifos for client/daemon communication. */
struct dm_event_fifos {
int client;
int server;
const char *client_path;
const char *server_path;
};
/* EXIT_SUCCESS 0 -- stdlib.h */
/* EXIT_FAILURE 1 -- stdlib.h */
/* EXIT_LOCKFILE_INUSE 2 -- obsoleted */
#define EXIT_DESC_CLOSE_FAILURE 3
#define EXIT_DESC_OPEN_FAILURE 4
/* EXIT_OPEN_PID_FAILURE 5 -- obsoleted */
#define EXIT_FIFO_FAILURE 6
#define EXIT_CHDIR_FAILURE 7
/* Implemented in libdevmapper-event.c, but not part of public API. */
// FIXME misuse of bitmask as enum
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout);
int init_fifos(struct dm_event_fifos *fifos);
void fini_fifos(struct dm_event_fifos *fifos);
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);
#endif /* __DMEVENTD_DOT_H__ */

View File

@ -1,875 +0,0 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "dmlib.h"
#include "libdevmapper-event.h"
//#include "libmultilog.h"
#include "dmeventd.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
static int _sequence_nr = 0;
struct dm_event_handler {
char *dso;
char *dmeventd_path;
char *dev_name;
char *uuid;
int major;
int minor;
uint32_t timeout;
enum dm_event_mask mask;
};
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
{
dm_free(dmevh->dev_name);
dm_free(dmevh->uuid);
dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
}
struct dm_event_handler *dm_event_handler_create(void)
{
struct dm_event_handler *dmevh;
if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
log_error("Failed to allocate event handler.");
return NULL;
}
return dmevh;
}
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{
_dm_event_handler_clear_dev_info(dmevh);
dm_free(dmevh->dso);
dm_free(dmevh->dmeventd_path);
dm_free(dmevh);
}
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
{
if (!dmeventd_path) /* noop */
return 0;
dm_free(dmevh->dmeventd_path);
if (!(dmevh->dmeventd_path = dm_strdup(dmeventd_path)))
return -ENOMEM;
return 0;
}
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{
if (!path) /* noop */
return 0;
dm_free(dmevh->dso);
if (!(dmevh->dso = dm_strdup(path)))
return -ENOMEM;
return 0;
}
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
{
if (!dev_name)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
if (!(dmevh->dev_name = dm_strdup(dev_name)))
return -ENOMEM;
return 0;
}
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
{
if (!uuid)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
if (!(dmevh->uuid = dm_strdup(uuid)))
return -ENOMEM;
return 0;
}
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
{
int minor = dmevh->minor;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
{
int major = dmevh->major;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask)
{
dmevh->mask = evmask;
}
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
{
dmevh->timeout = timeout;
}
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
{
return dmevh->dso;
}
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
{
return dmevh->dev_name;
}
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
{
return dmevh->uuid;
}
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
{
return dmevh->major;
}
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
{
return dmevh->minor;
}
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
{
return dmevh->timeout;
}
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
{
return dmevh->mask;
}
static int _check_message_id(struct dm_event_daemon_message *msg)
{
int pid, seq_nr;
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
"Expected %d:%d but received %s", getpid(),
_sequence_nr, msg->data);
return 0;
}
return 1;
}
/*
* daemon_read
* @fifos
* @msg
*
* Read message from daemon.
*
* Returns: 0 on failure, 1 on success
*/
static int _daemon_read(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
unsigned bytes = 0;
int ret, i;
fd_set fds;
size_t size = 2 * sizeof(uint32_t); /* status + size */
uint32_t *header = alloca(size);
char *buf = (char *)header;
while (bytes < size) {
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
/* Watch daemon read FIFO for input. */
struct timeval tval = { .tv_sec = 1 };
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if (ret < 0 && errno != EINTR) {
log_error("Unable to read from event server");
return 0;
}
if ((ret == 0) && (i > 4) && !bytes) {
log_error("No input from event server.");
return 0;
}
}
if (ret < 1) {
log_error("Unable to read from event server.");
return 0;
}
ret = read(fifos->server, buf + bytes, size);
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
else {
log_error("Unable to read from event server.");
return 0;
}
}
bytes += ret;
if (header && (bytes == 2 * sizeof(uint32_t))) {
msg->cmd = ntohl(header[0]);
msg->size = ntohl(header[1]);
buf = msg->data = dm_malloc(msg->size);
size = msg->size;
bytes = 0;
header = 0;
}
}
if (bytes != size) {
dm_free(msg->data);
msg->data = NULL;
}
return bytes == size;
}
/* Write message to daemon. */
static int _daemon_write(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
int ret;
fd_set fds;
size_t bytes = 0;
size_t size = 2 * sizeof(uint32_t) + msg->size;
uint32_t *header = alloca(size);
char *buf = (char *)header;
char drainbuf[128];
header[0] = htonl(msg->cmd);
header[1] = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
/* drain the answer fifo */
while (1) {
struct timeval tval = { .tv_usec = 100 };
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if (ret < 0) {
if (errno == EINTR)
continue;
log_error("Unable to talk to event daemon");
return 0;
}
if (ret == 0)
break;
ret = read(fifos->server, drainbuf, sizeof(drainbuf));
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
log_error("Unable to talk to event daemon");
return 0;
}
}
while (bytes < size) {
do {
/* Watch daemon write FIFO to be ready for output. */
FD_ZERO(&fds);
FD_SET(fifos->client, &fds);
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
return 0;
}
} while (ret < 1);
ret = write(fifos->client, buf + bytes, size - bytes);
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
else {
log_error("Unable to talk to event daemon");
return 0;
}
}
bytes += ret;
}
return bytes == size;
}
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
int msg_size;
memset(msg, 0, sizeof(*msg));
/*
* Set command and pack the arguments
* into ASCII message string.
*/
if ((msg_size =
((cmd == DM_EVENT_CMD_HELLO) ?
dm_asprintf(&(msg->data), "%d:%d HELLO", getpid(), _sequence_nr) :
dm_asprintf(&(msg->data), "%d:%d %s %s %u %" PRIu32,
getpid(), _sequence_nr,
dso_name ? : "-", dev_name ? : "-", evmask, timeout)))
< 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
msg->cmd = cmd;
msg->size = msg_size;
/*
* Write command and message to and
* read status return code from daemon.
*/
if (!_daemon_write(fifos, msg)) {
stack;
dm_free(msg->data);
msg->data = NULL;
return -EIO;
}
do {
dm_free(msg->data);
msg->data = NULL;
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
} while (!_check_message_id(msg));
_sequence_nr++;
return (int32_t) msg->cmd;
}
/*
* start_daemon
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
if (stat(fifos->client_path, &statbuf))
goto start_server;
if (!S_ISFIFO(statbuf.st_mode)) {
log_error("%s is not a fifo.", fifos->client_path);
return 0;
}
/* Anyone listening? If not, errno will be ENXIO */
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
if (fifos->client >= 0) {
/* server is running and listening */
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
return 1;
} else if (errno != ENXIO) {
/* problem */
log_sys_error("open", fifos->client_path);
return 0;
}
start_server:
/* server is not running */
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
log_sys_error("stat", args[0]);
return 0;
}
pid = fork();
if (pid < 0)
log_sys_error("fork", "");
else if (!pid) {
execvp(args[0], args);
log_error("Unable to exec dmeventd: %s", strerror(errno));
_exit(EXIT_FAILURE);
} else {
if (waitpid(pid, &status, 0) < 0)
log_error("Unable to start dmeventd: %s",
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
else
ret = 1;
}
return ret;
}
int init_fifos(struct dm_event_fifos *fifos)
{
/* FIXME? Is fifo the most suitable method? Why not share
comms/daemon code with something else e.g. multipath? */
/* Open the fifo used to read from the daemon. */
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
log_sys_error("open", fifos->server_path);
return 0;
}
/* Lock out anyone else trying to do communication with the daemon. */
if (flock(fifos->server, LOCK_EX) < 0) {
log_sys_error("flock", fifos->server_path);
goto bad;
}
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
log_sys_error("open", fifos->client_path);
goto bad;
}
return 1;
bad:
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
fifos->server = -1;
return 0;
}
/* Initialize client. */
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
{
if (!_start_daemon(dmeventd_path, fifos))
return_0;
return init_fifos(fifos);
}
void fini_fifos(struct dm_event_fifos *fifos)
{
if (fifos->client >= 0 && close(fifos->client))
log_sys_debug("close", fifos->client_path);
if (fifos->server >= 0) {
if (flock(fifos->server, LOCK_UN))
log_sys_debug("flock unlock", fifos->server_path);
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
}
}
/* Get uuid of a device */
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
{
struct dm_task *dmt;
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
log_error("_get_device_info: dm_task creation for info failed");
return NULL;
}
if (dmevh->uuid) {
if (!dm_task_set_uuid(dmt, dmevh->uuid))
goto_bad;
} else if (dmevh->dev_name) {
if (!dm_task_set_name(dmt, dmevh->dev_name))
goto_bad;
} else if (dmevh->major && dmevh->minor) {
if (!dm_task_set_major(dmt, dmevh->major) ||
!dm_task_set_minor(dmt, dmevh->minor))
goto_bad;
}
/* FIXME Add name or uuid or devno to messages */
if (!dm_task_run(dmt)) {
log_error("_get_device_info: dm_task_run() failed");
goto bad;
}
if (!dm_task_get_info(dmt, &info)) {
log_error("_get_device_info: failed to get info for device");
goto bad;
}
if (!info.exists) {
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
dmevh->uuid ? : "",
(!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0,
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->minor > 0) ? dmevh->minor : 0,
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) && dmevh->minor == 0 ? "0" : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ") " : "");
goto bad;
}
return dmt;
bad:
dm_task_destroy(dmt);
return NULL;
}
/* Handle the event (de)registration call and return negative error codes. */
static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
int ret;
struct dm_event_fifos fifos = {
.server = -1,
.client = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
};
if (!_init_client(dmeventd_path, &fifos)) {
stack;
return -ESRCH;
}
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
dm_free(msg->data);
msg->data = 0;
if (!ret)
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
fini_fifos(&fifos);
return ret;
}
/* External library interface. */
int dm_event_register_handler(const struct dm_event_handler *dmevh)
{
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg = { 0 };
if (!(dmt = _get_device_info(dmevh)))
return_0;
uuid = dm_task_get_uuid(dmt);
if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") &&
!strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
!strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
!strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
log_warn("WARNING: %s: dmeventd plugins are deprecated", dmevh->dso);
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event registration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
dm_free(msg.data);
dm_task_destroy(dmt);
return ret;
}
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
{
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg = { 0 };
if (!(dmt = _get_device_info(dmevh)))
return_0;
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event deregistration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
dm_free(msg.data);
dm_task_destroy(dmt);
return ret;
}
/* Fetch a string off src and duplicate it into *dest. */
/* FIXME: move to separate module to share with the daemon. */
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
if ((p = strchr(*src, delimiter)))
*p = 0;
if ((ret = dm_strdup(*src)))
*src += strlen(ret) + 1;
if (p)
*p = delimiter;
return ret;
}
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *id;
char *p = msg->data;
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
dm_free(id);
return 0;
}
dm_free(id);
return -ENOMEM;
}
/*
* Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise.
*/
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0 };
struct dm_info info;
if (!(dmt = _get_device_info(dmevh))) {
log_debug("Device does not exists (uuid=%s, name=%s, %d:%d).",
dmevh->uuid, dmevh->dev_name,
dmevh->major, dmevh->minor);
ret = -ENODEV;
goto fail;
}
uuid = dm_task_get_uuid(dmt);
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
log_debug("%s: device not registered.", dm_task_get_name(dmt));
ret = -ENOENT;
goto fail;
}
/* FIXME this will probably horribly break if we get
ill-formatted reply */
ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
dm_task_destroy(dmt);
dmt = NULL;
dm_free(msg.data);
msg.data = NULL;
_dm_event_handler_clear_dev_info(dmevh);
if (!reply_uuid) {
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
goto fail;
}
if (!(dmevh->uuid = dm_strdup(reply_uuid))) {
ret = -ENOMEM;
goto fail;
}
if (!(dmt = _get_device_info(dmevh))) {
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
goto fail;
}
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
dm_free(reply_dso);
reply_dso = NULL;
dm_free(reply_uuid);
reply_uuid = NULL;
if (!(dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)))) {
ret = -ENOMEM;
goto fail;
}
if (!dm_task_get_info(dmt, &info)) {
ret = -1;
goto fail;
}
dmevh->major = info.major;
dmevh->minor = info.minor;
dm_task_destroy(dmt);
return ret;
fail:
dm_free(msg.data);
dm_free(reply_dso);
dm_free(reply_uuid);
_dm_event_handler_clear_dev_info(dmevh);
if (dmt)
dm_task_destroy(dmt);
return ret;
}
/*
* You can (and have to) call this at the stage of the protocol where
* daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0)
*
* would be normally sent. This call will parse the version reply from
* dmeventd, in addition to above call. It is not safe to call this at any
* other place in the protocol.
*
* This is an internal function, not exposed in the public API.
*/
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
char *p;
struct dm_event_daemon_message msg = { 0 };
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
return 0;
p = msg.data;
*version = 0;
if (!p || !(p = strchr(p, ' '))) /* Message ID */
return 0;
if (!(p = strchr(p + 1, ' '))) /* HELLO */
return 0;
if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
*version = atoi(p);
return 1;
}
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg = { 0 };
if (!device_exists(device_path))
return -ENODEV;
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
NULL, device_path, 0, timeout);
}
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
struct dm_event_daemon_message msg = { 0 };
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
msg.data);
dm_free(msg.data);
return -EIO;
}
*timeout = atoi(p);
}
dm_free(msg.data);
return ret;
}
#endif

View File

@ -1,116 +0,0 @@
/*
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Note that this file is released only as part of a technology preview
* and its contents may change in future updates in ways that do not
* preserve compatibility.
*/
#ifndef LIB_DMEVENT_H
#define LIB_DMEVENT_H
#include <stdint.h>
/*
* Event library interface.
*/
enum dm_event_mask {
DM_EVENT_SETTINGS_MASK = 0x0000FF,
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
DM_EVENT_ERROR_MASK = 0x00FF00,
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
};
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
#define DM_EVENT_PROTOCOL_VERSION 2
struct dm_task;
struct dm_event_handler;
struct dm_event_handler *dm_event_handler_create(void);
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
/*
* Path of shared library to handle events.
*
* All of dmeventd, dso, device_name and uuid strings are duplicated so
* you do not need to keep the pointers valid after the call succeeds.
* They may return -ENOMEM though.
*/
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
/*
* Path of dmeventd binary.
*/
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
/*
* Identify the device to monitor by exactly one of device_name, uuid or
* device number. String arguments are duplicated, see above.
*/
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
/*
* Specify mask for events to monitor.
*/
// FIXME misuse of bitmask as enum
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask);
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
// FIXME misuse of bitmask as enum
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
/* FIXME Review interface (what about this next thing?) */
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
/*
* Initiate monitoring using dmeventd.
*/
int dm_event_register_handler(const struct dm_event_handler *dmevh);
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
detailed descriptions. */
// FIXME misuse of bitmask as enum
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
int unregister_device(const char *device_name, const char *uuid, int major,
int minor, void **user);
#endif

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: devmapper-event
Description: device-mapper event library
Version: @DM_LIB_PATCHLEVEL@
Cflags: -I${includedir}
Libs: -L${libdir} -ldevmapper-event
Requires.private: devmapper

View File

@ -1,46 +0,0 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SUBDIRS += lvm2
ifneq ("@MIRRORS@", "none")
SUBDIRS += mirror
endif
ifneq ("@SNAPSHOTS@", "none")
SUBDIRS += snapshot
endif
ifneq ("@RAID@", "none")
SUBDIRS += raid
endif
ifneq ("@THIN@", "none")
SUBDIRS += thin
endif
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = lvm2 mirror snapshot raid thin
endif
include $(top_builddir)/make.tmpl
snapshot: lvm2
mirror: lvm2
raid: lvm2
thin: lvm2

View File

@ -1,7 +0,0 @@
dmeventd_lvm2_init
dmeventd_lvm2_exit
dmeventd_lvm2_lock
dmeventd_lvm2_unlock
dmeventd_lvm2_pool
dmeventd_lvm2_run
dmeventd_lvm2_command

View File

@ -1,31 +0,0 @@
#
# Copyright (C) 2010-2014 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/tools
SOURCES = dmeventd_lvm.c
LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS)
install_lvm2: install_lib_shared
install: install_lvm2

View File

@ -1,176 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "log.h"
#include "lvm2cmd.h"
#include "dmeventd_lvm.h"
#include <pthread.h>
#include <syslog.h>
extern int dmeventd_debug;
/*
* register_device() is called first and performs initialisation.
* Only one device may be registered or unregistered at a time.
*/
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* Number of active registrations.
*/
static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* FIXME Do not pass things directly to syslog, rather use the existing logging
* facilities to sort logging ... however that mechanism needs to be somehow
* configurable and we don't have that option yet
*/
static void _temporary_log_fn(int level,
const char *file __attribute__((unused)),
int line __attribute__((unused)),
int dm_errno __attribute__((unused)),
const char *message)
{
level &= ~(_LOG_STDERR | _LOG_ONCE);
switch (level) {
case _LOG_DEBUG:
if (dmeventd_debug >= 3)
syslog(LOG_DEBUG, "%s", message);
break;
case _LOG_INFO:
if (dmeventd_debug >= 2)
syslog(LOG_INFO, "%s", message);
break;
case _LOG_NOTICE:
if (dmeventd_debug >= 1)
syslog(LOG_NOTICE, "%s", message);
break;
case _LOG_WARN:
syslog(LOG_WARNING, "%s", message);
break;
case _LOG_ERR:
syslog(LOG_ERR, "%s", message);
break;
default:
syslog(LOG_CRIT, "%s", message);
}
}
void dmeventd_lvm2_lock(void)
{
pthread_mutex_lock(&_event_mutex);
}
void dmeventd_lvm2_unlock(void)
{
pthread_mutex_unlock(&_event_mutex);
}
int dmeventd_lvm2_init(void)
{
int r = 0;
pthread_mutex_lock(&_register_mutex);
/*
* Need some space for allocations. 1024 should be more
* than enough for what we need (device mapper name splitting)
*/
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
goto out;
if (!_lvm_handle) {
lvm2_log_fn(_temporary_log_fn);
if (!(_lvm_handle = lvm2_init())) {
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
goto out;
}
lvm2_disable_dmeventd_monitoring(_lvm_handle);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
}
_register_count++;
r = 1;
out:
pthread_mutex_unlock(&_register_mutex);
return r;
}
void dmeventd_lvm2_exit(void)
{
pthread_mutex_lock(&_register_mutex);
if (!--_register_count) {
lvm2_run(_lvm_handle, "_memlock_dec");
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
}
pthread_mutex_unlock(&_register_mutex);
}
struct dm_pool *dmeventd_lvm2_pool(void)
{
return _mem_pool;
}
int dmeventd_lvm2_run(const char *cmdline)
{
return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
}
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
const char *cmd, const char *device)
{
char *vg = NULL, *lv = NULL, *layer;
int r;
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
syslog(LOG_ERR, "Unable to determine VG name from %s.\n",
device);
return 0;
}
/* strip off the mirror component designations */
if ((layer = strstr(lv, "_mimagetmp")) ||
(layer = strstr(lv, "_mlog")))
*layer = '\0';
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
dm_pool_free(mem, vg);
if (r < 0) {
syslog(LOG_ERR, "Unable to form LVM command. (too long).\n");
return 0;
}
return 1;
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Wrappers around liblvm2cmd functions for dmeventd plug-ins.
*
* liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
* threads to co-operate in sharing a single instance.
*
* FIXME Either support this properly as a generic liblvm2cmd wrapper or make
* liblvm2cmd thread-safe so this can go away.
*/
#ifndef _DMEVENTD_LVMWRAP_H
#define _DMEVENTD_LVMWRAP_H
struct dm_pool;
int dmeventd_lvm2_init(void);
void dmeventd_lvm2_exit(void);
int dmeventd_lvm2_run(const char *cmdline);
void dmeventd_lvm2_lock(void);
void dmeventd_lvm2_unlock(void);
struct dm_pool *dmeventd_lvm2_pool(void);
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
const char *cmd, const char *device);
#endif /* _DMEVENTD_LVMWRAP_H */

View File

@ -1,3 +0,0 @@
process_event
register_device
unregister_device

View File

@ -1,37 +0,0 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2005, 2008-2014 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
SOURCES = dmeventd_mirror.c
LIB_NAME = libdevmapper-event-lvm2mirror
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 -ldevmapper
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@ -1,233 +0,0 @@
/*
* Copyright (C) 2005-2012 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include "defaults.h"
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
/* FIXME Reformat to 80 char lines. */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
static int _process_status_code(const char status_code, const char *dev_name,
const char *dev_type, int r)
{
/*
* A => Alive - No failures
* D => Dead - A write failure occurred leaving mirror out-of-sync
* F => Flush failed.
* S => Sync - A sychronization failure occurred, mirror out-of-sync
* R => Read - A read failure occurred, mirror data unaffected
* U => Unclassified failure (bug)
*/
if (status_code == 'F') {
syslog(LOG_ERR, "%s device %s flush failed.",
dev_type, dev_name);
r = ME_FAILURE;
} else if (status_code == 'S')
syslog(LOG_ERR, "%s device %s sync failed.",
dev_type, dev_name);
else if (status_code == 'R')
syslog(LOG_ERR, "%s device %s read failed.",
dev_type, dev_name);
else if (status_code != 'A') {
syslog(LOG_ERR, "%s device %s has failed (%c).",
dev_type, dev_name, status_code);
r = ME_FAILURE;
}
return r;
}
static int _get_mirror_event(char *params)
{
int i, r = ME_INSYNC;
char **args = NULL;
char *dev_status_str;
char *log_status_str;
char *sync_str;
char *p = NULL;
int log_argc, num_devs;
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
* New-style failure params: 1 AA
* New-style log params: 3 cluster 253:3 A
* or 3 disk 253:3 A
* or 1 core
*/
/* number of devices */
if (!dm_split_words(params, 1, 0, &p))
goto out_parse;
if (!(num_devs = atoi(p)) ||
(num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0))
goto out_parse;
p += strlen(p) + 1;
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
args = dm_malloc((num_devs + 7) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
goto out_parse;
/* FIXME: Code differs from lib/mirror/mirrored.c */
dev_status_str = args[2 + num_devs];
log_argc = atoi(args[3 + num_devs]);
log_status_str = args[3 + num_devs + log_argc];
sync_str = args[num_devs];
/* Check for bad mirror devices */
for (i = 0; i < num_devs; i++)
r = _process_status_code(dev_status_str[i], args[i],
i ? "Secondary mirror" : "Primary mirror", r);
/* Check for bad disk log device */
if (log_argc > 1)
r = _process_status_code(log_status_str[0],
args[2 + num_devs + log_argc],
"Log", r);
if (r == ME_FAILURE)
goto out;
p = strstr(sync_str, "/");
if (p) {
p[0] = '\0';
if (strcmp(sync_str, p+1))
r = ME_IGNORE;
p[0] = '/';
} else
goto out_parse;
out:
dm_free(args);
return r;
out_parse:
dm_free(args);
syslog(LOG_ERR, "Unable to parse mirror status string.");
return ME_IGNORE;
}
static int _remove_failed_devices(const char *device)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device))
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
r = dmeventd_lvm2_run(cmd_str);
syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
(r) ? "finished successfully" : "failed");
return (r) ? 0 : -1;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **unused __attribute__((unused)))
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
dmeventd_lvm2_lock();
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.", device);
continue;
}
if (strcmp(target_type, "mirror")) {
syslog(LOG_INFO, "%s has unmirrored portion.", device);
continue;
}
switch(_get_mirror_event(params)) {
case ME_INSYNC:
/* FIXME: all we really know is that this
_part_ of the device is in sync
Also, this is not an error
*/
syslog(LOG_NOTICE, "%s is now in-sync.", device);
break;
case ME_FAILURE:
syslog(LOG_ERR, "Device failure in %s.", device);
if (_remove_failed_devices(device))
/* FIXME Why are all the error return codes unused? Get rid of them? */
syslog(LOG_ERR, "Failed to remove faulty devices in %s.",
device);
/* Should check before warning user that device is now linear
else
syslog(LOG_NOTICE, "%s is now a linear device.\n",
device);
*/
break;
case ME_IGNORE:
break;
default:
/* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.");
}
} while (next);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
{
if (!dmeventd_lvm2_init())
return 0;
syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
return 1;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
{
syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
device);
dmeventd_lvm2_exit();
return 1;
}

View File

@ -1,3 +0,0 @@
process_event
register_device
unregister_device

View File

@ -1,36 +0,0 @@
#
# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
SOURCES = dmeventd_raid.c
LIB_NAME = libdevmapper-event-lvm2raid
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 -ldevmapper
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@ -1,180 +0,0 @@
/*
* Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
/* FIXME Reformat to 80 char lines. */
/*
* run_repair is a close copy to
* plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
*/
static int run_repair(const char *device)
{
int r;
#define CMD_SIZE 256 /* FIXME Use system restriction */
char cmd_str[CMD_SIZE];
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvscan --cache", device))
return -1;
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Re-scan of RAID device %s failed.", device);
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
"lvconvert --config devices{ignore_suspended_devices=1} "
"--repair --use-policies", device))
return -1;
/* if repair goes OK, report success even if lvscan has failed */
r = dmeventd_lvm2_run(cmd_str);
if (!r)
syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
return (r) ? 0 : -1;
}
static int _process_raid_event(char *params, const char *device)
{
int i, n, failure = 0;
char *p, *a[4];
char *raid_type;
char *num_devices;
char *health_chars;
char *resync_ratio;
/*
* RAID parms: <raid_type> <#raid_disks> \
* <health chars> <resync ratio>
*/
if (!dm_split_words(params, 4, 0, a)) {
syslog(LOG_ERR, "Failed to process status line for %s\n",
device);
return -EINVAL;
}
raid_type = a[0];
num_devices = a[1];
health_chars = a[2];
resync_ratio = a[3];
if (!(n = atoi(num_devices))) {
syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
device, num_devices);
return -EINVAL;
}
for (i = 0; i < n; i++) {
switch (health_chars[i]) {
case 'A':
/* Device is 'A'live and well */
case 'a':
/* Device is 'a'live, but not yet in-sync */
break;
case 'D':
syslog(LOG_ERR,
"Device #%d of %s array, %s, has failed.",
i, raid_type, device);
failure++;
break;
default:
/* Unhandled character returned from kernel */
break;
}
if (failure)
return run_repair(device);
}
p = strstr(resync_ratio, "/");
if (!p) {
syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
device, resync_ratio);
return -EINVAL;
}
p[0] = '\0';
syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
return 0;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **unused __attribute__((unused)))
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
dmeventd_lvm2_lock();
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
syslog(LOG_INFO, "%s mapping lost.", device);
continue;
}
if (strcmp(target_type, "raid")) {
syslog(LOG_INFO, "%s has non-raid portion.", device);
continue;
}
if (_process_raid_event(params, device))
syslog(LOG_ERR, "Failed to process event for %s",
device);
} while (next);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
{
if (!dmeventd_lvm2_init())
return 0;
syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
return 1;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **unused __attribute__((unused)))
{
syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
device);
dmeventd_lvm2_exit();
return 1;
}

View File

@ -1,3 +0,0 @@
process_event
register_device
unregister_device

View File

@ -1,33 +0,0 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
SOURCES = dmeventd_snapshot.c
LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 -ldevmapper
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@ -1,247 +0,0 @@
/*
* Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include <sys/wait.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
#include <stdarg.h>
/* FIXME Missing openlog? */
/* First warning when snapshot is 80% full. */
#define WARNING_THRESH 80
/* Run a check every 5%. */
#define CHECK_STEP 5
/* Do not bother checking snapshots less than 50% full. */
#define CHECK_MINIMUM 50
#define UMOUNT_COMMAND "/bin/umount"
struct dso_state {
struct dm_pool *mem;
int percent_check;
uint64_t known_size;
char cmd_str[1024];
};
static int _run(const char *cmd, ...)
{
va_list ap;
int argc = 1; /* for argv[0], i.e. cmd */
int i = 0;
const char **argv;
pid_t pid = fork();
int status;
if (pid == 0) { /* child */
va_start(ap, cmd);
while (va_arg(ap, const char *))
++ argc;
va_end(ap);
/* + 1 for the terminating NULL */
argv = alloca(sizeof(const char *) * (argc + 1));
argv[0] = cmd;
va_start(ap, cmd);
while ((argv[++i] = va_arg(ap, const char *)));
va_end(ap);
execvp(cmd, (char **)argv);
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
exit(127);
}
if (pid > 0) { /* parent */
if (waitpid(pid, &status, 0) != pid)
return 0; /* waitpid failed */
if (!WIFEXITED(status) || WEXITSTATUS(status))
return 0; /* the child failed */
}
if (pid < 0)
return 0; /* fork failed */
return 1; /* all good */
}
static int _extend(const char *cmd)
{
return dmeventd_lvm2_run(cmd);
}
static void _umount(const char *device, int major, int minor)
{
FILE *mounts;
char buffer[4096];
char *words[3];
struct stat st;
if (!(mounts = fopen("/proc/mounts", "r"))) {
syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
return;
}
while (!feof(mounts)) {
/* read a line of /proc/mounts */
if (!fgets(buffer, sizeof(buffer), mounts))
break; /* eof, likely */
/* words[0] is the mount point and words[1] is the device path */
if (dm_split_words(buffer, 3, 0, words) < 2)
continue;
/* find the major/minor of the device */
if (stat(words[0], &st))
continue; /* can't stat, skip this one */
if (S_ISBLK(st.st_mode) &&
major(st.st_rdev) == major &&
minor(st.st_rdev) == minor) {
syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
device, words[1], strerror(errno));
}
}
if (fclose(mounts))
syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **private)
{
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
struct dm_status_snapshot *status = NULL;
const char *device = dm_task_get_name(dmt);
int percent;
struct dso_state *state = *private;
/* No longer monitoring, waiting for remove */
if (!state->percent_check)
return;
dmeventd_lvm2_lock();
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type)
goto out;
if (!dm_get_status_snapshot(state->mem, params, &status))
goto out;
if (status->invalid) {
struct dm_info info;
if (dm_task_get_info(dmt, &info)) {
dmeventd_lvm2_unlock();
_umount(device, info.major, info.minor);
return;
} /* else; too bad, but this is best-effort thing... */
}
/* Snapshot size had changed. Clear the threshold. */
if (state->known_size != status->total_sectors) {
state->percent_check = CHECK_MINIMUM;
state->known_size = status->total_sectors;
}
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.
*/
if (status->invalid || !status->total_sectors) {
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
state->percent_check = 0;
goto out;
}
percent = (int) (100 * status->used_sectors / status->total_sectors);
if (percent >= state->percent_check) {
/* Usage has raised more than CHECK_STEP since the last
time. Run actions. */
state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
/* Try to extend the snapshot, in accord with user-set policies */
if (!_extend(state->cmd_str))
syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
}
out:
if (status)
dm_pool_free(state->mem, status);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
{
struct dm_pool *statemem = NULL;
struct dso_state *state;
if (!dmeventd_lvm2_init())
goto out;
if (!(statemem = dm_pool_create("snapshot_state", 512)) ||
!(state = dm_pool_zalloc(statemem, sizeof(*state))))
goto bad;
if (!dmeventd_lvm2_command(statemem, state->cmd_str,
sizeof(state->cmd_str),
"lvextend --use-policies", device))
goto bad;
state->mem = statemem;
state->percent_check = CHECK_MINIMUM;
*private = state;
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
return 1;
bad:
if (statemem)
dm_pool_destroy(statemem);
dmeventd_lvm2_exit();
out:
syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
{
struct dso_state *state = *private;
syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
dm_pool_destroy(state->mem);
dmeventd_lvm2_exit();
return 1;
}

View File

@ -1,3 +0,0 @@
process_event
register_device
unregister_device

View File

@ -1,36 +0,0 @@
#
# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
SOURCES = dmeventd_thin.c
LIB_NAME = libdevmapper-event-lvm2thin
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
LIBS += -ldevmapper-event-lvm2 -ldevmapper
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@ -1,401 +0,0 @@
/*
* Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "libdevmapper-event.h"
#include "dmeventd_lvm.h"
#include <sys/wait.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
#include <stdarg.h>
/* FIXME Missing openlog? */
/* First warning when thin is 80% full. */
#define WARNING_THRESH 80
/* Run a check every 5%. */
#define CHECK_STEP 5
/* Do not bother checking thins less than 50% full. */
#define CHECK_MINIMUM 50
#define UMOUNT_COMMAND "/bin/umount"
#define THIN_DEBUG 0
struct dso_state {
struct dm_pool *mem;
int metadata_percent_check;
int data_percent_check;
uint64_t known_metadata_size;
uint64_t known_data_size;
char cmd_str[1024];
};
/* TODO - move this mountinfo code into library to be reusable */
#ifdef __linux__
# include "kdev_t.h"
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
# define MKDEV(x,y) makedev((x),(y))
#endif
/* Get dependencies for device, and try to find matching device */
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
{
struct dm_task *dmt;
const struct dm_deps *deps;
struct dm_info info;
int major, minor;
int r = 0;
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
return 0;
if (!dm_task_set_name(dmt, name))
goto out;
if (!dm_task_no_open_count(dmt))
goto out;
if (!dm_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &info))
goto out;
if (!(deps = dm_task_get_deps(dmt)))
goto out;
if (!info.exists || deps->count != 1)
goto out;
major = (int) MAJOR(deps->device[0]);
minor = (int) MINOR(deps->device[0]);
if ((major != tp_major) || (minor != tp_minor))
goto out;
*dev_minor = info.minor;
#if THIN_DEBUG
{
char dev_name[PATH_MAX];
if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name)))
syslog(LOG_DEBUG, "Found %s (%u:%u) depends on %s",
name, major, *dev_minor, dev_name);
}
#endif
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
/* Get all active devices */
static int _find_all_devs(dm_bitset_t bs, int tp_major, int tp_minor)
{
struct dm_task *dmt;
struct dm_names *names;
unsigned next = 0;
int minor, r = 1;
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0;
if (!dm_task_run(dmt)) {
r = 0;
goto out;
}
if (!(names = dm_task_get_names(dmt))) {
r = 0;
goto out;
}
if (!names->dev)
goto out;
do {
names = (struct dm_names *)((char *) names + next);
if (_has_deps(names->name, tp_major, tp_minor, &minor))
dm_bit_set(bs, minor);
next = names->next;
} while (next);
out:
dm_task_destroy(dmt);
return r;
}
static int _extend(struct dso_state *state)
{
#if THIN_DEBUG
syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str);
#endif
return dmeventd_lvm2_run(state->cmd_str);
}
static int _run(const char *cmd, ...)
{
va_list ap;
int argc = 1; /* for argv[0], i.e. cmd */
int i = 0;
const char **argv;
pid_t pid = fork();
int status;
if (pid == 0) { /* child */
va_start(ap, cmd);
while (va_arg(ap, const char *))
++argc;
va_end(ap);
/* + 1 for the terminating NULL */
argv = alloca(sizeof(const char *) * (argc + 1));
argv[0] = cmd;
va_start(ap, cmd);
while ((argv[++i] = va_arg(ap, const char *)));
va_end(ap);
execvp(cmd, (char **)argv);
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
exit(127);
}
if (pid > 0) { /* parent */
if (waitpid(pid, &status, 0) != pid)
return 0; /* waitpid failed */
if (!WIFEXITED(status) || WEXITSTATUS(status))
return 0; /* the child failed */
}
if (pid < 0)
return 0; /* fork failed */
return 1; /* all good */
}
struct mountinfo_s {
struct dm_info info;
dm_bitset_t minors; /* Bitset for active thin pool minors */
const char *device;
};
static int _umount_device(char *buffer, unsigned major, unsigned minor,
char *target, void *cb_data)
{
struct mountinfo_s *data = cb_data;
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
data->device, target);
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
data->device, target, strerror(errno));
}
return 1;
}
/*
* Find all thin pool users and try to umount them.
* TODO: work with read-only thin pool support
*/
static void _umount(struct dm_task *dmt, const char *device)
{
/* TODO: Convert to use hash to reduce memory usage */
static const size_t MINORS = (1U << 20); /* 20 bit */
struct mountinfo_s data = {
.device = device,
};
if (!dm_task_get_info(dmt, &data.info))
return;
dmeventd_lvm2_unlock();
if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
goto out;
}
if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
goto out;
}
if (!dm_mountinfo_read(_umount_device, &data)) {
syslog(LOG_ERR, "Could not parse mountinfo file.\n");
goto out;
}
out:
if (data.minors)
dm_bitset_destroy(data.minors);
dmeventd_lvm2_lock();
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **private)
{
const char *device = dm_task_get_name(dmt);
int percent;
struct dso_state *state = *private;
struct dm_status_thin_pool *tps = NULL;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
#if 0
/* No longer monitoring, waiting for remove */
if (!state->meta_percent_check && !state->data_percent_check)
return;
#endif
dmeventd_lvm2_lock();
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
syslog(LOG_ERR, "Invalid target type.\n");
goto out;
}
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
syslog(LOG_ERR, "Failed to parse status.\n");
_umount(dmt, device);
goto out;
}
#if THIN_DEBUG
syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64
" %" PRIu64 " / %" PRIu64 ".\n", state,
tps->used_metadata_blocks, tps->total_metadata_blocks,
tps->used_data_blocks, tps->total_data_blocks);
#endif
/* Thin pool size had changed. Clear the threshold. */
if (state->known_metadata_size != tps->total_metadata_blocks) {
state->metadata_percent_check = CHECK_MINIMUM;
state->known_metadata_size = tps->total_metadata_blocks;
}
if (state->known_data_size != tps->total_data_blocks) {
state->data_percent_check = CHECK_MINIMUM;
state->known_data_size = tps->total_data_blocks;
}
percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks;
if (percent >= state->metadata_percent_check) {
/*
* Usage has raised more than CHECK_STEP since the last
* time. Run actions.
*/
state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
/* FIXME: extension of metadata needs to be written! */
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n",
device, percent);
/* Try to extend the metadata, in accord with user-set policies */
if (!_extend(state)) {
syslog(LOG_ERR, "Failed to extend thin metadata %s.\n",
device);
_umount(dmt, device);
}
/* FIXME: hmm READ-ONLY switch should happen in error path */
}
percent = 100 * tps->used_data_blocks / tps->total_data_blocks;
if (percent >= state->data_percent_check) {
/*
* Usage has raised more than CHECK_STEP since
* the last time. Run actions.
*/
state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent);
/* Try to extend the thin data, in accord with user-set policies */
if (!_extend(state)) {
syslog(LOG_ERR, "Failed to extend thin %s.\n", device);
state->data_percent_check = 0;
_umount(dmt, device);
}
/* FIXME: hmm READ-ONLY switch should happen in error path */
}
out:
if (tps)
dm_pool_free(state->mem, tps);
dmeventd_lvm2_unlock();
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
{
struct dm_pool *statemem = NULL;
struct dso_state *state;
if (!dmeventd_lvm2_init())
goto bad;
if (!(statemem = dm_pool_create("thin_pool_state", 2048)) ||
!(state = dm_pool_zalloc(statemem, sizeof(*state))) ||
!dmeventd_lvm2_command(statemem, state->cmd_str,
sizeof(state->cmd_str),
"lvextend --use-policies",
device)) {
if (statemem)
dm_pool_destroy(statemem);
dmeventd_lvm2_exit();
goto bad;
}
state->mem = statemem;
state->metadata_percent_check = CHECK_MINIMUM;
state->data_percent_check = CHECK_MINIMUM;
*private = state;
syslog(LOG_INFO, "Monitoring thin %s.\n", device);
return 1;
bad:
syslog(LOG_ERR, "Failed to monitor thin %s.\n", device);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **private)
{
struct dso_state *state = *private;
syslog(LOG_INFO, "No longer monitoring thin %s.\n", device);
dm_pool_destroy(state->mem);
dmeventd_lvm2_exit();
return 1;
}

View File

@ -1,60 +0,0 @@
#
# Copyright (C) 2011-2012 Red Hat, Inc.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU Lesser General Public License v.2.1.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = lvmetad-core.c
SOURCES2 = testclient.c
TARGETS = lvmetad lvmetad-testclient
.PHONY: install_lvmetad
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = lvmetad
include $(top_builddir)/make.tmpl
INCLUDES += -I$(top_srcdir)/libdaemon/server
LVMLIBS = -ldaemonserver $(LVMINTERNAL_LIBS) -ldevmapper
LIBS += $(PTHREAD_LIBS)
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS)
CLDFLAGS += -L$(top_builddir)/libdaemon/server
CFLAGS += $(EXTRA_EXEC_CFLAGS)
lvmetad: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
# TODO: No idea. No idea how to test either.
#ifneq ("$(CFLOW_CMD)", "")
#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
#-include $(top_builddir)/libdm/libdevmapper.cflow
#-include $(top_builddir)/lib/liblvm-internal.cflow
#-include $(top_builddir)/lib/liblvm2cmd.cflow
#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
#endif
install_lvmetad: lvmetad
$(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmetad
install: install_lvm2

View File

@ -1,83 +0,0 @@
/*
* Copyright (C) 2011-2012 Red Hat, Inc.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_LVMETAD_CLIENT_H
#define _LVM_LVMETAD_CLIENT_H
#include "daemon-client.h"
#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
struct volume_group;
/* Different types of replies we may get from lvmetad. */
typedef struct {
daemon_reply r;
const char **uuids; /* NULL terminated array */
} lvmetad_uuidlist;
typedef struct {
daemon_reply r;
struct dm_config_tree *cft;
} lvmetad_vg;
/* Get a list of VG UUIDs that match a given VG name. */
lvmetad_uuidlist lvmetad_lookup_vgname(daemon_handle h, const char *name);
/* Get the metadata of a single VG, identified by UUID. */
lvmetad_vg lvmetad_get_vg(daemon_handle h, const char *uuid);
/*
* Add and remove PVs on demand. Udev-driven systems will use this interface
* instead of scanning.
*/
daemon_reply lvmetad_add_pv(daemon_handle h, const char *pv_uuid, const char *mda_content);
daemon_reply lvmetad_remove_pv(daemon_handle h, const char *pv_uuid);
/* Trigger a full disk scan, throwing away all caches. XXX do we eventually want
* this? Probably not yet, anyway.
* daemon_reply lvmetad_rescan(daemon_handle h);
*/
/*
* Update the version of metadata of a volume group. The VG has to be locked for
* writing for this, and the VG metadata here has to match whatever has been
* written to the disk (under this lock). This initially avoids the requirement
* for lvmetad to write to disk (in later revisions, lvmetad_supersede_vg may
* also do the writing, or we probably add another function to do that).
*/
daemon_reply lvmetad_supersede_vg(daemon_handle h, struct volume_group *vg);
/* Wrappers to open/close connection */
static inline daemon_handle lvmetad_open(const char *socket)
{
daemon_info lvmetad_info = {
.path = "lvmetad",
.socket = socket ?: LVMETAD_SOCKET,
.protocol = "lvmetad",
.protocol_version = 1,
.autostart = 0
};
return daemon_open(lvmetad_info);
}
static inline void lvmetad_close(daemon_handle h)
{
return daemon_close(h);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
#!/bin/bash
export LD_LIBRARY_PATH="$1"
test -n "$2" && {
rm -f /var/run/lvmetad.{socket,pid}
chmod +rx lvmetad
valgrind ./lvmetad -f &
PID=$!
sleep 1
./testclient
kill $PID
exit 0
}
sudo ./test.sh "$1" .

View File

@ -1,127 +0,0 @@
#include "lvmetad-client.h"
#include "label.h"
#include "lvmcache.h"
#include "metadata.h"
const char *uuid1 = "abcd-efgh";
const char *uuid2 = "bbcd-efgh";
const char *vgid = "yada-yada";
const char *uuid3 = "cbcd-efgh";
const char *metadata2 = "{\n"
"id = \"yada-yada\"\n"
"seqno = 15\n"
"status = [\"READ\", \"WRITE\"]\n"
"flags = []\n"
"extent_size = 8192\n"
"physical_volumes {\n"
" pv0 {\n"
" id = \"abcd-efgh\"\n"
" }\n"
" pv1 {\n"
" id = \"bbcd-efgh\"\n"
" }\n"
" pv2 {\n"
" id = \"cbcd-efgh\"\n"
" }\n"
"}\n"
"}\n";
void _handle_reply(daemon_reply reply) {
const char *repl = daemon_reply_str(reply, "response", NULL);
const char *status = daemon_reply_str(reply, "status", NULL);
const char *vgid = daemon_reply_str(reply, "vgid", NULL);
fprintf(stderr, "[C] REPLY: %s\n", repl);
if (!strcmp(repl, "failed"))
fprintf(stderr, "[C] REASON: %s\n", daemon_reply_str(reply, "reason", "unknown"));
if (vgid)
fprintf(stderr, "[C] VGID: %s\n", vgid);
if (status)
fprintf(stderr, "[C] STATUS: %s\n", status);
daemon_reply_destroy(reply);
}
void _pv_add(daemon_handle h, const char *uuid, const char *metadata)
{
daemon_reply reply = daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
"metadata = %b", metadata,
NULL);
_handle_reply(reply);
}
int scan(daemon_handle h, char *fn) {
struct device *dev = dev_cache_get(fn, NULL);
struct label *label;
if (!label_read(dev, &label, 0)) {
fprintf(stderr, "[C] no label found on %s\n", fn);
return;
}
char uuid[64];
id_write_format(dev->pvid, uuid, 64);
fprintf(stderr, "[C] found PV: %s\n", uuid);
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
struct physical_volume pv = { 0, };
if (!(info->fmt->ops->pv_read(info->fmt, dev_name(dev), &pv, 0))) {
fprintf(stderr, "[C] Failed to read PV %s", dev_name(dev));
return;
}
struct format_instance_ctx fic;
struct format_instance *fid = info->fmt->ops->create_instance(info->fmt, &fic);
struct metadata_area *mda;
struct volume_group *vg = NULL;
dm_list_iterate_items(mda, &info->mdas) {
struct volume_group *this = mda->ops->vg_read(fid, "", mda);
if (this && !vg || this->seqno > vg->seqno)
vg = this;
}
if (vg) {
char *buf = NULL;
/* TODO. This is not entirely correct, since export_vg_to_buffer
* adds trailing garbage to the buffer. We may need to use
* export_vg_to_config_tree and format the buffer ourselves. It
* does, however, work for now, since the garbage is well
* formatted and has no conflicting keys with the rest of the
* request. */
export_vg_to_buffer(vg, &buf);
daemon_reply reply =
daemon_send_simple(h, "pv_add", "uuid = %s", uuid,
"metadata = %b", strchr(buf, '{'),
NULL);
_handle_reply(reply);
}
}
void _dump_vg(daemon_handle h, const char *uuid)
{
daemon_reply reply = daemon_send_simple(h, "vg_by_uuid", "uuid = %s", uuid, NULL);
fprintf(stderr, "[C] reply buffer: %s\n", reply.buffer);
daemon_reply_destroy(reply);
}
int main(int argc, char **argv) {
daemon_handle h = lvmetad_open();
if (argc > 1) {
int i;
struct cmd_context *cmd = create_toolcontext(0, NULL, 0, 0);
for (i = 1; i < argc; ++i) {
const char *uuid = NULL;
scan(h, argv[i]);
}
destroy_toolcontext(cmd);
return 0;
}
_pv_add(h, uuid1, NULL);
_pv_add(h, uuid2, metadata2);
_dump_vg(h, vgid);
_pv_add(h, uuid3, NULL);
daemon_close(h);
return 0;
}

59
debian/changelog vendored Normal file
View File

@ -0,0 +1,59 @@
lvm2 (1.95.10-2) unstable; urgency=low
* Fix software raid problems by ensuring lvm init script runs after
raidtools init script. (Closes: #152569)
-- Andres Salomon <dilinger@mp3revolution.net> Tue, 3 Sep 2002 04:05:43 -0400
lvm2 (1.95.10-1) unstable; urgency=low
* New upstream release (Beta 3.2).
* Change all references to /dev/device-mapper/control to
/dev/mapper/control.
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 1 Sep 2002 18:55:12 -0400
lvm2 (0.95.05-3) unstable; urgency=low
* Get rid of awk dependency in init script. (Closes: #146257)
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 12 May 2002 04:39:06 -0500
lvm2 (0.95.05-2) unstable; urgency=low
* Use ${shlibs:Depends} in Depends.
* Get rid of postinst/postrm scripts, use debhelper's init script instead.
* Add Conflicts against lvm10, lvm-common.
* Fix endian issues on big-endian machines.
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 2 May 2002 23:53:53 -0500
lvm2 (0.95.05-1) unstable; urgency=low
* New release (Beta2).
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 25 Apr 2002 00:37:41 -0500
lvm2 (0.95.04cvs20020306-1) unstable; urgency=low
* CVS updated.
* Convert from debian native package.
-- Andres Salomon <dilinger@mp3revolution.net> Wed, 6 Mar 2002 00:43:21 -0500
lvm2 (0.95.04cvs20020304) unstable; urgency=low
* CVS updated.
* Enhance init script; create devmapper control device, etc.
* Add dmsetup as a suggestion.
* Add /etc/lvm/lvm.conf conffile.
* Add undocumented(7) for the commands missing manpages.
-- Andres Salomon <dilinger@mp3revolution.net> Mon, 4 Mar 2002 04:51:26 -0500
lvm2 (0.95.02cvs20020220) unstable; urgency=low
* Initial Release.
-- Andres Salomon <dilinger@mp3revolution.net> Wed, 20 Feb 2002 03:17:25 -0500

2
debian/conffiles vendored Normal file
View File

@ -0,0 +1,2 @@
/etc/lvm/lvm.conf
/etc/init.d/lvm2

20
debian/control vendored Normal file
View File

@ -0,0 +1,20 @@
Source: lvm2
Section: admin
Priority: optional
Maintainer: Andres Salomon <dilinger@mp3revolution.net>
Build-Depends: debhelper (>> 3.0.0), libdevmapper-dev (>= 0.96.04), libreadline4-dev
Standards-Version: 3.5.2
Package: lvm2
Architecture: any
Depends: ${shlibs:Depends}
Conflicts: lvm10, lvm-common
Replaces: lvm10, lvm-common
Provides: lvm-binaries
Suggests: dmsetup
Description: The Linux Logical Volume Manager
This is LVM2, the rewrite of The Linux Logical Volume Manager. LVM
supports enterprise level volume management of disk and disk subsystems
by grouping arbitrary disks into volume groups. The total capacity of
volume groups can be allocated to logical volumes, which are accessed as
regular block devices.

25
debian/copyright vendored Normal file
View File

@ -0,0 +1,25 @@
This package was debianized by Andres Salomon <dilinger@mp3revolution.net> on
Wed, 20 Feb 2002 03:17:25 -0500.
It was downloaded from http://www.sistina.com/products_lvm.htm
Upstream Author(s): LVM Development Team
Copyright (c) 2001-2002 LVM Development Team
LVM2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
LVM2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
On Debian systems, the full text of the GPL can be found in
/usr/share/common-licenses/GPL

4
debian/dirs vendored Normal file
View File

@ -0,0 +1,4 @@
etc/lvm
usr/share/man/man5
usr/share/man/man8
sbin

6
debian/docs vendored Normal file
View File

@ -0,0 +1,6 @@
BUGS
INTRO
README
TODO
VERSION
doc/*

64
debian/init.d vendored Normal file
View File

@ -0,0 +1,64 @@
#! /bin/sh
#
# lvm2 This script handles LVM2 initialization/shutdown.
#
# Written by Andres Salomon <dilinger@mp3revolution.net>.
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin
NAME=lvm2
DESC=LVM
test -x /sbin/vgchange || exit 0
modprobe dm-mod >/dev/null 2>&1
# Create necessary files in /dev for device-mapper
create_devfiles() {
DIR="/dev/mapper"
FILE="$DIR/control"
major=$(grep "[0-9] misc$" /proc/devices | sed 's/[ ]\+misc//')
minor=$(grep "[0-9] device-mapper$" /proc/misc | sed 's/[ ]\+device-mapper//')
if test ! -d $DIR; then
mkdir --mode=755 $DIR >/dev/null 2>&1
fi
if test ! -c $FILE -a ! -z "$minor"; then
mknod --mode=600 $FILE c $major $minor >/dev/null 2>&1
fi
}
case "$1" in
start)
echo -n "Initializing $DESC: "
create_devfiles
vgchange -a y
# # Mount all LVM devices
# for vg in $( vgchange -a y 2>/dev/null | grep active | awk -F\" '{print $2}' ); do
# MTPT=$( grep $vg /etc/fstab | awk '{print $2}' )
# mount $MTPT
# done
echo "$NAME."
;;
stop)
echo -n "Shutting down $DESC: "
# We don't really try all that hard to shut it down; far too many
# things that can keep it from successfully shutting down.
vgchange -a n
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
vgchange -a n
sleep 1
vgchange -a y
echo "$NAME."
;;
*)
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

26
debian/manpages vendored Normal file
View File

@ -0,0 +1,26 @@
debian/lvm2/usr/share/man/man5/lvm.conf.5
debian/lvm2/usr/share/man/man8/lvchange.8
debian/lvm2/usr/share/man/man8/lvcreate.8
debian/lvm2/usr/share/man/man8/lvdisplay.8
debian/lvm2/usr/share/man/man8/lvextend.8
debian/lvm2/usr/share/man/man8/lvm.8
debian/lvm2/usr/share/man/man8/lvmchange.8
debian/lvm2/usr/share/man/man8/lvreduce.8
debian/lvm2/usr/share/man/man8/lvremove.8
debian/lvm2/usr/share/man/man8/lvrename.8
debian/lvm2/usr/share/man/man8/lvscan.8
debian/lvm2/usr/share/man/man8/pvchange.8
debian/lvm2/usr/share/man/man8/pvcreate.8
debian/lvm2/usr/share/man/man8/pvdisplay.8
debian/lvm2/usr/share/man/man8/pvscan.8
debian/lvm2/usr/share/man/man8/vgcfgbackup.8
debian/lvm2/usr/share/man/man8/vgchange.8
debian/lvm2/usr/share/man/man8/vgck.8
debian/lvm2/usr/share/man/man8/vgcreate.8
debian/lvm2/usr/share/man/man8/vgdisplay.8
debian/lvm2/usr/share/man/man8/vgextend.8
debian/lvm2/usr/share/man/man8/vgmerge.8
debian/lvm2/usr/share/man/man8/vgreduce.8
debian/lvm2/usr/share/man/man8/vgremove.8
debian/lvm2/usr/share/man/man8/vgrename.8
debian/lvm2/usr/share/man/man8/vgscan.8

120
debian/rules vendored Executable file
View File

@ -0,0 +1,120 @@
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 by Joey Hess.
#
# This version is for a hypothetical package that builds an
# architecture-dependant package, as well as an architecture-independent
# package.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# This is the debhelper compatibility version to use.
export DH_COMPAT=3
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -g
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/ --mandir=\$${prefix}/usr/share/man --infodir=\$${prefix}/usr/share/info
touch configure-stamp
build-arch: configure-stamp build-arch-stamp
build-arch-stamp:
dh_testdir
# Add here command to compile/build the package.
$(MAKE)
touch build-arch-stamp
build-indep: configure-stamp build-indep-stamp
build-indep-stamp:
dh_testdir
# Add here command to compile/build the arch indep package.
# It's ok not to do anything here, if you don't need to build
# anything for this package.
#/usr/bin/docbook-to-man debian/lvm2.sgml > lvm2.1
touch build-indep-stamp
build: build-arch build-indep
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
-$(MAKE) distclean
-test -r /usr/share/misc/config.sub && \
cp -f /usr/share/misc/config.sub config.sub
-test -r /usr/share/misc/config.guess && \
cp -f /usr/share/misc/config.guess config.guess
dh_clean
install: DH_OPTIONS=
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/lvm2.
$(MAKE) install prefix=$(CURDIR)/debian/lvm2
install -m 0644 doc/example.conf debian/lvm2/etc/lvm/lvm.conf
# Build architecture-independent files here.
# Pass -i to all debhelper commands in this target to reduce clutter.
binary-indep: build install
# nada.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
# dh_installdebconf
dh_installdocs
dh_installexamples
# dh_installlogrotate -a
# dh_installemacsen -a
# dh_installpam -a
# dh_installmime -a
dh_installinit --update-rcd-params="start 26 S . start 50 0 6 ."
dh_installcron
dh_installman
dh_installinfo
dh_undocumented
dh_installchangelogs
dh_strip
dh_link
dh_compress
dh_fixperms
dh_makeshlibs
dh_installdeb
# dh_perl -a
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

14
debian/undocumented vendored Normal file
View File

@ -0,0 +1,14 @@
e2fsadm.8
lvmdiskscan.8
lvmsadc.8
lvmsar.8
lvresize.8
pvdata.8
pvmove.8
pvresize.8
version.8
vgcfgrestore.8
vgexport.8
vgimport.8
vgmknodes.8
vgsplit.8

1
doc/.gitignore vendored
View File

@ -1 +0,0 @@
example.conf

220
doc/example.conf Normal file
View File

@ -0,0 +1,220 @@
# This is an example configuration file for the LVM2 system.
# It contains the default settings that would be used if there was no
# /etc/lvm/lvm.conf file.
#
# Refer to 'man lvm.conf' for further information including the file layout.
#
# To put this file in a different directory and override /etc/lvm set
# the environment variable LVM_SYSTEM_DIR before running the tools.
# This section allows you to configure which block devices should
# be used by the LVM system.
devices {
# Where do you want your volume groups to appear ?
dir = "/dev"
# An array of directories that contain the device nodes you wish
# to use with LVM2.
scan = [ "/dev" ]
# A filter that tells LVM2 to only use a restricted set of devices.
# The filter consists of an array of regular expressions. These
# expressions can be delimited by a character of your choice, and
# prefixed with either an 'a' (for accept) or 'r' (for reject).
# Remember to run vgscan after you change this parameter.
# By default we accept every block device:
filter = [ "a/.*/" ]
# Exclude the cdrom drive
# filter = [ "r|/dev/cdrom|" ]
# When testing I like to work with just loopback devices:
# filter = [ "a/loop/", "r/.*/" ]
# Or maybe all loops and ide drives except hdc:
# filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
# Use anchors if you want to be really specific
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time). By
# default this cache file is hidden in the /etc/lvm directory.
# It is safe to delete this file. vgscan regenerates it.
cache = "/etc/lvm/.cache"
# You can turn off writing this cache file by setting this to 0.
write_cache_state = 1
}
# This section that allows you to configure the nature of the
# information that LVM2 reports.
log {
# Controls the messages sent to stdout or stderr.
# There are three levels of verbosity, 3 being the most verbose.
verbose = 0
# Should we send log messages through syslog?
# 1 is yes; 0 is no.
syslog = 1
# Should we log error and debug messages to a file?
# By default there is no log file.
#file = "/var/log/lvm2.log"
# Should we overwrite the log file each time the program is run?
# By default we append.
overwrite = 0
# What level of log messages should we send to the log file and/or syslog?
# There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
# 7 is the most verbose (LOG_DEBUG).
level = 0
# Format of output messages
# Whether or not (1 or 0) to indent messages according to their severity
indent = 1
# Whether or not (1 or 0) to display the command name on each line output
command_names = 0
# A prefix to use before the message text (but after the command name,
# if selected). Default is two spaces, so you can see/grep the severity
# of each message.
prefix = " "
# To make the messages look similar to the original LVM tools use:
# indent = 0
# command_names = 1
# prefix = " -- "
}
# Configuration of metadata backups and archiving. In LVM2 when we
# talk about a 'backup' we mean making a copy of the metadata for the
# *current* system. The 'archive' contains old metadata configurations.
# Backups are stored in a human readeable text format.
backup {
# Should we maintain a backup of the current metadata configuration ?
# Use 1 for Yes; 0 for No.
# Think very hard before turning this off!
backup = 1
# Where shall we keep it ?
# Remember to back up this directory regularly!
backup_dir = "/etc/lvm/backup"
# Should we maintain an archive of old metadata configurations.
# Use 1 for Yes; 0 for No.
# On by default. Think very hard before turning this off.
archive = 1
# Where should archived files go ?
# Remember to back up this directory regularly!
archive_dir = "/etc/lvm/archive"
# What is the minimum number of archive files you wish to keep ?
retain_min = 10
# What is the minimum time you wish to keep an archive file for ?
retain_days = 30
}
# Settings for the running LVM2 in shell (readline) mode.
shell {
# Number of lines of history to store in ~/.lvm_history
history_size = 100
}
# Miscellaneous global LVM2 settings
global {
# The file creation mask for any files and directories created.
# Interpreted as octal if the first digit is zero.
umask = 077
# Allow other users to read the files
#umask = 022
# Enabling test mode means that no changes to the on disk metadata
# will be made. Equivalent to having the -t option on every
# command. Defaults to off.
test = 0
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.
# If the device-mapper kernel driver is not present in your kernel
# setting this to 0 should suppress the error messages.
activation = 1
# The default metadata format that commands should use - "lvm1" or "lvm2".
# The command line override is -M1 or -M2.
# Defaults to "lvm1" if compiled in, else "lvm2".
# format = "lvm1"
# Location of proc filesystem
proc = "/proc"
# Type of locking to use. Defaults to file-based locking (1).
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
# if LVM2 commands get run concurrently).
locking_type = 1
# Local non-LV directory that holds file-based locks while commands are
# in progress. A directory like /tmp that may get wiped on reboot is OK.
locking_dir = "/var/lock/lvm"
# Other entries can go here to allow you to load shared libraries
# e.g. if support for LVM1 metadata was compiled as a shared library use
# format_libraries = "liblvm2format1.so"
# Full pathnames can be given.
# Search this directory first for shared libraries.
# library_dir = "/lib"
}
####################
# Advanced section #
####################
# Metadata settings
#
# metadata {
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
# It's best to leave this at 2.
# You might want to override it from the command line with 0 or 1
# when running pvcreate on new PVs which are to be added to large VGs.
# pvmetadatacopies = 2
# Approximate default size of on-disk metadata areas in sectors.
# You should increase this if you have large volume groups or
# you want to retain a large on-disk history of your metadata changes.
# pvmetadatasize = 255
# List of directories holding live copies of text format metadata.
# These directories must not be on logical volumes!
# It's possible to use LVM2 with a couple of directories here,
# preferably on different (non-LV) filesystems, and with no other
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
# addition to on-disk metadata areas.
# The feature was originally added to simplify testing.
#
# Never edit any files in these directories by hand unless you
# you are absolutely sure you know what you are doing! Use
# the supplied toolset to make changes (e.g. vgcfgrestore).
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
#}

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lvm2cmd.h"
#include <stdio.h>
/* All output gets passed to this function line-by-line */
void test_log_fn(int level, const char *file, int line,
int dm_errno, const char *format)
{
/* Extract and process output here rather than printing it */
if (level != 4)
return;
printf("%s\n", format);
return;
}
int main(int argc, char **argv)
{
void *handle;
int r;
lvm2_log_fn(test_log_fn);
handle = lvm2_init();
lvm2_log_level(handle, 1);
r = lvm2_run(handle, "vgs --noheadings vg1");
/* More commands here */
lvm2_exit(handle);
return r;
}

View File

@ -1,77 +0,0 @@
Guidance for writing policies
=============================
Try to keep transactionality out of it. The core is careful to
avoid asking about anything that is migrating. This is a pain, but
makes it easier to write the policies.
Mappings are loaded into the policy at construction time.
Every bio that is mapped by the target is referred to the policy.
The policy can return a simple HIT or MISS or issue a migration.
Currently there's no way for the policy to issue background work,
e.g. to start writing back dirty blocks that are going to be evicte
soon.
Because we map bios, rather than requests it's easy for the policy
to get fooled by many small bios. For this reason the core target
issues periodic ticks to the policy. It's suggested that the policy
doesn't update states (eg, hit counts) for a block more than once
for each tick. The core ticks by watching bios complete, and so
trying to see when the io scheduler has let the ios run.
Overview of supplied cache replacement policies
===============================================
multiqueue
----------
This policy is the default.
The multiqueue policy has two sets of 16 queues: one set for entries
waiting for the cache and another one for those in the cache.
Cache entries in the queues are aged based on logical time. Entry into
the cache is based on variable thresholds and queue selection is based
on hit count on entry. The policy aims to take different cache miss
costs into account and to adjust to varying load patterns automatically.
Message and constructor argument pairs are:
'sequential_threshold <#nr_sequential_ios>' and
'random_threshold <#nr_random_ios>'.
The sequential threshold indicates the number of contiguous I/Os
required before a stream is treated as sequential. The random threshold
is the number of intervening non-contiguous I/Os that must be seen
before the stream is treated as random again.
The sequential and random thresholds default to 512 and 4 respectively.
Large, sequential ios are probably better left on the origin device
since spindles tend to have good bandwidth. The io_tracker counts
contiguous I/Os to try to spot when the io is in one of these sequential
modes.
cleaner
-------
The cleaner writes back all dirty blocks in a cache to decommission it.
Examples
========
The syntax for a table is:
cache <metadata dev> <cache dev> <origin dev> <block size>
<#feature_args> [<feature arg>]*
<policy> <#policy_args> [<policy arg>]*
The syntax to send a message using the dmsetup command is:
dmsetup message <mapped device> 0 sequential_threshold 1024
dmsetup message <mapped device> 0 random_threshold 8
Using dmsetup:
dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
/dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
creates a 128GB large mapped device named 'blah' with the
sequential threshold set to 1024 and the random_threshold set to 8.

View File

@ -1,243 +0,0 @@
Introduction
============
dm-cache is a device mapper target written by Joe Thornber, Heinz
Mauelshagen, and Mike Snitzer.
It aims to improve performance of a block device (eg, a spindle) by
dynamically migrating some of its data to a faster, smaller device
(eg, an SSD).
This device-mapper solution allows us to insert this caching at
different levels of the dm stack, for instance above the data device for
a thin-provisioning pool. Caching solutions that are integrated more
closely with the virtual memory system should give better performance.
The target reuses the metadata library used in the thin-provisioning
library.
The decision as to what data to migrate and when is left to a plug-in
policy module. Several of these have been written as we experiment,
and we hope other people will contribute others for specific io
scenarios (eg. a vm image server).
Glossary
========
Migration - Movement of the primary copy of a logical block from one
device to the other.
Promotion - Migration from slow device to fast device.
Demotion - Migration from fast device to slow device.
The origin device always contains a copy of the logical block, which
may be out of date or kept in sync with the copy on the cache device
(depending on policy).
Design
======
Sub-devices
-----------
The target is constructed by passing three devices to it (along with
other parameters detailed later):
1. An origin device - the big, slow one.
2. A cache device - the small, fast one.
3. A small metadata device - records which blocks are in the cache,
which are dirty, and extra hints for use by the policy object.
This information could be put on the cache device, but having it
separate allows the volume manager to configure it differently,
e.g. as a mirror for extra robustness.
Fixed block size
----------------
The origin is divided up into blocks of a fixed size. This block size
is configurable when you first create the cache. Typically we've been
using block sizes of 256k - 1024k.
Having a fixed block size simplifies the target a lot. But it is
something of a compromise. For instance, a small part of a block may be
getting hit a lot, yet the whole block will be promoted to the cache.
So large block sizes are bad because they waste cache space. And small
block sizes are bad because they increase the amount of metadata (both
in core and on disk).
Writeback/writethrough
----------------------
The cache has two modes, writeback and writethrough.
If writeback, the default, is selected then a write to a block that is
cached will go only to the cache and the block will be marked dirty in
the metadata.
If writethrough is selected then a write to a cached block will not
complete until it has hit both the origin and cache devices. Clean
blocks should remain clean.
A simple cleaner policy is provided, which will clean (write back) all
dirty blocks in a cache. Useful for decommissioning a cache.
Migration throttling
--------------------
Migrating data between the origin and cache device uses bandwidth.
The user can set a throttle to prevent more than a certain amount of
migration occuring at any one time. Currently we're not taking any
account of normal io traffic going to the devices. More work needs
doing here to avoid migrating during those peak io moments.
For the time being, a message "migration_threshold <#sectors>"
can be used to set the maximum number of sectors being migrated,
the default being 204800 sectors (or 100MB).
Updating on-disk metadata
-------------------------
On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is
written. If no such requests are made then commits will occur every
second. This means the cache behaves like a physical disk that has a
write cache (the same is true of the thin-provisioning target). If
power is lost you may lose some recent writes. The metadata should
always be consistent in spite of any crash.
The 'dirty' state for a cache block changes far too frequently for us
to keep updating it on the fly. So we treat it as a hint. In normal
operation it will be written when the dm device is suspended. If the
system crashes all cache blocks will be assumed dirty when restarted.
Per-block policy hints
----------------------
Policy plug-ins can store a chunk of data per cache block. It's up to
the policy how big this chunk is, but it should be kept small. Like the
dirty flags this data is lost if there's a crash so a safe fallback
value should always be possible.
For instance, the 'mq' policy, which is currently the default policy,
uses this facility to store the hit count of the cache blocks. If
there's a crash this information will be lost, which means the cache
may be less efficient until those hit counts are regenerated.
Policy hints affect performance, not correctness.
Policy messaging
----------------
Policies will have different tunables, specific to each one, so we
need a generic way of getting and setting these. Device-mapper
messages are used. Refer to cache-policies.txt.
Discard bitset resolution
-------------------------
We can avoid copying data during migration if we know the block has
been discarded. A prime example of this is when mkfs discards the
whole block device. We store a bitset tracking the discard state of
blocks. However, we allow this bitset to have a different block size
from the cache blocks. This is because we need to track the discard
state for all of the origin device (compare with the dirty bitset
which is just for the smaller cache device).
Target interface
================
Constructor
-----------
cache <metadata dev> <cache dev> <origin dev> <block size>
<#feature args> [<feature arg>]*
<policy> <#policy args> [policy args]*
metadata dev : fast device holding the persistent metadata
cache dev : fast device holding cached data blocks
origin dev : slow device holding original data blocks
block size : cache unit size in sectors
#feature args : number of feature arguments passed
feature args : writethrough. (The default is writeback.)
policy : the replacement policy to use
#policy args : an even number of arguments corresponding to
key/value pairs passed to the policy
policy args : key/value pairs passed to the policy
E.g. 'sequential_threshold 1024'
See cache-policies.txt for details.
Optional feature arguments are:
writethrough : write through caching that prohibits cache block
content from being different from origin block content.
Without this argument, the default behaviour is to write
back cache block contents later for performance reasons,
so they may differ from the corresponding origin blocks.
A policy called 'default' is always registered. This is an alias for
the policy we currently think is giving best all round performance.
As the default policy could vary between kernels, if you are relying on
the characteristics of a specific policy, always request it by name.
Status
------
<#used metadata blocks>/<#total metadata blocks> <#read hits> <#read misses>
<#write hits> <#write misses> <#demotions> <#promotions> <#blocks in cache>
<#dirty> <#features> <features>* <#core args> <core args>* <#policy args>
<policy args>*
#used metadata blocks : Number of metadata blocks used
#total metadata blocks : Total number of metadata blocks
#read hits : Number of times a READ bio has been mapped
to the cache
#read misses : Number of times a READ bio has been mapped
to the origin
#write hits : Number of times a WRITE bio has been mapped
to the cache
#write misses : Number of times a WRITE bio has been
mapped to the origin
#demotions : Number of times a block has been removed
from the cache
#promotions : Number of times a block has been moved to
the cache
#blocks in cache : Number of blocks resident in the cache
#dirty : Number of blocks in the cache that differ
from the origin
#feature args : Number of feature args to follow
feature args : 'writethrough' (optional)
#core args : Number of core arguments (must be even)
core args : Key/value pairs for tuning the core
e.g. migration_threshold
#policy args : Number of policy arguments to follow (must be even)
policy args : Key/value pairs
e.g. 'sequential_threshold 1024
Messages
--------
Policies will have different tunables, specific to each one, so we
need a generic way of getting and setting these. Device-mapper
messages are used. (A sysfs interface would also be possible.)
The message format is:
<key> <value>
E.g.
dmsetup message my_cache 0 sequential_threshold 1024
Examples
========
The test suite can be found here:
https://github.com/jthornber/thinp-test-suite
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
/dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
/dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
mq 4 sequential_threshold 1024 random_threshold 8'

View File

@ -1,76 +0,0 @@
dm-crypt
=========
Device-Mapper's "crypt" target provides transparent encryption of block devices
using the kernel crypto API.
Parameters: <cipher> <key> <iv_offset> <device path> \
<offset> [<#opt_params> <opt_params>]
<cipher>
Encryption cipher and an optional IV generation mode.
(In format cipher[:keycount]-chainmode-ivopts:ivmode).
Examples:
des
aes-cbc-essiv:sha256
twofish-ecb
/proc/crypto contains supported crypto modes
<key>
Key used for encryption. It is encoded as a hexadecimal number.
You can only use key sizes that are valid for the selected cipher.
<keycount>
Multi-key compatibility mode. You can define <keycount> keys and
then sectors are encrypted according to their offsets (sector 0 uses key0;
sector 1 uses key1 etc.). <keycount> must be a power of two.
<iv_offset>
The IV offset is a sector count that is added to the sector number
before creating the IV.
<device path>
This is the device that is going to be used as backend and contains the
encrypted data. You can specify it as a path like /dev/xxx or a device
number <major>:<minor>.
<offset>
Starting sector within the device where the encrypted data begins.
<#opt_params>
Number of optional parameters. If there are no optional parameters,
the optional paramaters section can be skipped or #opt_params can be zero.
Otherwise #opt_params is the number of following arguments.
Example of optional parameters section:
1 allow_discards
allow_discards
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
The default is to ignore discard requests.
WARNING: Assess the specific security risks carefully before enabling this
option. For example, allowing discards on encrypted devices may lead to
the leak of information about the ciphertext device (filesystem type,
used space etc.) if the discarded blocks can be located easily on the
device later.
Example scripts
===============
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
encryption with dm-crypt using the 'cryptsetup' utility, see
http://code.google.com/p/cryptsetup/
[[
#!/bin/sh
# Create a crypt device using dmsetup
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
]]
[[
#!/bin/sh
# Create a crypt device using cryptsetup and LUKS header with default cipher
cryptsetup luksFormat $1
cryptsetup luksOpen $1 crypt1
]]

View File

@ -1,26 +0,0 @@
dm-delay
========
Device-Mapper's "delay" target delays reads and/or writes
and maps them to different devices.
Parameters:
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
With separate write parameters, the first set is only used for reads.
Delays are specified in milliseconds.
Example scripts
===============
[[
#!/bin/sh
# Create device delaying rw operation for 500ms
echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
]]
[[
#!/bin/sh
# Create device delaying only write operation for 500ms and
# splitting reads and writes to different devices $1 $2
echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
]]

Some files were not shown because too many files have changed in this diff Show More