1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-24 21:44:22 +03:00

Compare commits

..

390 Commits

Author SHA1 Message Date
Patrick Caulfield
cbe3e5991b Add locking to PV commands. 2001-12-07 09:37:18 +00:00
Patrick Caulfield
3335b34c44 Add locking to VG commands 2001-12-06 15:19:32 +00:00
Patrick Caulfield
6ffc854f9c Made active/open messages print with log_verbose rather than log_very_verbose
and made them a little more user-friendly. This is the way users will be told
which nodes an LV/VG is open on.
2001-12-06 15:17:37 +00:00
Patrick Caulfield
cbe47da378 Add return code to vg_unlock so it knows whether or not to reload the metadata.
Add locking to lvrename.
2001-12-06 13:13:07 +00:00
Patrick Caulfield
dd34a165a1 Add an extra parameter to the unlock functions to tell the cluster not to reload
the metadata at unlock time. We use this if the command failed.
2001-12-06 09:58:51 +00:00
Patrick Caulfield
b2a6905722 Lock LVs by vg/lv name 2001-12-05 14:57:41 +00:00
Patrick Caulfield
3af6e3b294 Return open count correctly when run locally. 2001-12-05 11:56:11 +00:00
Patrick Caulfield
43a6ba01b9 Locking for lvremove and a couple of typo fixes. 2001-12-05 11:55:45 +00:00
Patrick Caulfield
74646b92fb ADd locking to lvresize 2001-12-05 10:11:56 +00:00
Patrick Caulfield
09453f276f Lock by name rather than UUID. (just as well really, the UUIDs are too long for
SLM to lock by)
2001-12-03 14:27:29 +00:00
Patrick Caulfield
2ddd6ebf79 Add local lockfile-based locking 2001-12-03 11:06:13 +00:00
Patrick Caulfield
4da649182f Put back prototypes that got lost in the last merge I did. 2001-11-26 15:52:34 +00:00
Patrick Caulfield
fb38dc166f Add routines for checking for LV and VG activity around the cluster 2001-11-26 15:49:56 +00:00
Patrick Caulfield
3213274526 Send UUIDs round the cluster. Hmmm, need to resolve these at t'other end. 2001-11-23 13:59:25 +00:00
Patrick Caulfield
010c1715c4 Bring forward a few more changes so my tree works with the current devmapper 2001-11-23 13:53:23 +00:00
Patrick Caulfield
67a5321134 Bring Alasdairs 64bit fixes into this tree. 2001-11-23 12:00:52 +00:00
Patrick Caulfield
b590ecf83a Make shared library 2001-11-22 09:37:35 +00:00
Patrick Caulfield
cc296900ae Use new simplified API 2001-11-21 16:09:43 +00:00
Patrick Caulfield
89d9ee62d7 Simplify the API a fair bit and add some actual suspend/resume calls for local
use.
2001-11-21 16:08:46 +00:00
Patrick Caulfield
4cc7c16037 Add a couple of suspend API functions. 2001-11-21 16:07:05 +00:00
Patrick Caulfield
8032fb64cd The first command to call the locking API.
In fact the biggest diff here is to make sure the error path always calls unlock
as stated in the previous checkin. Southerners please take note(!)
2001-11-20 14:23:28 +00:00
Patrick Caulfield
75ef8629d5 - Add suspend flag to the locking API as we don't always want to suspend the
target LV.

- Removed lvm_ prefix from all functions because Joe told me to.

- Added super-high-level functions that keep the mainline code clean - comands
  now just call lock_lvm() and unlock_lvm() [lock/unlock are too glib!] and the
  library takes care of whether we are clustered or not.

It's important that client routines call unlock before finishing not because the
API can't clean up afterwards (it does) but because multiple LVM commands can be
issued from one lvm invocation and thus they are the same client as far as the
CLVMD is concerned.

The local locking paths currently don't do anything.

Thought: it might be worth renaming this bit of the lib "locking" to make it
less obvious that we have clustering code (of sorts) in here. Or maybe that's
just job security through obscurity.
2001-11-20 14:20:49 +00:00
Patrick Caulfield
7a6d29f5d2 Add cmgr into list of include files and objects to build. 2001-11-19 14:54:19 +00:00
Patrick Caulfield
1c1770003f Add cluster manager library. 2001-11-19 14:40:32 +00:00
Alasdair Kergon
835dab97ff Zero first 4k of new LVs. 2001-11-16 15:38:52 +00:00
Patrick Caulfield
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
Patrick Caulfield
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
Patrick Caulfield
c289355a3a Fix format characters for printing size_ts 2001-11-16 10:56:11 +00:00
Patrick Caulfield
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
Alasdair Kergon
6cf2a0281b lvrename (without reactivation) 2001-11-15 17:27:45 +00:00
Patrick Caulfield
120d35f9af Use POSIX defined PRIu64 for formatting 64 bit unsigned integer types 2001-11-15 15:18:53 +00:00
Patrick Caulfield
2b15d5e7b3 Use FMT_64 to format 64bit types 2001-11-15 14:27:51 +00:00
Patrick Caulfield
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
Alasdair Kergon
91b04abf05 Use inttypes.h 2001-11-15 14:14:03 +00:00
Patrick Caulfield
77faac8740 #include <string.h> for memset 2001-11-15 11:46:00 +00:00
Alasdair Kergon
43b3d54855 More LV-related tidying. lvdisplay without args now shows all LVs. 2001-11-14 18:38:07 +00:00
Alasdair Kergon
69e9b85700 Avoid generating duplicate lv names 2001-11-14 14:12:01 +00:00
Alasdair Kergon
0b6d132759 Miscellaneous tidying 2001-11-14 13:52:38 +00:00
Joe Thornber
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
Joe Thornber
c35b290fa4 o Prefix static var with '_' 2001-11-14 10:44:14 +00:00
Joe Thornber
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
Joe Thornber
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
Alasdair Kergon
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
Joe Thornber
02b7f77bd8 o Put underscore between vg and lv name. 2001-11-13 16:14:54 +00:00
Alasdair Kergon
0ac7ead922 Merge lvreduce & lvextend into lvresize. 2001-11-13 14:17:50 +00:00
Joe Thornber
da9d0e03ce o Stuff 2001-11-12 19:28:50 +00:00
Joe Thornber
120f65f672 o Add ALLOC_SIMPLE 2001-11-12 17:55:05 +00:00
Alasdair Kergon
200a14caa4 Remove hard-coding and create device-mapper directory if required 2001-11-12 17:21:25 +00:00
Joe Thornber
35bf6da8e2 o if any pattern rejects a device, and there were no accepts then reject ! 2001-11-12 17:06:33 +00:00
Joe Thornber
f08f70276c o check result of an allocation 2001-11-12 16:00:52 +00:00
Alasdair Kergon
1ae50fd95b iospace restructured 2001-11-12 15:10:01 +00:00
Joe Thornber
40512beb47 o add fs.c to the Makefile 2001-11-12 13:02:06 +00:00
Joe Thornber
0d7f9b2c94 o add uplink from vg to cmd_context 2001-11-12 12:23:10 +00:00
Joe Thornber
52f42140a7 o Plug in fs_(add|del)_lv 2001-11-12 12:20:58 +00:00
Joe Thornber
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
Joe Thornber
f72d80afc5 o Compile errors 2001-11-12 11:48:31 +00:00
Joe Thornber
7c5cb13b22 o Ready for testing 2001-11-12 11:42:29 +00:00
steve
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
Alasdair Kergon
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
Joe Thornber
44e51ea5fa sync only, not ready yet 2001-11-09 08:48:22 +00:00
Alasdair Kergon
87e201460a lvdisplay & lvreduce 2001-11-08 16:15:58 +00:00
Heinz Mauelshagen
039bd945e2 more todo 2001-11-08 08:19:06 +00:00
Alasdair Kergon
e9e52d2b4b o Always set LVM_READ.
o Avoid duplicate deallocation.
2001-11-07 22:47:43 +00:00
steve
2bf92e7399 Oops. Forgot to check this in earlier. Changes as per previous check in
comments.
2001-11-07 19:27:17 +00:00
Joe Thornber
5b0df241f0 o more todo 2001-11-07 17:38:25 +00:00
Joe Thornber
76f5b05eff o Lot's to do 2001-11-07 17:25:17 +00:00
Joe Thornber
40fb6c998f o Added lvs_in_vgs_opened 2001-11-07 15:02:07 +00:00
Joe Thornber
33f50a342d o pool_empty was very wrong 2001-11-07 14:11:20 +00:00
steve
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
Joe Thornber
2bf8cc62cf o Another pass at the activation code 2001-11-07 11:51:42 +00:00
Heinz Mauelshagen
1ae8247af3 Added GPL disclaimer 2001-11-07 08:50:07 +00:00
Alasdair Kergon
5ef32227ec lvcreate 2001-11-06 19:02:26 +00:00
Joe Thornber
6456e773bd o lv_extend 2001-11-06 12:01:46 +00:00
Joe Thornber
234fe53ca3 o Factor _allocate out for use by lv_extend 2001-11-06 11:31:29 +00:00
Joe Thornber
7c93e7a7b3 o lv_reduce
o  pv_maps wasn't taking a list of acceptable pvs
2001-11-06 11:19:33 +00:00
Joe Thornber
8afc6c7f4b o Contiguous allocation 2001-11-06 10:55:01 +00:00
Joe Thornber
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
Alasdair Kergon
d452c035c6 Reinstate size of lv 2001-11-05 18:07:44 +00:00
Joe Thornber
45113c8f5a o code for building free area lists on a pv. Compiles but not run. 2001-11-05 16:41:38 +00:00
Joe Thornber
0acdd3c62b o adjacent extents are now merged into a single target when activating. 2001-11-05 13:37:13 +00:00
Alasdair Kergon
96d7d0a33e lvcreate prototype 2001-11-05 13:06:03 +00:00
Joe Thornber
b6b280267b o build lv name from <vg>_<lv> 2001-11-02 16:45:44 +00:00
Alasdair Kergon
6e6d253b1a Link in the activation library. 2001-11-02 16:28:04 +00:00
Joe Thornber
d92c105db2 o First pass at activation 2001-11-02 13:45:05 +00:00
Alasdair Kergon
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
Joe Thornber
c4b7411565 o LGPL list implementation 2001-10-31 12:47:01 +00:00
Joe Thornber
de06396046 o random little fixes 2001-10-30 17:53:21 +00:00
Alasdair Kergon
ee6bfeb8e3 lvchange 2001-10-30 14:32:48 +00:00
Alasdair Kergon
058347321f basic lvscan 2001-10-29 18:23:35 +00:00
Joe Thornber
feefe49324 o Add read_ahead and stripes to struct logical_volume 2001-10-29 15:34:56 +00:00
Alasdair Kergon
187381a9a2 prefix & vgname in lvname 2001-10-29 15:28:00 +00:00
Alasdair Kergon
993dfa4368 lvremove 2001-10-29 13:52:23 +00:00
steve
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
steve
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
Joe Thornber
634e0db26d o rfilter was no longer accepting by default 2001-10-25 18:12:44 +00:00
Alasdair Kergon
56855c23e1 o log/overwrite=1 in config file to overwrite instead of append to log 2001-10-25 17:25:48 +00:00
Joe Thornber
0b00f742e3 o was freeing memory from the wrong pool 2001-10-25 15:24:35 +00:00
Alasdair Kergon
b7ab3f673c o fopen error message
o debug options in makefile
2001-10-25 15:07:26 +00:00
Joe Thornber
be04ea1e35 o pfilter stores results for all aliases. 2001-10-25 14:51:51 +00:00
Joe Thornber
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
Joe Thornber
2d82b2c64f o rfilter now checks all aliases for a match 2001-10-25 14:19:39 +00:00
Joe Thornber
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
Joe Thornber
c7abdefa31 o Remove a couple of warnings, and one bug in ttree. Spotted by the optimiser 2001-10-25 13:08:29 +00:00
Joe Thornber
ba772c0bca o Shuffle the keys to stop degeneracy. 2001-10-25 12:38:18 +00:00
Joe Thornber
5bad234119 o Trivial binary tree 2001-10-25 11:38:19 +00:00
Joe Thornber
c7e7baaf23 o added aliases list to struct device. 2001-10-25 11:34:55 +00:00
steve
36658a671b o Correction in logic for write access to tables 2001-10-25 11:05:29 +00:00
steve
045f2e10ba o Fix typos from yesterday 2001-10-25 10:37:05 +00:00
Joe Thornber
fb5a7db66d o Merged common code between hash_destroy and hash_wipe. 2001-10-25 08:31:43 +00:00
Alasdair Kergon
ba7d33982e persistent cache fully incorporated. Goodbye to scanning /dev/cdrom :-) 2001-10-24 17:53:50 +00:00
Joe Thornber
c62279a755 o Updated 00_makefile
o 00_bh-async-3 has been merge with vanilla
2001-10-24 10:52:10 +00:00
steve
17fa1a7ffb o Error list handling now part of fs rather than part of table. 2001-10-24 08:26:10 +00:00
steve
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
Alasdair Kergon
0b8c30c109 persistent filter & some log message changes 2001-10-23 18:20:27 +00:00
Joe Thornber
9ab0f463cc o removed old files 2001-10-23 14:17:07 +00:00
Joe Thornber
6433dda7b8 o forgot to use the path passed into _read_array. 2001-10-23 13:12:05 +00:00
Joe Thornber
fa7a2f4be4 o test program for the new persistent filter. 2001-10-23 13:11:28 +00:00
Alasdair Kergon
ba90e16505 deallocations 2001-10-23 12:33:57 +00:00
Joe Thornber
008f710203 o rethink of the persistent filter 2001-10-23 12:24:55 +00:00
Alasdair Kergon
df2740f126 filter integration into tools 2001-10-23 11:50:49 +00:00
Joe Thornber
2db89d143e o forgot to retry on EINTR or EAGAIN, doh ! 2001-10-23 11:16:30 +00:00
Joe Thornber
0525d49da3 o forgot 'static' 2001-10-22 14:40:31 +00:00
Joe Thornber
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
Joe Thornber
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
Alasdair Kergon
67abf45576 reinstate a removed line 2001-10-22 13:44:09 +00:00
Joe Thornber
d2c9c814e7 o removed 00_latest since it never is. 2001-10-22 10:03:05 +00:00
Joe Thornber
22f8881a64 o tidying 2001-10-21 10:24:10 +00:00
Joe Thornber
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
Joe Thornber
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
Alasdair Kergon
ba71cb5dd7 pvdisplay 2001-10-18 16:55:19 +00:00
steve
9aad6c2c52 o Remove unused variable. 2001-10-18 15:59:25 +00:00
Alasdair Kergon
4d9627f20c pvchange 2001-10-17 15:29:31 +00:00
steve
c142492e91 o Fix crash that Patrick reported 2001-10-17 15:03:00 +00:00
steve
6bf8d9e207 o Fix a typo. This should fix devfs support. 2001-10-17 14:34:53 +00:00
steve
4f9a6168c1 o Patches to go with earlier check in 2001-10-17 13:13:25 +00:00
steve
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
steve
f8686d0e75 o Update to parser
o Extra checks in symlink routines
2001-10-17 11:09:43 +00:00
Alasdair Kergon
549e3c8f9d pvscan 2001-10-16 18:07:54 +00:00
steve
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
Alasdair Kergon
f00be261ba vgchange 2001-10-16 16:25:28 +00:00
steve
9cd94f26d0 o Get file size correct for table
o Make parser look at the right object
2001-10-16 12:17:54 +00:00
steve
4d8f5c80a7 o Fixes to parsing code 2001-10-16 11:56:55 +00:00
steve
24a23acc3d o Tidy up, removing debugging printk's no longer needed 2001-10-16 10:38:13 +00:00
steve
ca8703cfd8 o More bug fixes 2001-10-15 22:39:14 +00:00
Alasdair Kergon
6dcbb5b2f8 vgextend 2001-10-15 22:04:27 +00:00
Alasdair Kergon
a84fdddb2a vgcreate basic extent size validation 2001-10-15 20:29:15 +00:00
Alasdair Kergon
38bb2f8ceb More vgcreate error trapping 2001-10-15 18:39:40 +00:00
steve
23f5ef4345 o More fixes 2001-10-15 16:40:17 +00:00
Alasdair Kergon
ef8a2a9054 o lvm readline error-case tidy-up
o more vgcreate error cases
2001-10-15 12:49:58 +00:00
steve
96103d0e36 o Some bug fixes
o Added symlink ops
 o Some extra sanity checks
2001-10-15 11:31:00 +00:00
Joe Thornber
ff5f6748df o vgcreate 2001-10-12 14:25:53 +00:00
Alasdair Kergon
1c1fd6c366 vgcreate 2001-10-12 12:21:43 +00:00
Joe Thornber
32d37d00cb o make ios the first argument to pv_create 2001-10-12 10:52:32 +00:00
Joe Thornber
82f6cda966 o lift call to check out of pvcreate_single 2001-10-12 10:45:04 +00:00
Joe Thornber
f1ff8ff0d0 o rename _single pvcreate_signle 2001-10-12 10:43:36 +00:00
Joe Thornber
756c72902f o made _single static 2001-10-12 10:42:31 +00:00
Joe Thornber
73f8f0bbd0 o pvcreate
o added uuid unit

o stubbed partition stuff
2001-10-12 10:32:06 +00:00
steve
18ed528f5d o Further tidyups and fixes. 2001-10-12 10:06:40 +00:00
Alasdair Kergon
8fd2f136bc sync 2001-10-12 09:52:30 +00:00
Alasdair Kergon
0524b1bf67 vgreduce, vgremove, vgrename & vgscan 2001-10-11 21:35:55 +00:00
steve
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
Joe Thornber
d46bdba332 o try incrementing pv_number from 1 2001-10-11 16:31:09 +00:00
Joe Thornber
760728110a o if contained &= instad of & 2001-10-11 15:09:31 +00:00
Joe Thornber
12d0a194ca o initalise list_heads, initialise list_heads, initi .. 2001-10-11 14:21:38 +00:00
Joe Thornber
4104543508 o a very quick hack to get vg_number right 2001-10-11 14:10:18 +00:00
Joe Thornber
5c211db015 o set PV_ALLOCATABLE flag correctly 2001-10-11 13:34:17 +00:00
Joe Thornber
2dc6180f8d o pv->system_id 2001-10-11 13:22:51 +00:00
Joe Thornber
e222a34b69 o vg->pv_act 2001-10-11 13:05:55 +00:00
Joe Thornber
ef17d95063 o calculate pv_numbers and lv_numbers for LVM1 support 2001-10-11 10:55:19 +00:00
Joe Thornber
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
steve
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
Joe Thornber
c5a49599ba o sync 2001-10-10 17:11:31 +00:00
Alasdair Kergon
df9da9edf5 standardise some log messages 2001-10-10 16:36:32 +00:00
Joe Thornber
e2200fd050 o builds a very sub-optimal table 2001-10-10 15:30:31 +00:00
Joe Thornber
c6207f5d9c o allocate and zero the extents before exporting the lv's 2001-10-10 14:56:53 +00:00
Joe Thornber
4302b7ff6b o zero all of uuid 2001-10-10 13:33:20 +00:00
Joe Thornber
50a7923438 o uuid_list->id should be NAME_LEN wide 2001-10-10 13:30:58 +00:00
Joe Thornber
ab416445c8 o sizeof(NAME_LEN), don't do that 2001-10-10 13:24:16 +00:00
Joe Thornber
a54698d43c o forgot to init a list head 2001-10-10 13:09:40 +00:00
Joe Thornber
c5a77cc1c0 o dev_write 2001-10-10 13:03:10 +00:00
Alasdair Kergon
a9ffa811fc Tidy metadata diagnostic messages. 2001-10-10 12:45:20 +00:00
Joe Thornber
080a2608e0 o return data not 1 in read_ov 2001-10-10 12:42:03 +00:00
Joe Thornber
57f2e83d6a o check for orphaned pv's when reading 2001-10-10 12:28:10 +00:00
Joe Thornber
5b030139d3 o pv_setup for format1, this is the last one ! 2001-10-10 10:55:55 +00:00
Joe Thornber
0da1ff42d1 o AC_INIT was pointing to an old file 2001-10-10 10:11:25 +00:00
Joe Thornber
2c599b7baa o metadata.h was in here twice 2001-10-10 10:09:12 +00:00
Joe Thornber
5c8af8d21a o pv_write for orphan pv's 2001-10-10 10:05:29 +00:00
Joe Thornber
026f3cfde2 o add munging for format1 and 2 2001-10-10 09:36:29 +00:00
Joe Thornber
f6349180e8 o Code to calculate the metadata layout. 2001-10-10 09:25:04 +00:00
Joe Thornber
aa6421921c o stub pv_write to stop tools crashing 2001-10-09 17:44:58 +00:00
Joe Thornber
7d41d2dab2 o fix seg fault while reading extents 2001-10-09 17:36:48 +00:00
Joe Thornber
f0b4d18f93 o remove another spurious error message 2001-10-09 17:30:20 +00:00
Alasdair Kergon
6750f06e10 o vgremove.
o filter devices by major.
2001-10-09 17:20:02 +00:00
Joe Thornber
b2bd38fa9e o spot empty list in build_vg 2001-10-09 17:09:46 +00:00
Joe Thornber
3482a01e22 o proposed interface to the kernel driver 2001-10-09 16:44:30 +00:00
Joe Thornber
6335467552 o dev-mgr disappears 2001-10-09 16:13:12 +00:00
Joe Thornber
4a39e65b62 o change pv_read to take a name rather than a device 2001-10-09 16:05:34 +00:00
Joe Thornber
c50a23e918 o remove spurious log message 2001-10-09 14:42:58 +00:00
Joe Thornber
1e76b72b98 o hack, hack, hack 2001-10-09 14:26:45 +00:00
Joe Thornber
b94cf39eef o vg_write compiles 2001-10-09 10:47:52 +00:00
Joe Thornber
fef254ffff o get_vgs works 2001-10-09 09:22:50 +00:00
Joe Thornber
e5495863a2 o pv_Read works 2001-10-09 08:58:52 +00:00
Joe Thornber
3b4df2abf0 o get_pvs now works for format 1 2001-10-09 08:11:52 +00:00
Alasdair Kergon
aef2aee6a4 vgrename & vgck 2001-10-08 18:44:22 +00:00
Joe Thornber
d0d9519149 o test program for get_pvs 2001-10-08 18:09:31 +00:00
Joe Thornber
685df1d2c5 o get_pvs for format 1
o fix vg_read if vg doesn't exist
2001-10-08 17:53:43 +00:00
Joe Thornber
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
Joe Thornber
66c887d0f3 o read_vg works (or so it claims) 2001-10-08 16:08:16 +00:00
Joe Thornber
22e9960697 o dev_cache_t program works 2001-10-08 13:58:52 +00:00
Joe Thornber
64aa6e1f2d o sync 2001-10-08 12:11:33 +00:00
Joe Thornber
7a93ed9d04 o we were stuill building dev-mgr files 2001-10-08 10:35:59 +00:00
Joe Thornber
a905e922e9 o read_vg_t compiles 2001-10-08 10:20:25 +00:00
Joe Thornber
f9f08fc720 o makefile for read_vg_t 2001-10-08 09:50:00 +00:00
Joe Thornber
8d402d76d0 o get things compiling 2001-10-08 09:45:16 +00:00
Joe Thornber
46fda6281c o test program for reading a vg 2001-10-08 08:47:27 +00:00
Alasdair Kergon
a14dbe1ea6 Sync include file changes. 2001-10-05 21:39:30 +00:00
Joe Thornber
18810a4c16 o end of day sync 2001-10-05 16:36:53 +00:00
Joe Thornber
147bc80dba o replace {stack; return 0;}'s with a macro (just for this file). 2001-10-05 15:48:05 +00:00
Joe Thornber
c7a484195a o low level write path 2001-10-05 15:20:40 +00:00
Joe Thornber
4968eb6503 o finished writing extent reading code 2001-10-05 13:59:44 +00:00
Alasdair Kergon
a6f2d698a9 revised flags and comments 2001-10-05 13:03:03 +00:00
steve
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
Alasdair Kergon
e1140134c6 metadata status flags regrouping & comments; misc tool changes 2001-10-04 22:53:37 +00:00
Joe Thornber
5ed11e012e o vg_read for format1 2001-10-04 17:48:55 +00:00
Alasdair Kergon
5380bd39ca makefile support for tests 2001-10-04 12:07:29 +00:00
Joe Thornber
2ee2685688 o define the uintN_t types 2001-10-04 11:40:13 +00:00
Joe Thornber
782002245b o forgot to add this before 2001-10-04 10:25:34 +00:00
Joe Thornber
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
Joe Thornber
72ecb99e54 o Use the __alignof__ extension to set DEFAULT_ALIGNMENT to that required
for a 'double'.
2001-10-04 09:10:11 +00:00
Alasdair Kergon
c863507d08 vgcreate & lvmchange outlines 2001-10-03 20:38:07 +00:00
Alasdair Kergon
cff86c9093 vgrename & pvchange outlines 2001-10-03 17:03:25 +00:00
Joe Thornber
0479dfcc54 o added dev-cache.c, dev-io and sorted source files alphabetically 2001-10-03 12:46:17 +00:00
Joe Thornber
68dd67f21c o moved dev-cache to device dir 2001-10-03 12:43:29 +00:00
Joe Thornber
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
Alasdair Kergon
b61e791a4f lvremove outline 2001-10-03 12:34:08 +00:00
Joe Thornber
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
Alasdair Kergon
112cb0dc28 pvscan framework 2001-10-02 17:09:05 +00:00
Joe Thornber
0d3d7fdcf2 o test program for the device cache 2001-10-02 13:44:44 +00:00
Joe Thornber
5d6b89ef3b o test program for the hash table. 2001-10-02 12:46:04 +00:00
Joe Thornber
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
Alasdair Kergon
ae292bd920 Another step towards consistency & compilation. 2001-10-01 22:12:10 +00:00
Alasdair Kergon
6c85a90723 Misc structural changes. 2001-10-01 19:36:06 +00:00
Alasdair Kergon
852592066c Misc structural changes. 2001-10-01 19:29:52 +00:00
Joe Thornber
96e1bc9b44 o changed dev-manager to a dev_filter 2001-10-01 16:21:21 +00:00
Joe Thornber
b41d81ed31 o get block size moved to dev-io.c 2001-10-01 16:07:29 +00:00
Alasdair Kergon
e241ec2244 merge partition code 2001-10-01 15:59:40 +00:00
Alasdair Kergon
16e1f1a94c Tidy includes 2001-10-01 15:53:21 +00:00
Joe Thornber
7a68c42b26 o drop the reference counting in the devices. 2001-10-01 15:43:51 +00:00
Alasdair Kergon
37ccc2e118 Merge fixes 2001-10-01 15:29:39 +00:00
Joe Thornber
4192fe1ab2 o missing * 2001-10-01 15:28:28 +00:00
Joe Thornber
d5c743d7bb o added filter type. 2001-10-01 15:27:16 +00:00
Alasdair Kergon
11814d63e8 Tidy include files 2001-10-01 15:14:39 +00:00
Alasdair Kergon
b753656d50 Create symlinks to .h files in an include directory 2001-10-01 13:36:54 +00:00
Joe Thornber
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
Joe Thornber
1fb0e1900e o list.h from kernel for userland tools to use. 2001-09-28 13:19:17 +00:00
Joe Thornber
954a9731e0 o logical data structures 2001-09-28 13:15:30 +00:00
Joe Thornber
65c3364ad8 o generic hash table to store void *'s, not efficient, but adequate for LVM. 2001-09-28 13:08:44 +00:00
Joe Thornber
3d72b7dccc o rewrite of dm_user_bmap, not tested though. 2001-09-27 10:15:02 +00:00
Patrick Caulfield
13ee569f06 Fix prototype for malloc_aux 2001-09-27 10:01:17 +00:00
Patrick Caulfield
d79ef23a75 Don't include asm/* files 2001-09-27 10:00:47 +00:00
steve
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
Joe Thornber
47a8d7475f o table creation works again. 2001-09-26 19:48:20 +00:00
Joe Thornber
4939053121 o It should build now 2001-09-26 17:32:57 +00:00
Joe Thornber
b525bf554e o typos 2001-09-26 17:07:10 +00:00
Joe Thornber
f00285d2b2 o remove steve's insane ramblings from my code. 2001-09-26 14:32:07 +00:00
steve
040f8d6eda o Lunchtime. 2001-09-26 11:47:02 +00:00
steve
66d905325c o More updates 2001-09-26 09:26:10 +00:00
steve
8b0cd95e73 o Beginnings of new interface. 2001-09-26 08:06:46 +00:00
Alasdair Kergon
d867cca6d9 fix memory leak 2001-09-25 16:26:38 +00:00
Joe Thornber
a28f736369 o quick tidy up 2001-09-25 15:23:20 +00:00
Alasdair Kergon
5c3a71cc59 lvactivate checkpoint commit 2001-09-25 12:49:28 +00:00
Alasdair Kergon
cef6dadb08 Another missing dependency. 2001-09-24 22:44:06 +00:00
steve
36be817a3e o Check in case of setting up volumes before root is mounted. 2001-09-24 15:18:45 +00:00
steve
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
Alasdair Kergon
157159e487 Fix dependencies. 2001-09-24 12:05:04 +00:00
Alasdair Kergon
02ada9f800 Makefiles & autoconf. 2001-09-21 12:37:43 +00:00
Alasdair Kergon
6fcf9a97bb Initialise root node pointer. 2001-09-21 12:32:37 +00:00
Alasdair Kergon
17a5d8799f Unused variables. 2001-09-21 12:31:57 +00:00
steve
31f3fe7a22 o Sync up of todays changes .... nothing very important 2001-09-20 22:58:06 +00:00
steve
89e46d3d83 o Bug fix in error path 2001-09-20 20:22:15 +00:00
steve
885795e67d o Use ERR_PTR and PTR_ERR rather than an extra argument. 2001-09-20 19:25:58 +00:00
steve
92bfb53dd4 o Changed to use table->err_msg rather than passing functions around 2001-09-20 18:22:35 +00:00
steve
4cecbeb115 o Some new files (also part of new fs interface) 2001-09-19 21:28:25 +00:00
steve
5971480f55 o Further changes to new file system interface 2001-09-19 21:27:46 +00:00
steve
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
Alasdair Kergon
76fa6c5cfb hardsect/blksize handling 2001-09-19 17:46:27 +00:00
steve
633b68b518 o Added ref counting to tables
o Further changes to new fs interface
2001-09-19 16:01:27 +00:00
steve
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
steve
f3654e6f8d o Change the deallocation of tables to match the vmalloc changes in my
previous commit
2001-09-19 11:02:02 +00:00
steve
d685dbcf22 o Cut down number of vmallocs to increase speed and efficiency 2001-09-19 10:59:10 +00:00
steve
6a57fa079e o More fs fiddling. Another check point commit. 2001-09-19 10:32:51 +00:00
steve
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
Alasdair Kergon
c2866e799d Fix allocation & list-handling. 2001-09-18 20:03:00 +00:00
steve
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
steve
30abca7be2 Should have been included in the previous commit. 2001-09-18 16:53:18 +00:00
steve
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
steve
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
Alasdair Kergon
59156de92b Error checking: only allow block devices & test for 'nodev'. 2001-09-17 21:17:30 +00:00
steve
e0d7d10600 o Again, please ignore this for the time being. 2001-09-17 19:05:49 +00:00
Alasdair Kergon
daaf862257 o Arbitrary mount path.
o Name length 128.
2001-09-17 16:55:31 +00:00
steve
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
steve
f1571e2d46 o Fixed code where return value of vmalloc wasn't checked 2001-09-17 11:23:13 +00:00
steve
bd28d06298 o Use count should be an atomic_t 2001-09-17 09:01:23 +00:00
steve
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
steve
20a6c8d8e5 o Support /sbin/hotplug 2001-09-14 15:35:06 +00:00
steve
98d264faf4 o Made pending I/O wait uninterruptible 2001-09-14 14:03:02 +00:00
steve
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
Alasdair Kergon
8df5d06f9a Use dmfs_ function name prefix (in line with other file systems). 2001-09-14 13:27:58 +00:00
Patrick Caulfield
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
steve
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
Alasdair Kergon
d2f97ce2da Always truncate error file. 2001-09-14 11:15:54 +00:00
Patrick Caulfield
543ca631e9 Don't store things in _devs[-1] - it's not nice. 2001-09-14 10:54:08 +00:00
steve
f184886db1 o Forgot to create slab caches for dm-blkdev.c
o Misc code tidy
2001-09-14 10:40:20 +00:00
Alasdair Kergon
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
steve
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
steve
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
Alasdair Kergon
cbad7caa68 is_identifier characters 2001-09-13 21:50:38 +00:00
steve
b0388a4012 o Two fixes which Alasdair pointed out. 2001-09-13 20:10:14 +00:00
steve
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
steve
da49f88a03 o Forgot to add ref to module. 2001-09-13 19:36:40 +00:00
Alasdair Kergon
e28feceb06 Add dm-parse to makefile 2001-09-13 19:09:23 +00:00
steve
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
Alasdair Kergon
6f1dce1572 o Remove hard-coded mount point
o Fix macro for compilation
2001-09-13 16:52:50 +00:00
steve
6847776ae7 o Some structures change size with different configs, so always include
<linux/config.h> first.
2001-09-13 14:03:42 +00:00
steve
67bd53bdd8 o Some ioctl() commands. 2001-09-13 14:01:13 +00:00
Patrick Caulfield
e735abfdfd Fix includes so that string functions get prototyped 2001-09-13 12:38:31 +00:00
Patrick Caulfield
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
steve
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
steve
9462763bbb o Use kmem_cache_destroy() to remove slab cache. 2001-09-13 11:07:08 +00:00
Patrick Caulfield
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
Alasdair Kergon
6ae2b6c835 Add dm-parse 2001-09-12 13:50:26 +00:00
Joe Thornber
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
Joe Thornber
bf1cf89914 o more tidy ups from Clausen. 2001-09-05 07:48:11 +00:00
Joe Thornber
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
Joe Thornber
52ffc15ffc o added new constant CHILD_PER_NODE to make things clearer 2001-09-03 08:36:41 +00:00
Joe Thornber
e478c9c693 o Various tidy ups [Andrew Clausen] 2001-09-02 10:49:20 +00:00
Joe Thornber
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
Joe Thornber
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
Joe Thornber
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
Joe Thornber
e8f62085be o tidy ups 2001-08-31 12:49:31 +00:00
Joe Thornber
f430bffe2a o allocate io_hooks from a slab 2001-08-31 10:25:32 +00:00
Joe Thornber
1f0520634f o stray return -ENXIO in reuqest [Jens Axboe] 2001-08-31 09:43:35 +00:00
Joe Thornber
902d4c31fb o rebuilt 00_latest 2001-08-31 09:14:55 +00:00
Joe Thornber
17364ac09f o split uml part out 2001-08-29 14:23:40 +00:00
Joe Thornber
0b889f8f81 o various little tidy ups 2001-08-29 13:58:48 +00:00
Joe Thornber
40e349ff35 o change format of table line to <start> <len> <target> ... 2001-08-28 14:56:47 +00:00
AJ Lewis
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
Joe Thornber
912bc1d4e1 o more deferred io stuff 2001-08-28 14:05:22 +00:00
Joe Thornber
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
Joe Thornber
f0feaca9d7 o ACtual source code patch 2001-08-24 09:50:16 +00:00
Joe Thornber
b6656f171b o a couple of patches we'll need for deviec-mapper 2001-08-24 09:39:32 +00:00
Joe Thornber
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
Joe Thornber
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
Joe Thornber
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
Alasdair Kergon
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
Joe Thornber
0166d938af o chagngesd alloc to return 0 on success 2001-08-22 15:59:56 +00:00
Joe Thornber
6194aeddb0 o fs_add and fs_remove actually create/remove the device now 2001-08-22 15:33:08 +00:00
Joe Thornber
903dbf2c30 o added brackets to make t->name = (char *) (t + 1) more explicit 2001-08-22 15:12:31 +00:00
Alasdair Kergon
9380f9ff57 Return 0 on success now. 2001-08-22 15:02:55 +00:00
Joe Thornber
259ed95486 o wu macro was doing a read unlock
o added dm_fs_add/remveove
2001-08-22 15:01:09 +00:00
Joe Thornber
2ebc92681e o _tok_cpy was broken 2001-08-22 14:30:30 +00:00
Joe Thornber
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
Joe Thornber
a8c2978185 o _get_workd was always returning the end on iput 2001-08-22 13:52:26 +00:00
Alasdair Kergon
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
Joe Thornber
7f94445a1e o set permissions on /proc/device-mapper/control to -w-w-w 2001-08-22 13:45:28 +00:00
Joe Thornber
82a89aec65 o call dm_init_fs 2001-08-22 13:41:00 +00:00
AJ Lewis
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
AJ Lewis
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
AJ Lewis
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
Joe Thornber
aaccea731e o quick hack to get the proc entry registering 2001-08-21 15:31:50 +00:00
Joe Thornber
29e31d7610 o dm-fs compiles, I've forgotten to register the device in /proc though 2001-08-21 15:24:02 +00:00
AJ Lewis
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
AJ Lewis
e6ccd12f00 o Brought hash table code over from experimental 2001-08-21 15:22:59 +00:00
Joe Thornber
b134315df1 o wasn't including dm-fs.o in the build 2001-08-21 14:52:54 +00:00
Joe Thornber
7f34dffa13 o dm-target compiles 2001-08-21 14:51:41 +00:00
Joe Thornber
fa239e78c9 o dm-table compiles 2001-08-21 14:47:42 +00:00
AJ Lewis
707a6c4d6a o Added _basic_ config file support to the device manager 2001-08-21 14:44:18 +00:00
Joe Thornber
e5da303b43 o make dm.c compile 2001-08-21 14:28:00 +00:00
Joe Thornber
84ccd66331 o 2.4.9 support
o new uml-lvm patch
2001-08-21 13:45:16 +00:00
AJ Lewis
ad8cc2baea o Populating with stuff from experimental 2001-08-21 13:22:16 +00:00
Joe Thornber
7c4cf70309 o Populating with stuff from experimental 2001-08-21 12:56:08 +00:00
Joe Thornber
c3211e9b4f o dm_activate/dm_close 2001-08-20 16:12:22 +00:00
steve
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
Joe Thornber
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
Joe Thornber
8cdc26add9 o changed _dev_lock to a rw_semaphore 2001-08-20 14:06:25 +00:00
Joe Thornber
e0b2238886 o proc interface is getting there. 2001-08-20 13:45:43 +00:00
Joe Thornber
369a2e4029 o missed one 2001-08-20 08:05:51 +00:00
Joe Thornber
c4089e3b51 Just syncing with the office.
o device-mapper.c has split
2001-08-20 08:03:02 +00:00
Joe Thornber
9e2e9bc5b8 o added a description 2001-08-16 15:14:07 +00:00
Joe Thornber
a9e44426ed o checked in the new driver, and the uml dir 2001-08-16 08:26:13 +00:00
1217 changed files with 22324 additions and 371161 deletions

142
.gitignore vendored
View File

@@ -1,142 +0,0 @@
*.5
*.7
*.8
*.8_gen
*.a
*.d
*.o
*.orig
*.pc
*.pot
*.pyc
*.pyo
*.rej
*.so
*.so.*
*.sw*
*~
.export.sym
.exported_symbols_generated
.gdb_history
Makefile
make.tmpl
/autom4te.cache/
/autoscan.log
/build/
/config.cache
/config.log
/config.status
/configure.scan
/cscope.out
/html/
/reports/
/tags
/tmp/
coverity/coverity_model.xml
tools/man-generator
tools/man-generator.c
test/.lib-dir-stamp
test/.tests-stamp
test/lib/dmsecuretest
test/lib/lvchange
test/lib/lvconvert
test/lib/lvcreate
test/lib/lvdisplay
test/lib/lvextend
test/lib/lvmconfig
test/lib/lvmdiskscan
test/lib/lvmsadc
test/lib/lvmsar
test/lib/lvreduce
test/lib/lvremove
test/lib/lvrename
test/lib/lvresize
test/lib/lvs
test/lib/lvscan
test/lib/pvchange
test/lib/pvck
test/lib/pvcreate
test/lib/pvdisplay
test/lib/pvmove
test/lib/pvremove
test/lib/pvresize
test/lib/pvs
test/lib/pvscan
test/lib/securetest
test/lib/vgcfgbackup
test/lib/vgcfgrestore
test/lib/vgchange
test/lib/vgck
test/lib/vgconvert
test/lib/vgcreate
test/lib/vgdisplay
test/lib/vgexport
test/lib/vgextend
test/lib/vgimport
test/lib/vgimportclone
test/lib/vgmerge
test/lib/vgmknodes
test/lib/vgreduce
test/lib/vgremove
test/lib/vgrename
test/lib/vgs
test/lib/vgscan
test/lib/vgsplit
test/api/lvtest.t
test/api/pe_start.t
test/api/percent.t
test/api/python_lvm_unit.py
test/api/test
test/api/thin_percent.t
test/api/vglist.t
test/api/vgtest.t
test/lib/aux
test/lib/check
test/lib/clvmd
test/lib/dm-version-expected
test/lib/dmeventd
test/lib/dmsetup
test/lib/dmstats
test/lib/fail
test/lib/flavour-ndev-cluster
test/lib/flavour-ndev-cluster-lvmpolld
test/lib/flavour-ndev-lvmetad
test/lib/flavour-ndev-lvmetad-lvmpolld
test/lib/flavour-ndev-lvmpolld
test/lib/flavour-ndev-vanilla
test/lib/flavour-udev-cluster
test/lib/flavour-udev-cluster-lvmpolld
test/lib/flavour-udev-lvmetad
test/lib/flavour-udev-lvmetad-lvmpolld
test/lib/flavour-udev-lvmlockd-dlm
test/lib/flavour-udev-lvmlockd-sanlock
test/lib/flavour-udev-lvmlockd-test
test/lib/flavour-udev-lvmpolld
test/lib/flavour-udev-vanilla
test/lib/fsadm
test/lib/get
test/lib/inittest
test/lib/invalid
test/lib/lvm
test/lib/lvm-wrapper
test/lib/lvmchange
test/lib/lvmdbusd.profile
test/lib/lvmetad
test/lib/lvmpolld
test/lib/not
test/lib/paths
test/lib/paths-common
test/lib/runner
test/lib/should
test/lib/test
test/lib/thin-performance.profile
test/lib/utils
test/lib/version-expected
test/unit/dmraid_t.c
test/unit/unit-test

340
COPYING
View File

@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
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
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 software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, 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.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program 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 to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -1,25 +0,0 @@
BSD 2-Clause License
Copyright (c) 2014, Red Hat, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,504 +0,0 @@
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
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.]
Preamble
The licenses for most software are designed to take away your
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.
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.
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.
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
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
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.
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.
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.
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.
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.
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.
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.
GNU LESSER 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".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
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
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
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
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
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
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
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
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
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
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
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.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
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
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
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
License as published by the Free Software Foundation; either
version 2.1 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.
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
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

31
INSTALL
View File

@@ -1,31 +0,0 @@
Installation
============
1) Generate custom makefiles.
Run the 'configure' script from the top directory.
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.
Run 'make' from the top directory to build everything you configured.
Run 'make install' to build and install everything you configured.
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.
The tools will work fine without a configuration file being
present, but you ought to review the example file in doc/example.conf.
Please also refer to the WHATS_NEW file and the manual pages for the
individual commands.

View File

@@ -1,190 +1,26 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2018 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., 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 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@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
VPATH = @srcdir@
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
ifeq ("@UDEV_RULES@", "yes")
SUBDIRS += udev
endif
ifeq ("@INTL@", "yes")
SUBDIRS += po
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
tools.distclean: test.distclean
endif
DISTCLEAN_DIRS += lcov_reports*
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
SUBDIRS = include man lib tools
include make.tmpl
include $(top_srcdir)/base/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/test/unit/Makefile
libdm: include
libdaemon: include
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
daemons: lib libdaemon tools
scripts: lib
tools: lib libdaemon
po: tools daemons
man: tools
all_man: tools
scripts: libdm
test: tools daemons
unit-test run-unit-test: test
lib.device-mapper: include.device-mapper
libdm.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
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
CLEAN_DIRS += autom4te.cache
check check_system check_cluster check_local check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock: test
$(MAKE) -C test $(@)
conf.generate man.generate: tools
# how to use parenthesis in makefiles
leftparen:=(
LVM_VER := $(firstword $(subst $(leftparen), ,$(LVM_VERSION)))
VER := LVM2.$(LVM_VER)
# release file name
FILE_VER := $(VER).tgz
CLEAN_TARGETS += $(FILE_VER)
CLEAN_DIRS += $(rpmbuilddir)
dist:
@echo "Generating $(FILE_VER)";\
(cd $(top_srcdir); git ls-tree -r HEAD --name-only | xargs tar --transform "s,^,$(VER)/," -c) | gzip >$(FILE_VER)
rpm: dist
$(RM) -r $(rpmbuilddir)/SOURCES
$(MKDIR_P) $(rpmbuilddir)/SOURCES
$(LN_S) -f $(abs_top_builddir)/$(FILE_VER) $(rpmbuilddir)/SOURCES
$(LN_S) -f $(abs_top_srcdir)/spec/build.inc $(rpmbuilddir)/SOURCES
$(LN_S) -f $(abs_top_srcdir)/spec/macros.inc $(rpmbuilddir)/SOURCES
$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES
DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\
GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\
sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
-e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \
-e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
generate: conf.generate man.generate
$(MAKE) -C conf generate
$(MAKE) -C man generate
all_man:
$(MAKE) -C man all_man
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
install_all_man:
$(MAKE) -C man install_all_man
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
ifneq ("$(LCOV)", "")
.PHONY: lcov-reset lcov lcov-dated
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 --directory $(top_builddir)
ifneq ("$(GENHTML)", "")
lcov:
$(RM) -rf $(LCOV_REPORTS_DIR)
$(MKDIR_P) $(LCOV_REPORTS_DIR)
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
--output-file $(LCOV_REPORTS_DIR)/out.info
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
$(LCOV_REPORTS_DIR)/out.info
endif
endif
ifneq ($(shell which ctags 2>/dev/null),)
.PHONY: tags
tags:
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
CLEAN_TARGETS += tags
endif

52
README
View File

@@ -1,50 +1,2 @@
This tree contains the LVM2 and device-mapper tools and libraries.
This is development branch, for stable 2.02 release see 2018-06-01-stable
branch.
For more information about LVM2 read the changelog in the WHATS_NEW file.
Installation instructions are in INSTALL.
There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from:
ftp://sourceware.org/pub/lvm2/
ftp://sources.redhat.com/pub/lvm2/
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
https://sourceware.org/git/?p=lvm2.git
git clone git://sourceware.org/git/lvm2.git
mirrored to:
https://github.com/lvmteam/lvm2
git clone https://github.com/lvmteam/lvm2.git
git clone git@github.com:lvmteam/lvm2.git
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/lvm-devel
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
Website:
https://sourceware.org/lvm2/
Report upstream bugs at:
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
or open issues at:
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible here:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
This is pretty much empty so far...if you can't see subdirectories,
try 'cvs -f update'

62
TESTING
View File

@@ -1,62 +0,0 @@
LVM2 Test Suite
===============
The codebase contains many tests in the test subdirectory.
Before running tests
--------------------
Keep in mind the testsuite MUST run under root user.
It is recommended not to use LVM on the test machine, especially when running
tests with udev (`make check_system`.)
You MUST disable (or mask) any LVM daemons:
- lvmetad
- dmeventd
- lvmpolld
- lvmdbusd
- lvmlockd
- clvmd
- cmirrord
For running cluster tests, we are using singlenode locking. Pass
`--with-clvmd=singlenode` to configure.
NOTE: This is useful only for testing, and should not be used in produciton
code.
To run D-Bus daemon tests, existing D-Bus session is required.
Running tests
-------------
As root run:
make check
To run only tests matching a string:
make check T=test
To skip tests matching a string:
make check S=test
There are other targets and many environment variables can be used to tweak the
testsuite - for full list and description run `make -C test help`.
Installing testsuite
--------------------
It is possible to install and run a testsuite against installed LVM. Run the
following:
make -C test install
Then lvm2-testsuite binary can be executed to test installed binaries.
See `lvm2-testsuite --help` for options. The same environment variables can be
used as with `make check`.

35
TODO Normal file
View File

@@ -0,0 +1,35 @@
before alpha
------------
FIXME review
extra validation in format1 (must be done before alpha)
status flag review (confirm all use of ->status is consistent)
file system handling (being done)
error message review
correct handling of *existing* snapshots
review statics
review consistency checks for full compatibility with LVM1
iospace split/rename
before beta1
-----------
autobackup/text format
export/import
striping
64bit review
LVM1 compatible tool exit codes
before 2.0
----------
partial activation
atomic transactions
bidirectional format1/format2 migration tool
persistent minors
stats
snapshots
pvmove

View File

@@ -1 +0,0 @@
2.03.06(2)-git (2019-06-15)

View File

@@ -1 +0,0 @@
1.02.165-git (2019-06-15)

5100
WHATS_NEW

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,234 +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_IF_YES([TEST-FOR-YES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
dnl AS_IF() abstraction, checks shell variable for 'yes'
AC_DEFUN([AC_IF_YES], [AS_IF([test $$1 = yes], [$2], [$3])])
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
])
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_GCC_BUILTIN(BUILTIN)
#
# DESCRIPTION
#
# This macro checks if the compiler supports one of GCC's built-in
# functions; many other compilers also provide those same built-ins.
#
# The BUILTIN parameter is the name of the built-in function.
#
# If BUILTIN is supported define HAVE_<BUILTIN>. Keep in mind that since
# builtins usually start with two underscores they will be copied over
# into the HAVE_<BUILTIN> definition (e.g. HAVE___BUILTIN_EXPECT for
# __builtin_expect()).
#
# The macro caches its result in the ax_cv_have_<BUILTIN> variable (e.g.
# ax_cv_have___builtin_expect).
#
# The macro currently supports the following built-in functions:
#
# __builtin_assume_aligned
# __builtin_bswap16
# __builtin_bswap32
# __builtin_bswap64
# __builtin_choose_expr
# __builtin___clear_cache
# __builtin_clrsb
# __builtin_clrsbl
# __builtin_clrsbll
# __builtin_clz
# __builtin_clzl
# __builtin_clzll
# __builtin_complex
# __builtin_constant_p
# __builtin_ctz
# __builtin_ctzl
# __builtin_ctzll
# __builtin_expect
# __builtin_ffs
# __builtin_ffsl
# __builtin_ffsll
# __builtin_fpclassify
# __builtin_huge_val
# __builtin_huge_valf
# __builtin_huge_vall
# __builtin_inf
# __builtin_infd128
# __builtin_infd32
# __builtin_infd64
# __builtin_inff
# __builtin_infl
# __builtin_isinf_sign
# __builtin_nan
# __builtin_nand128
# __builtin_nand32
# __builtin_nand64
# __builtin_nanf
# __builtin_nanl
# __builtin_nans
# __builtin_nansf
# __builtin_nansl
# __builtin_object_size
# __builtin_parity
# __builtin_parityl
# __builtin_parityll
# __builtin_popcount
# __builtin_popcountl
# __builtin_popcountll
# __builtin_powi
# __builtin_powif
# __builtin_powil
# __builtin_prefetch
# __builtin_trap
# __builtin_types_compatible_p
# __builtin_unreachable
#
# Unsuppored built-ins will be tested with an empty parameter set and the
# result of the check might be wrong or meaningless so use with care.
#
# LICENSE
#
# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
serial 3
AC_DEFUN([AX_GCC_BUILTIN], [
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1])
AC_CACHE_CHECK([for $1], [ac_var], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [
m4_case([$1],
[__builtin_assume_aligned], [$1("", 0)],
[__builtin_bswap16], [$1(0)],
[__builtin_bswap32], [$1(0)],
[__builtin_bswap64], [$1(0)],
[__builtin_choose_expr], [$1(0, 0, 0)],
[__builtin___clear_cache], [$1("", "")],
[__builtin_clrsb], [$1(0)],
[__builtin_clrsbl], [$1(0)],
[__builtin_clrsbll], [$1(0)],
[__builtin_clz], [$1(0)],
[__builtin_clzl], [$1(0)],
[__builtin_clzll], [$1(0)],
[__builtin_complex], [$1(0.0, 0.0)],
[__builtin_constant_p], [$1(0)],
[__builtin_ctz], [$1(0)],
[__builtin_ctzl], [$1(0)],
[__builtin_ctzll], [$1(0)],
[__builtin_expect], [$1(0, 0)],
[__builtin_ffs], [$1(0)],
[__builtin_ffsl], [$1(0)],
[__builtin_ffsll], [$1(0)],
[__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)],
[__builtin_huge_val], [$1()],
[__builtin_huge_valf], [$1()],
[__builtin_huge_vall], [$1()],
[__builtin_inf], [$1()],
[__builtin_infd128], [$1()],
[__builtin_infd32], [$1()],
[__builtin_infd64], [$1()],
[__builtin_inff], [$1()],
[__builtin_infl], [$1()],
[__builtin_isinf_sign], [$1(0.0)],
[__builtin_nan], [$1("")],
[__builtin_nand128], [$1("")],
[__builtin_nand32], [$1("")],
[__builtin_nand64], [$1("")],
[__builtin_nanf], [$1("")],
[__builtin_nanl], [$1("")],
[__builtin_nans], [$1("")],
[__builtin_nansf], [$1("")],
[__builtin_nansl], [$1("")],
[__builtin_object_size], [$1("", 0)],
[__builtin_parity], [$1(0)],
[__builtin_parityl], [$1(0)],
[__builtin_parityll], [$1(0)],
[__builtin_popcount], [$1(0)],
[__builtin_popcountl], [$1(0)],
[__builtin_popcountll], [$1(0)],
[__builtin_powi], [$1(0, 0)],
[__builtin_powif], [$1(0, 0)],
[__builtin_powil], [$1(0, 0)],
[__builtin_prefetch], [$1("")],
[__builtin_trap], [$1()],
[__builtin_types_compatible_p], [$1(int, int)],
[__builtin_unreachable], [$1()],
[m4_warn([syntax], [Unsupported built-in $1, the test may fail])
$1()]
)
])],
[AS_VAR_SET([ac_var], [yes])],
[AS_VAR_SET([ac_var], [no])])
])
AS_IF([test yes = AS_VAR_GET([ac_var])],
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1,
[Define to 1 if the system has the `$1' built-in function])], [])
AS_VAR_POPDEF([ac_var])
])

669
aclocal.m4 vendored
View File

@@ -1,669 +0,0 @@
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
# Copyright (C) 1996-2017 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($@)])])
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_python_module.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PYTHON_MODULE(modname[, fatal, python])
#
# DESCRIPTION
#
# Checks for Python module.
#
# If fatal is non-empty then absence of a module will trigger an error.
# The third parameter can either be "python" for Python 2 or "python3" for
# Python 3; defaults to Python 3.
#
# LICENSE
#
# Copyright (c) 2008 Andrew Collier
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 9
AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
AC_DEFUN([AX_PYTHON_MODULE],[
if test -z $PYTHON;
then
if test -z "$3";
then
PYTHON="python3"
else
PYTHON="$3"
fi
fi
PYTHON_NAME=`basename $PYTHON`
AC_MSG_CHECKING($PYTHON_NAME module: $1)
$PYTHON -c "import $1" 2>/dev/null
if test $? -eq 0;
then
AC_MSG_RESULT(yes)
eval AS_TR_CPP(HAVE_PYMOD_$1)=yes
else
AC_MSG_RESULT(no)
eval AS_TR_CPP(HAVE_PYMOD_$1)=no
#
if test -n "$2"
then
AC_MSG_ERROR(failed to find required module $1)
exit 1
fi
fi
])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 11 (pkg-config-0.29.1)
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
dnl 02111-1307, USA.
dnl
dnl As a special exception to the GNU General Public License, if you
dnl distribute this file as part of a program that contains a
dnl configuration script generated by Autoconf, you may include it under
dnl the same distribution terms that you use for the rest of that
dnl program.
dnl PKG_PREREQ(MIN-VERSION)
dnl -----------------------
dnl Since: 0.29
dnl
dnl Verify that the version of the pkg-config macros are at least
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
dnl installed version of pkg-config, this checks the developer's version
dnl of pkg.m4 when generating configure.
dnl
dnl To ensure that this macro is defined, also add:
dnl m4_ifndef([PKG_PREREQ],
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.1])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
dnl ----------------------------------
dnl Since: 0.16
dnl
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
dnl first found in the path. Checks that the version of pkg-config found
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
dnl used since that's the first version where most current features of
dnl pkg-config existed.
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
])dnl PKG_PROG_PKG_CONFIG
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------------------------------
dnl Since: 0.18
dnl
dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl 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])
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
dnl ---------------------------------------------
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
dnl pkg_failed based on the result.
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
])dnl _PKG_CONFIG
dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl ---------------------------
dnl Internal check to see if pkg-config supports short errors.
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
])dnl _PKG_SHORT_ERRORS_SUPPORTED
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl --------------------------------------------------------------
dnl Since: 0.4.0
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
dnl 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
])dnl PKG_CHECK_MODULES
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
dnl [ACTION-IF-NOT-FOUND])
dnl ---------------------------------------------------------------------
dnl Since: 0.29
dnl
dnl Checks for existence of MODULES and gathers its build flags with
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
dnl and VARIABLE-PREFIX_LIBS from --libs.
dnl
dnl Note that if there is a possibility the first call to
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
dnl configure.ac.
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
_save_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES($@)
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
])dnl PKG_CHECK_MODULES_STATIC
dnl PKG_INSTALLDIR([DIRECTORY])
dnl -------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable pkgconfigdir as the location where a module
dnl should install pkg-config .pc files. By default the directory is
dnl $libdir/pkgconfig, but the default can be changed by passing
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
dnl 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
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
dnl --------------------------------
dnl Since: 0.27
dnl
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
dnl module should install arch-independent pkg-config .pc files. By
dnl default the directory is $datadir/pkgconfig, but the default can be
dnl changed by passing DIRECTORY. The user can override through the
dnl --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
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl 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
])dnl PKG_CHECK_VAR
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
dnl [DESCRIPTION], [DEFAULT])
dnl ------------------------------------------
dnl
dnl Prepare a "--with-" configure option using the lowercase
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
dnl PKG_CHECK_MODULES in a single macro.
AC_DEFUN([PKG_WITH_MODULES],
[
m4_pushdef([with_arg], m4_tolower([$1]))
m4_pushdef([description],
[m4_default([$5], [build with ]with_arg[ support])])
m4_pushdef([def_arg], [m4_default([$6], [auto])])
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
m4_case(def_arg,
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
[m4_pushdef([with_without],[--with-]with_arg)])
AC_ARG_WITH(with_arg,
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
[AS_TR_SH([with_]with_arg)=def_arg])
AS_CASE([$AS_TR_SH([with_]with_arg)],
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
[auto],[PKG_CHECK_MODULES([$1],[$2],
[m4_n([def_action_if_found]) $3],
[m4_n([def_action_if_not_found]) $4])])
m4_popdef([with_arg])
m4_popdef([description])
m4_popdef([def_arg])
])dnl PKG_WITH_MODULES
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
dnl [DESCRIPTION], [DEFAULT])
dnl -----------------------------------------------
dnl
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
dnl check._[VARIABLE-PREFIX] is exported as make variable.
AC_DEFUN([PKG_HAVE_WITH_MODULES],
[
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
AM_CONDITIONAL([HAVE_][$1],
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
])dnl PKG_HAVE_WITH_MODULES
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
dnl [DESCRIPTION], [DEFAULT])
dnl ------------------------------------------------------
dnl
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
dnl and preprocessor variable.
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
[
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
])dnl PKG_HAVE_DEFINE_WITH_MODULES
# Copyright (C) 1999-2017 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.
# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# ---------------------------------------------------------------------------
# Adds support for distributing Python modules and packages. To
# install modules, copy them to $(pythondir), using the python_PYTHON
# automake variable. To install a package with the same name as the
# automake package, install to $(pkgpythondir), or use the
# pkgpython_PYTHON automake variable.
#
# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
# locations to install python extension modules (shared libraries).
# Another macro is required to find the appropriate flags to compile
# extension modules.
#
# If your package is configured with a different prefix to python,
# users will have to add the install directory to the PYTHONPATH
# environment variable, or create a .pth file (see the python
# documentation for details).
#
# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
# cause an error if the version of python installed on the system
# doesn't meet the requirement. MINIMUM-VERSION should consist of
# numbers and dots only.
AC_DEFUN([AM_PATH_PYTHON],
[
dnl Find a Python interpreter. Python versions prior to 2.0 are not
dnl supported. (2.0 was released on October 16, 2000).
dnl FIXME: Remove the need to hard-code Python versions here.
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
AC_ARG_VAR([PYTHON], [the Python interpreter])
m4_if([$1],[],[
dnl No version check is needed.
# Find any Python interpreter.
if test -z "$PYTHON"; then
AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
fi
am_display_PYTHON=python
], [
dnl A version check is needed.
if test -n "$PYTHON"; then
# If the user set $PYTHON, use it and don't search something else.
AC_MSG_CHECKING([whether $PYTHON version is >= $1])
AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([Python interpreter is too old])])
am_display_PYTHON=$PYTHON
else
# Otherwise, try each interpreter until we find one that satisfies
# VERSION.
AC_CACHE_CHECK([for a Python interpreter with version >= $1],
[am_cv_pathless_PYTHON],[
for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
test "$am_cv_pathless_PYTHON" = none && break
AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
done])
# Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
if test "$am_cv_pathless_PYTHON" = none; then
PYTHON=:
else
AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
fi
am_display_PYTHON=$am_cv_pathless_PYTHON
fi
])
if test "$PYTHON" = :; then
dnl Run any user-specified action, or abort.
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
else
dnl Query Python for its version number. Getting [:3] seems to be
dnl the best way to do this; it's what "site.py" does in the standard
dnl library.
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
[am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
dnl Use the values of $prefix and $exec_prefix for the corresponding
dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
dnl distinct variables so they can be overridden if need be. However,
dnl general consensus is that you shouldn't need this ability.
AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
dnl At times (like when building shared libraries) you may want
dnl to know which OS platform Python thinks this is.
AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
[am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
# Just factor out some code duplication.
am_python_setup_sysconfig="\
import sys
# Prefer sysconfig over distutils.sysconfig, for better compatibility
# with python 3.x. See automake bug#10227.
try:
import sysconfig
except ImportError:
can_use_sysconfig = 0
else:
can_use_sysconfig = 1
# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
# <https://github.com/pypa/virtualenv/issues/118>
try:
from platform import python_implementation
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
can_use_sysconfig = 0
except ImportError:
pass"
dnl Set up 4 directories:
dnl pythondir -- where to install python scripts. This is the
dnl site-packages directory, not the python standard library
dnl directory like in previous automake betas. This behavior
dnl is more consistent with lispdir.m4 for example.
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON script directory],
[am_cv_python_pythondir],
[if test "x$prefix" = xNONE
then
am_py_prefix=$ac_default_prefix
else
am_py_prefix=$prefix
fi
am_cv_python_pythondir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pythondir in
$am_py_prefix*)
am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
;;
*)
case $am_py_prefix in
/usr|/System*) ;;
*)
am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
esac
])
AC_SUBST([pythondir], [$am_cv_python_pythondir])
dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
dnl more consistent with the rest of automake.
AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
dnl pyexecdir -- directory for installing python extension modules
dnl (shared libraries)
dnl Query distutils for this directory.
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
[am_cv_python_pyexecdir],
[if test "x$exec_prefix" = xNONE
then
am_py_exec_prefix=$am_py_prefix
else
am_py_exec_prefix=$exec_prefix
fi
am_cv_python_pyexecdir=`$PYTHON -c "
$am_python_setup_sysconfig
if can_use_sysconfig:
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
else:
from distutils import sysconfig
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
sys.stdout.write(sitedir)"`
case $am_cv_python_pyexecdir in
$am_py_exec_prefix*)
am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
;;
*)
case $am_py_exec_prefix in
/usr|/System*) ;;
*)
am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
;;
esac
;;
esac
])
AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
dnl Run any user-specified action.
$2
fi
])
# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
# ---------------------------------------------------------------------------
# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
# Run ACTION-IF-FALSE otherwise.
# This test uses sys.hexversion instead of the string equivalent (first
# word of sys.version), in order to cope with versions such as 2.2c1.
# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
AC_DEFUN([AM_PYTHON_CHECK_VERSION],
[prog="import sys
# split strings by '.' and convert to numeric. Append some zeros
# because we need at least 4 digits for the hex conversion.
# map returns an iterator in Python 3.0 and a list in 2.x
minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
minverhex = 0
# xrange is not present in Python 3.0 and range returns an iterator
for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
sys.exit(sys.hexversion < minverhex)"
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
# Copyright (C) 2001-2017 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.
# AM_RUN_LOG(COMMAND)
# -------------------
# Run COMMAND, save the exit status in ac_status, and log it.
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
AC_DEFUN([AM_RUN_LOG],
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
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,170 +0,0 @@
#!/bin/sh
# py-compile - Compile a Python program
scriptversion=2011-06-08.12; # UTC
# Copyright (C) 2000-2014 Free Software Foundation, Inc.
# 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, 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, see <http://www.gnu.org/licenses/>.
# 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.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
if [ -z "$PYTHON" ]; then
PYTHON=python
fi
me=py-compile
usage_error ()
{
echo "$me: $*" >&2
echo "Try '$me --help' for more information." >&2
exit 1
}
basedir=
destdir=
while test $# -ne 0; do
case "$1" in
--basedir)
if test $# -lt 2; then
usage_error "option '--basedir' requires an argument"
else
basedir=$2
fi
shift
;;
--destdir)
if test $# -lt 2; then
usage_error "option '--destdir' requires an argument"
else
destdir=$2
fi
shift
;;
-h|--help)
cat <<\EOF
Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
Byte compile some python scripts FILES. Use --destdir to specify any
leading directory path to the FILES that you don't want to include in the
byte compiled file. Specify --basedir for any additional path information you
do want to be shown in the byte compiled file.
Example:
py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v|--version)
echo "$me $scriptversion"
exit $?
;;
--)
shift
break
;;
-*)
usage_error "unrecognized option '$1'"
;;
*)
break
;;
esac
shift
done
files=$*
if test -z "$files"; then
usage_error "no files given"
fi
# if basedir was given, then it should be prepended to filenames before
# byte compilation.
if [ -z "$basedir" ]; then
pathtrans="path = file"
else
pathtrans="path = os.path.join('$basedir', file)"
fi
# if destdir was given, then it needs to be prepended to the filename to
# byte compile but not go into the compiled file.
if [ -z "$destdir" ]; then
filetrans="filepath = path"
else
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
fi
$PYTHON -c "
import sys, os, py_compile, imp
files = '''$files'''
sys.stdout.write('Byte-compiling python modules...\n')
for file in files.split():
$pathtrans
$filetrans
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
sys.stdout.flush()
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath), path)
else:
py_compile.compile(filepath, filepath + 'c', path)
sys.stdout.write('\n')" || exit $?
# this will fail for python < 1.5, but that doesn't matter ...
$PYTHON -O -c "
import sys, os, py_compile, imp
# pypy does not use .pyo optimization
if hasattr(sys, 'pypy_translation_info'):
sys.exit(0)
files = '''$files'''
sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n')
for file in files.split():
$pathtrans
$filetrans
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
sys.stdout.flush()
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath, False), path)
else:
py_compile.compile(filepath, filepath + 'o', path)
sys.stdout.write('\n')" 2>/dev/null || :
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -1,40 +0,0 @@
# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Uncomment this to build the simple radix tree. You'll need to make clean too.
# Comment to build the advanced radix tree.
#base/data-struct/radix-tree.o: CFLAGS += -DSIMPLE_RADIX_TREE
# NOTE: this Makefile only works as 'include' for toplevel Makefile
# which defined all top_* variables
BASE_SOURCE=\
base/data-struct/hash.c \
base/data-struct/list.c \
base/data-struct/radix-tree.c
BASE_TARGET = base/libbase.a
BASE_DEPENDS = $(BASE_SOURCE:%.c=%.d)
BASE_OBJECTS = $(BASE_SOURCE:%.c=%.o)
CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
$(BASE_SOURCE:%.c=%.gcda) \
$(BASE_SOURCE:%.c=%.gcno) \
$(BASE_TARGET)
$(BASE_TARGET): $(BASE_OBJECTS)
@echo " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
ifeq ("$(DEPENDS)","yes")
-include $(BASE_DEPENDS)
endif

View File

@@ -1,394 +0,0 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "device_mapper/misc/dmlib.h"
#include "base/memory/zalloc.h"
#include "hash.h"
struct dm_hash_node {
struct dm_hash_node *next;
void *data;
unsigned data_len;
unsigned keylen;
char key[0];
};
struct dm_hash_table {
unsigned num_nodes;
unsigned num_slots;
struct dm_hash_node **slots;
};
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
144,
176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
221,
102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
194,
193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
139,
6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
43,
249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
71,
230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
109,
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
209
};
static struct dm_hash_node *_create_node(const char *str, unsigned len)
{
struct dm_hash_node *n = malloc(sizeof(*n) + len);
if (n) {
memcpy(n->key, str, len);
n->keylen = len;
}
return n;
}
static unsigned long _hash(const char *str, unsigned len)
{
unsigned long h = 0, g;
unsigned i;
for (i = 0; i < len; i++) {
h <<= 4;
h += _nums[(unsigned char) *str++];
g = h & ((unsigned long) 0xf << 16u);
if (g) {
h ^= g >> 16u;
h ^= g >> 5u;
}
}
return h;
}
struct dm_hash_table *dm_hash_create(unsigned size_hint)
{
size_t len;
unsigned new_size = 16u;
struct dm_hash_table *hc = zalloc(sizeof(*hc));
if (!hc)
return_0;
/* round size hint up to a power of two */
while (new_size < size_hint)
new_size = new_size << 1;
hc->num_slots = new_size;
len = sizeof(*(hc->slots)) * new_size;
if (!(hc->slots = zalloc(len)))
goto_bad;
return hc;
bad:
free(hc->slots);
free(hc);
return 0;
}
static void _free_nodes(struct dm_hash_table *t)
{
struct dm_hash_node *c, *n;
unsigned i;
for (i = 0; i < t->num_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
free(c);
}
}
void dm_hash_destroy(struct dm_hash_table *t)
{
_free_nodes(t);
free(t->slots);
free(t);
}
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
uint32_t len)
{
unsigned h = _hash(key, len) & (t->num_slots - 1);
struct dm_hash_node **c;
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
continue;
if (!memcmp(key, (*c)->key, len))
break;
}
return c;
}
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
uint32_t len)
{
struct dm_hash_node **c = _find(t, key, len);
return *c ? (*c)->data : 0;
}
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
uint32_t len, void *data)
{
struct dm_hash_node **c = _find(t, key, len);
if (*c)
(*c)->data = data;
else {
struct dm_hash_node *n = _create_node(key, len);
if (!n)
return 0;
n->data = data;
n->next = 0;
*c = n;
t->num_nodes++;
}
return 1;
}
void dm_hash_remove_binary(struct dm_hash_table *t, const void *key,
uint32_t len)
{
struct dm_hash_node **c = _find(t, key, len);
if (*c) {
struct dm_hash_node *old = *c;
*c = (*c)->next;
free(old);
t->num_nodes--;
}
}
void *dm_hash_lookup(struct dm_hash_table *t, const char *key)
{
return dm_hash_lookup_binary(t, key, strlen(key) + 1);
}
int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data)
{
return dm_hash_insert_binary(t, key, strlen(key) + 1, data);
}
void dm_hash_remove(struct dm_hash_table *t, const char *key)
{
dm_hash_remove_binary(t, key, strlen(key) + 1);
}
static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t,
const void *key, const void *val,
uint32_t len, uint32_t val_len)
{
struct dm_hash_node **c;
unsigned h;
h = _hash(key, len) & (t->num_slots - 1);
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
continue;
if (!memcmp(key, (*c)->key, len) && (*c)->data) {
if (((*c)->data_len == val_len) &&
!memcmp(val, (*c)->data, val_len))
return c;
}
}
return NULL;
}
int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len)
{
struct dm_hash_node *n;
struct dm_hash_node *first;
int len = strlen(key) + 1;
unsigned h;
n = _create_node(key, len);
if (!n)
return 0;
n->data = (void *)val;
n->data_len = val_len;
h = _hash(key, len) & (t->num_slots - 1);
first = t->slots[h];
if (first)
n->next = first;
else
n->next = 0;
t->slots[h] = n;
t->num_nodes++;
return 1;
}
/*
* Look through multiple entries with the same key for one that has a
* matching val and return that. If none have maching val, return NULL.
*/
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len)
{
struct dm_hash_node **c;
c = _find_str_with_val(t, key, val, strlen(key) + 1, val_len);
return (c && *c) ? (*c)->data : 0;
}
/*
* Look through multiple entries with the same key for one that has a
* matching val and remove that.
*/
void dm_hash_remove_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len)
{
struct dm_hash_node **c;
c = _find_str_with_val(t, key, val, strlen(key) + 1, val_len);
if (c && *c) {
struct dm_hash_node *old = *c;
*c = (*c)->next;
free(old);
t->num_nodes--;
}
}
/*
* Look up the value for a key and count how many
* entries have the same key.
*
* If no entries have key, return NULL and set count to 0.
*
* If one entry has the key, the function returns the val,
* and sets count to 1.
*
* If N entries have the key, the function returns the val
* from the first entry, and sets count to N.
*/
void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *count)
{
struct dm_hash_node **c;
struct dm_hash_node **c1 = NULL;
uint32_t len = strlen(key) + 1;
unsigned h;
*count = 0;
h = _hash(key, len) & (t->num_slots - 1);
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
continue;
if (!memcmp(key, (*c)->key, len)) {
(*count)++;
if (!c1)
c1 = c;
}
}
if (!c1)
return NULL;
else
return *c1 ? (*c1)->data : 0;
}
unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
{
return t->num_nodes;
}
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
{
struct dm_hash_node *c, *n;
unsigned i;
for (i = 0; i < t->num_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
f(c->data);
}
}
void dm_hash_wipe(struct dm_hash_table *t)
{
_free_nodes(t);
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
t->num_nodes = 0u;
}
char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
struct dm_hash_node *n)
{
return n->key;
}
void *dm_hash_get_data(struct dm_hash_table *t __attribute__((unused)),
struct dm_hash_node *n)
{
return n->data;
}
static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
{
struct dm_hash_node *c = NULL;
unsigned i;
for (i = s; i < t->num_slots && !c; i++)
c = t->slots[i];
return c;
}
struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
{
return _next_slot(t, 0);
}
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
{
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1);
}

View File

@@ -1,94 +0,0 @@
#ifndef BASE_DATA_STRUCT_HASH_H
#define BASE_DATA_STRUCT_HASH_H
#include <stdint.h>
//----------------------------------------------------------------
struct dm_hash_table;
struct dm_hash_node;
typedef void (*dm_hash_iterate_fn) (void *data);
struct dm_hash_table *dm_hash_create(unsigned size_hint)
__attribute__((__warn_unused_result__));
void dm_hash_destroy(struct dm_hash_table *t);
void dm_hash_wipe(struct dm_hash_table *t);
void *dm_hash_lookup(struct dm_hash_table *t, const char *key);
int dm_hash_insert(struct dm_hash_table *t, const char *key, void *data);
void dm_hash_remove(struct dm_hash_table *t, const char *key);
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key, uint32_t len);
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key, uint32_t len,
void *data);
void dm_hash_remove_binary(struct dm_hash_table *t, const void *key, uint32_t len);
unsigned dm_hash_get_num_entries(struct dm_hash_table *t);
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f);
char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n);
void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n);
struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t);
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n);
/*
* dm_hash_insert() replaces the value of an existing
* entry with a matching key if one exists. Otherwise
* it adds a new entry.
*
* dm_hash_insert_with_val() inserts a new entry if
* another entry with the same key already exists.
* val_len is the size of the data being inserted.
*
* If two entries with the same key exist,
* (added using dm_hash_insert_allow_multiple), then:
* . dm_hash_lookup() returns the first one it finds, and
* dm_hash_lookup_with_val() returns the one with a matching
* val_len/val.
* . dm_hash_remove() removes the first one it finds, and
* dm_hash_remove_with_val() removes the one with a matching
* val_len/val.
*
* If a single entry with a given key exists, and it has
* zero val_len, then:
* . dm_hash_lookup() returns it
* . dm_hash_lookup_with_val(val_len=0) returns it
* . dm_hash_remove() removes it
* . dm_hash_remove_with_val(val_len=0) removes it
*
* dm_hash_lookup_with_count() is a single call that will
* both lookup a key's value and check if there is more
* than one entry with the given key.
*
* (It is not meant to retrieve all the entries with the
* given key. In the common case where a single entry exists
* for the key, it is useful to have a single call that will
* both look up the value and indicate if multiple values
* exist for the key.)
*
* dm_hash_lookup_with_count:
* . If no entries exist, the function returns NULL, and
* the count is set to 0.
* . If only one entry exists, the value of that entry is
* returned and count is set to 1.
* . If N entries exists, the value of the first entry is
* returned and count is set to N.
*/
void *dm_hash_lookup_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len);
void dm_hash_remove_with_val(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len);
int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
const void *val, uint32_t val_len);
void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *count);
#define dm_hash_iterate(v, h) \
for (v = dm_hash_get_first((h)); v; \
v = dm_hash_get_next((h), v))
//----------------------------------------------------------------
#endif

View File

@@ -1,170 +0,0 @@
/*
* Copyright (C) 2001-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 Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "list.h"
#include <assert.h>
#include <stdlib.h>
/*
* Initialise a list before use.
* The list head's next and previous pointers point back to itself.
*/
void dm_list_init(struct dm_list *head)
{
head->n = head->p = head;
}
/*
* Insert an element before 'head'.
* If 'head' is the list head, this adds an element to the end of the list.
*/
void dm_list_add(struct dm_list *head, struct dm_list *elem)
{
assert(head->n);
elem->n = head;
elem->p = head->p;
head->p->n = elem;
head->p = elem;
}
/*
* Insert an element after 'head'.
* If 'head' is the list head, this adds an element to the front of the list.
*/
void dm_list_add_h(struct dm_list *head, struct dm_list *elem)
{
assert(head->n);
elem->n = head->n;
elem->p = head;
head->n->p = elem;
head->n = elem;
}
/*
* Delete an element from its list.
* Note that this doesn't change the element itself - it may still be safe
* to follow its pointers.
*/
void dm_list_del(struct dm_list *elem)
{
elem->n->p = elem->p;
elem->p->n = elem->n;
}
/*
* Remove an element from existing list and insert before 'head'.
*/
void dm_list_move(struct dm_list *head, struct dm_list *elem)
{
dm_list_del(elem);
dm_list_add(head, elem);
}
/*
* Is the list empty?
*/
int dm_list_empty(const struct dm_list *head)
{
return head->n == head;
}
/*
* Is this the first element of the list?
*/
int dm_list_start(const struct dm_list *head, const struct dm_list *elem)
{
return elem->p == head;
}
/*
* Is this the last element of the list?
*/
int dm_list_end(const struct dm_list *head, const struct dm_list *elem)
{
return elem->n == head;
}
/*
* Return first element of the list or NULL if empty
*/
struct dm_list *dm_list_first(const struct dm_list *head)
{
return (dm_list_empty(head) ? NULL : head->n);
}
/*
* Return last element of the list or NULL if empty
*/
struct dm_list *dm_list_last(const struct dm_list *head)
{
return (dm_list_empty(head) ? NULL : head->p);
}
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem)
{
return (dm_list_start(head, elem) ? NULL : elem->p);
}
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem)
{
return (dm_list_end(head, elem) ? NULL : elem->n);
}
/*
* Return the number of elements in a list by walking it.
*/
unsigned int dm_list_size(const struct dm_list *head)
{
unsigned int s = 0;
const struct dm_list *v;
dm_list_iterate(v, head)
s++;
return s;
}
/*
* Join two lists together.
* This moves all the elements of the list 'head1' to the end of the list
* 'head', leaving 'head1' empty.
*/
void dm_list_splice(struct dm_list *head, struct dm_list *head1)
{
assert(head->n);
assert(head1->n);
if (dm_list_empty(head1))
return;
head1->p->n = head;
head1->n->p = head->p;
head->p->n = head1->n;
head->p = head1->p;
dm_list_init(head1);
}

View File

@@ -1,209 +0,0 @@
#ifndef BASE_DATA_STRUCT_LIST_H
#define BASE_DATA_STRUCT_LIST_H
//----------------------------------------------------------------
/*
* A list consists of a list head plus elements.
* Each element has 'next' and 'previous' pointers.
* The list head's pointers point to the first and the last element.
*/
struct dm_list {
struct dm_list *n, *p;
};
/*
* String list.
*/
struct dm_str_list {
struct dm_list list;
const char *str;
};
/*
* Initialise a list before use.
* The list head's next and previous pointers point back to itself.
*/
#define DM_LIST_HEAD_INIT(name) { &(name), &(name) }
#define DM_LIST_INIT(name) struct dm_list name = DM_LIST_HEAD_INIT(name)
void dm_list_init(struct dm_list *head);
/*
* Insert an element before 'head'.
* If 'head' is the list head, this adds an element to the end of the list.
*/
void dm_list_add(struct dm_list *head, struct dm_list *elem);
/*
* Insert an element after 'head'.
* If 'head' is the list head, this adds an element to the front of the list.
*/
void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
/*
* Delete an element from its list.
* Note that this doesn't change the element itself - it may still be safe
* to follow its pointers.
*/
void dm_list_del(struct dm_list *elem);
/*
* Remove an element from existing list and insert before 'head'.
*/
void dm_list_move(struct dm_list *head, struct dm_list *elem);
/*
* Join 'head1' to the end of 'head'.
*/
void dm_list_splice(struct dm_list *head, struct dm_list *head1);
/*
* Is the list empty?
*/
int dm_list_empty(const struct dm_list *head);
/*
* Is this the first element of the list?
*/
int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
/*
* Is this the last element of the list?
*/
int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
/*
* Return first element of the list or NULL if empty
*/
struct dm_list *dm_list_first(const struct dm_list *head);
/*
* Return last element of the list or NULL if empty
*/
struct dm_list *dm_list_last(const struct dm_list *head);
/*
* Return the previous element of the list, or NULL if we've reached the start.
*/
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
/*
* Return the next element of the list, or NULL if we've reached the end.
*/
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
/*
* Given the address v of an instance of 'struct dm_list' called 'head'
* contained in a structure of type t, return the containing structure.
*/
#define dm_list_struct_base(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
/*
* Given the address v of an instance of 'struct dm_list list' contained in
* a structure of type t, return the containing structure.
*/
#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
/*
* Given the address v of one known element e in a known structure of type t,
* return another element f.
*/
#define dm_struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
/*
* Given the address v of a known element e in a known structure of type t,
* return the list head 'list'
*/
#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
/*
* Set v to each element of a list in turn.
*/
#define dm_list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n)
/*
* Set v to each element in a list in turn, starting from the element
* in front of 'start'.
* You can use this to 'unwind' a list_iterate and back out actions on
* already-processed elements.
* If 'start' is 'head' it walks the list backwards.
*/
#define dm_list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
/*
* A safe way to walk a list and delete and free some elements along
* the way.
* t must be defined as a temporary variable of the same type as v.
*/
#define dm_list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The 'struct dm_list' variable within the containing structure is 'field'.
*/
#define dm_list_iterate_items_gen(v, head, field) \
for (v = dm_list_struct_base((head)->n, __typeof__(*v), field); \
&v->field != (head); \
v = dm_list_struct_base(v->field.n, __typeof__(*v), field))
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct dm_list list' within the containing structure.
*/
#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The 'struct dm_list' variable within the containing structure is 'field'.
* t must be defined as a temporary variable of the same type as v.
*/
#define dm_list_iterate_items_gen_safe(v, t, head, field) \
for (v = dm_list_struct_base((head)->n, __typeof__(*v), field), \
t = dm_list_struct_base(v->field.n, __typeof__(*v), field); \
&v->field != (head); \
v = t, t = dm_list_struct_base(v->field.n, __typeof__(*v), field))
/*
* Walk a list, setting 'v' in turn to the containing structure of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct dm_list list' within the containing structure.
* t must be defined as a temporary variable of the same type as v.
*/
#define dm_list_iterate_items_safe(v, t, head) \
dm_list_iterate_items_gen_safe(v, t, (head), list)
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct dm_list' variable within the containing structure is 'field'.
*/
#define dm_list_iterate_back_items_gen(v, head, field) \
for (v = dm_list_struct_base((head)->p, __typeof__(*v), field); \
&v->field != (head); \
v = dm_list_struct_base(v->field.p, __typeof__(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct dm_list list' within the containing structure.
*/
#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
/*
* Return the number of elements in a list by walking it.
*/
unsigned int dm_list_size(const struct dm_list *head);
//----------------------------------------------------------------
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,256 +0,0 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "radix-tree.h"
#include "base/memory/container_of.h"
#include "base/memory/zalloc.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
//----------------------------------------------------------------
// This implementation is based around nested binary trees. Very
// simple (and hopefully correct).
struct node {
struct node *left;
struct node *right;
uint8_t key;
struct node *center;
bool has_value;
union radix_value value;
};
struct radix_tree {
radix_value_dtr dtr;
void *dtr_context;
struct node *root;
};
struct radix_tree *
radix_tree_create(radix_value_dtr dtr, void *dtr_context)
{
struct radix_tree *rt = zalloc(sizeof(*rt));
if (rt) {
rt->dtr = dtr;
rt->dtr_context = dtr_context;
}
return rt;
}
// Returns the number of entries in the tree
static unsigned _destroy_tree(struct node *n, radix_value_dtr dtr, void *context)
{
unsigned r;
if (!n)
return 0;
r = _destroy_tree(n->left, dtr, context);
r += _destroy_tree(n->right, dtr, context);
r += _destroy_tree(n->center, dtr, context);
if (n->has_value) {
if (dtr)
dtr(context, n->value);
r++;
}
free(n);
return r;
}
void radix_tree_destroy(struct radix_tree *rt)
{
_destroy_tree(rt->root, rt->dtr, rt->dtr_context);
free(rt);
}
static unsigned _count(struct node *n)
{
unsigned r;
if (!n)
return 0;
r = _count(n->left);
r += _count(n->right);
r += _count(n->center);
if (n->has_value)
r++;
return r;
}
unsigned radix_tree_size(struct radix_tree *rt)
{
return _count(rt->root);
}
static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
{
struct node *n = *pn;
if (!n || (kb == ke))
return pn;
if (*kb < n->key)
return _lookup(&n->left, kb, ke);
else if (*kb > n->key)
return _lookup(&n->right, kb, ke);
else
return _lookup(&n->center, kb + 1, ke);
}
static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_value v)
{
struct node *n = *pn;
if (!n) {
n = zalloc(sizeof(*n));
if (!n)
return false;
n->key = *kb;
*pn = n;
}
if (kb == ke) {
n->has_value = true;
n->value = v;
return true;
}
if (*kb < n->key)
return _insert(&n->left, kb, ke, v);
else if (*kb > n->key)
return _insert(&n->right, kb, ke, v);
else
return _insert(&n->center, kb + 1, ke, v);
}
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v)
{
return _insert(&rt->root, kb, ke, v);
}
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
{
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (!n || !n->has_value)
return false;
else {
if (rt->dtr)
rt->dtr(rt->dtr_context, n->value);
if (n->left || n->center || n->right) {
n->has_value = false;
return true;
} else {
// FIXME: delete parent if this was the last entry
free(n);
*pn = NULL;
}
return true;
}
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
{
struct node **pn;
unsigned count;
pn = _lookup(&rt->root, kb, ke);
if (*pn) {
count = _destroy_tree(*pn, rt->dtr, rt->dtr_context);
*pn = NULL;
}
return count;
}
bool
radix_tree_lookup(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value *result)
{
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (n && n->has_value) {
*result = n->value;
return true;
} else
return false;
}
static void _iterate(struct node *n, struct radix_tree_iterator *it)
{
if (!n)
return;
_iterate(n->left, it);
if (n->has_value)
// FIXME: fill out the key
it->visit(it, NULL, NULL, n->value);
_iterate(n->center, it);
_iterate(n->right, it);
}
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
{
if (kb == ke)
_iterate(rt->root, it);
else {
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (n) {
if (n->has_value)
it->visit(it, NULL, NULL, n->value);
_iterate(n->center, it);
}
}
}
bool radix_tree_is_well_formed(struct radix_tree *rt)
{
return true;
}
void radix_tree_dump(struct radix_tree *rt, FILE *out)
{
}
//----------------------------------------------------------------

View File

@@ -1,21 +0,0 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//----------------------------------------------------------------
#ifdef SIMPLE_RADIX_TREE
#include "base/data-struct/radix-tree-simple.c"
#else
#include "base/data-struct/radix-tree-adaptive.c"
#endif
//----------------------------------------------------------------

View File

@@ -1,64 +0,0 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BASE_DATA_STRUCT_RADIX_TREE_H
#define BASE_DATA_STRUCT_RADIX_TREE_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
//----------------------------------------------------------------
struct radix_tree;
union radix_value {
void *ptr;
uint64_t n;
};
typedef void (*radix_value_dtr)(void *context, union radix_value v);
// dtr will be called on any deleted entries. dtr may be NULL.
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context);
void radix_tree_destroy(struct radix_tree *rt);
unsigned radix_tree_size(struct radix_tree *rt);
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke);
// Returns the number of values removed
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *prefix_b, uint8_t *prefix_e);
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result);
// The radix tree stores entries in lexicographical order. Which means
// we can iterate entries, in order. Or iterate entries with a particular
// prefix.
struct radix_tree_iterator {
// Returns false if the iteration should end.
bool (*visit)(struct radix_tree_iterator *it,
uint8_t *kb, uint8_t *ke, union radix_value v);
};
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it);
// Checks that some constraints on the shape of the tree are
// being held. For debug only.
bool radix_tree_is_well_formed(struct radix_tree *rt);
void radix_tree_dump(struct radix_tree *rt, FILE *out);
//----------------------------------------------------------------
#endif

View File

@@ -1,23 +0,0 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BASE_MEMORY_CONTAINER_OF_H
#define BASE_MEMORY_CONTAINER_OF_H
//----------------------------------------------------------------
#define container_of(v, t, head) \
((t *)((const char *)(v) - (const char *)&((t *) 0)->head))
//----------------------------------------------------------------
#endif

View File

@@ -1,27 +0,0 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
// modify, copy, or redistribute it subject to the terms and conditions
// of the GNU Lesser General Public License v.2.1.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BASE_MEMORY_ZALLOC_H
#define BASE_MEMORY_ZALLOC_H
#include <stdlib.h>
//----------------------------------------------------------------
static inline void *zalloc(size_t len)
{
return calloc(1, len);
}
//----------------------------------------------------------------
#endif

6
conf/.gitignore vendored
View File

@@ -1,6 +0,0 @@
command_profile_template.profile
example.conf
lvmlocal.conf
metadata_profile_template.profile
configure.h
lvm-version.h

View File

@@ -1,60 +0,0 @@
#
# Copyright (C) 2004-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CONFSRC=example.conf
CONFDEST=lvm.conf
CONFLOCAL=lvmlocal.conf
PROFILE_TEMPLATES=command_profile_template.profile metadata_profile_template.profile
PROFILES=$(PROFILE_TEMPLATES) \
$(srcdir)/cache-mq.profile \
$(srcdir)/cache-smq.profile \
$(srcdir)/thin-generic.profile \
$(srcdir)/thin-performance.profile \
$(srcdir)/vdo-small.profile \
$(srcdir)/lvmdbusd.profile
include $(top_builddir)/make.tmpl
.PHONY: install_conf install_localconf install_profiles
generate:
$(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withgeneralpreamble --withcomments --ignorelocal --withspaces > example.conf.in
$(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withlocalpreamble --withcomments --withspaces local > lvmlocal.conf.in
install_conf: $(CONFSRC)
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST)"; \
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFDEST); \
fi
install_localconf: $(CONFLOCAL)
@if [ ! -e $(confdir)/$(CONFLOCAL) ]; then \
echo "$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL)"; \
$(INSTALL_WDATA) -D $< $(confdir)/$(CONFLOCAL); \
fi
install_profiles: $(PROFILES)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(profiledir)
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/
install_lvm2: install_conf install_localconf install_profiles
install: install_lvm2
DISTCLEAN_TARGETS += $(CONFSRC) $(CONFLOCAL) $(PROFILE_TEMPLATES)

View File

@@ -1,20 +0,0 @@
# Demo configuration 'mq' cache policy
#
# Note: This policy has been deprecated in favor of the smq policy
# keyword "default" means, setting is left with kernel defaults.
#
allocation {
cache_pool_chunk_size = 64
cache_mode = "writethrough"
cache_policy = "mq"
cache_settings {
mq {
sequential_threshold = "default" # #nr_sequential_ios
random_threshold = "default" # #nr_random_ios
read_promote_adjustment = "default"
write_promote_adjustment = "default"
discard_promote_adjustment = "default"
}
}
}

View File

@@ -1,14 +0,0 @@
# Demo configuration 'smq' cache policy
#
# The stochastic multi-queue (smq) policy addresses some of the problems
# with the multiqueue (mq) policy and uses less memory.
#
allocation {
cache_pool_chunk_size = 64
cache_mode = "writethrough"
cache_policy = "smq"
cache_settings {
# currently no settings for "smq" policy
}
}

View File

@@ -1,74 +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.
#
allocation {
cache_mode="writethrough"
cache_settings {
}
}
log {
report_command_log=0
command_log_sort="log_seq_num"
command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
command_log_selection="!(log_type=status && message=success)"
}
global {
units="h"
si_unit_consistency=1
suffix=1
lvdisplay_shows_full_device_path=0
}
report {
output_format="basic"
compact_output=0
compact_output_cols=""
aligned=1
buffered=1
headings=1
separator=" "
list_item_separator=","
prefixes=0
quoted=1
columns_as_rows=0
binary_values_as_numeric=0
time_format="%Y-%m-%d %T %z"
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"
vgs_cols_full="vg_all"
pvs_cols_full="pv_all"
lvs_cols_full="lv_all"
pvsegs_cols_full="pvseg_all,pv_uuid,lv_uuid"
segs_cols_full="seg_all,lv_uuid"
vgs_sort_full="vg_name"
pvs_sort_full="pv_name"
lvs_sort_full="vg_name,lv_name"
pvsegs_sort_full="pv_uuid,pvseg_start"
segs_sort_full="lv_uuid,seg_start"
mark_hidden_devices=1
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +0,0 @@
#
# DO NOT EDIT THIS FILE!
#
# LVM configuration profile used by lvmdbusd daemon.
#
# This sets up LVM to produce output in the most suitable format for processing
# by lvmdbusd daemon which utilizes LVM shell to execute LVM commands.
#
# Do not edit this file in any way. This profile is distributed together with
# lvmdbusd and it contains configuration that is important for lvmdbusd to
# cooperate and interface with LVM correctly.
#
global {
# use bytes for expected and deterministic output
units=b
# no need for suffix if we have units set
suffix=0
}
report {
compact_output=0
compact_output_cols=""
binary_values_as_numeric=0
# time in number of seconds since the Epoch
time_format="%s"
mark_hidden_devices=1
# lvmdbusd expects JSON output
output_format=json
# *_cols_full for lvm fullreport's fields which lvmdbusd relies on to update its state
vgs_cols_full="vg_name,vg_uuid,vg_fmt,vg_size,vg_free,vg_sysid,vg_extent_size,vg_extent_count,vg_free_count,vg_profile,max_lv,max_pv,pv_count,lv_count,snap_count,vg_seqno,vg_mda_count,vg_mda_free,vg_mda_size,vg_mda_used_count,vg_attr,vg_tags"
pvs_cols_full="pv_name,pv_uuid,pv_fmt,pv_size,pv_free,pv_used,dev_size,pv_mda_size,pv_mda_free,pv_ba_start,pv_ba_size,pe_start,pv_pe_count,pv_pe_alloc_count,pv_attr,pv_tags,vg_name,vg_uuid"
lvs_cols_full="lv_uuid,lv_name,lv_path,lv_size,vg_name,pool_lv_uuid,pool_lv,origin_uuid,origin,data_percent,lv_attr,lv_tags,vg_uuid,lv_active,data_lv,metadata_lv,lv_parent,lv_role,lv_layout"
pvsegs_cols_full="pvseg_start,pvseg_size,segtype,pv_uuid,lv_uuid,pv_name"
segs_cols_full="seg_pe_ranges,segtype,lv_uuid"
vgs_sort_full="vg_name"
pvs_sort_full="pv_name"
lvs_sort_full="vg_name,lv_name"
pvsegs_sort_full="pv_uuid,pvseg_start"
segs_sort_full="lv_uuid,seg_start"
}
log {
# lvmdbusd relies on command log report to inspect LVM command's execution status
report_command_log=1
# display only outermost LVM shell-related log that lvmdbusd inspects first after LVM command execution (it calls 'lastlog' for more detailed log afterwards if needed)
command_log_selection="log_context=shell"
command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
command_log_sort="log_seq_num"
}

View File

@@ -1,57 +0,0 @@
# This is a local configuration file template for the LVM2 system
# which should be installed as @DEFAULT_SYS_DIR@/lvmlocal.conf .
#
# Refer to 'man lvm.conf' for information about the file layout.
#
# To put this file in a different directory and override
# @DEFAULT_SYS_DIR@ set the environment variable LVM_SYSTEM_DIR before
# running the tools.
#
# The lvmlocal.conf file is normally expected to contain only the
# "local" section which contains settings that should not be shared or
# repeated among different hosts. (But if other sections are present,
# they *will* get processed. Settings in this file override equivalent
# ones in lvm.conf and are in turn overridden by ones in any enabled
# lvm_<tag>.conf files.)
#
# Please take care that each setting only appears once if uncommenting
# example settings in this file and never copy this file between hosts.
# Configuration section local.
# LVM settings that are specific to the local host.
local {
# Configuration option local/system_id.
# Defines the local system ID for lvmlocal mode.
# This is used when global/system_id_source is set to 'lvmlocal' in the
# main configuration file, e.g. lvm.conf. When used, it must be set to
# a unique value among all hosts sharing access to the storage,
# e.g. a host name.
#
# Example
# Set no system ID:
# system_id = ""
# Set the system_id to a specific name:
# system_id = "host1"
#
# This configuration option has an automatic default value.
# system_id = ""
# Configuration option local/extra_system_ids.
# A list of extra VG system IDs the local host can access.
# VGs with the system IDs listed here (in addition to the host's own
# system ID) can be fully accessed by the local host. (These are
# system IDs that the host sees in VGs, not system IDs that identify
# the local host, which is determined by system_id_source.)
# Use this only after consulting 'man lvmsystemid' to be certain of
# correct usage and possible dangers.
# This configuration option does not have a default value defined.
# Configuration option local/host_id.
# The lvmlockd sanlock host_id.
# This must be unique among all hosts, and must be between 1 and 2000.
# Applicable only if LVM is compiled with lockd support
# This configuration option has an automatic default value.
# host_id = 0
}

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=128
}
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
}

View File

@@ -1,24 +0,0 @@
# Demo configuration for 'VDO' using less memory.
# ~lvmconfig --type full | grep vdo
allocation {
vdo_use_compression=1
vdo_use_deduplication=1
vdo_use_metadata_hints=1
vdo_minimum_io_size=4096
vdo_block_map_cache_size_mb=128
vdo_block_map_period=16380
vdo_check_point_frequency=0
vdo_use_sparse_index=0
vdo_index_memory_size_mb=256
vdo_slab_size_mb=2048
vdo_ack_threads=1
vdo_bio_threads=1
vdo_bio_rotation=64
vdo_cpu_threads=2
vdo_hash_zone_threads=1
vdo_logical_threads=1
vdo_physical_threads=1
vdo_write_policy="auto"
vdo_max_discard=1
}

16156
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

144
configure.in Normal file
View File

@@ -0,0 +1,144 @@
################################################################################
##
## Copyright 1999-2000 Sistina Software, Inc.
##
## This is free software released under the GNU General Public License.
## There is no warranty for this software. See the file COPYING for
## details.
##
## See the file CONTRIBUTORS for a list of contributors.
##
## This file is maintained by:
## AJ Lewis <lewis@sistina.com>
##
## File name: configure.in
##
## Description: Input file for autoconf. Generates the configure script
## that tries to keep everything nice and portable. It also
## simplifies distribution package building considerably.
################################################################################
dnl Process this file with autoconf to produce a configure script.
AC_INIT(lib/device/dev-cache.h)
dnl setup the directory where autoconf has auxilary files
AC_CONFIG_AUX_DIR(autoconf)
dnl Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_RANLIB
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_STRUCT_ST_RDEV
AC_HEADER_TIME
dnl -- prefix is /usr by default, the exec_prefix default is setup later
AC_PREFIX_DEFAULT(/usr)
dnl -- setup the ownership of the files
AC_ARG_WITH(user,
[ --with-user=USER Set the owner of installed files ],
[ OWNER="$withval" ],
[ OWNER="root" ])
dnl -- setup the group ownership of the files
AC_ARG_WITH(group,
[ --with-group=GROUP Set the group owner of installed files ],
[ GROUP="$withval" ],
[ GROUP="root" ])
dnl -- Where the linux src tree is
AC_ARG_WITH(kernel_dir,
[ --with-kernel_dir=DIR linux kernel source in DIR [/usr/src/linux]],
[ kernel_dir="$withval" ],
[ kernel_dir=/usr/src/linux ])
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=)
dnl Enables staticly linked tools
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to the liblvm library
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
dnl Disable readline
AC_ARG_ENABLE(readline, [ --disable-readline Disable readline support], \
READLINE=$enableval, READLINE=yes)
dnl Mess with default exec_prefix
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
then exec_prefix="";
fi;
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(mkdir rmdir uname)
dnl check for termcap (Shamelessly copied from parted 1.4.17)
if test x$READLINE = xyes; then
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
AC_MSG_ERROR(
termcap could not be found which is required for the
--enable-readline option (which is enabled by default). Either disable readline
support with --disable-readline or download and install termcap from:
ftp.gnu.org/gnu/termcap
Note: if you are using precompiled packages you will also need the development
package as well (which may be called termcap-devel or something similar).
Note: (n)curses also seems to work as a substitute for termcap. This was
not found either - but you could try installing that as well.
)
exit
)
fi
dnl Check for readline (Shamelessly copied from parted 1.4.17)
if test x$READLINE = xyes; then
AC_CHECK_LIB(readline, readline, ,
AC_MSG_ERROR(
GNU Readline could not be found which is required for the
--enable-readline option (which is enabled by default). Either disable readline
support with --disable-readline or download and install readline from:
ftp.gnu.org/gnu/readline
Note: if you are using precompiled packages you will also need the development
package as well (which may be called readline-devel or something similar).
)
exit
)
fi
AC_SUBST(JOBS)
AC_SUBST(STATIC_LINK)
AC_SUBST(READLINE)
AC_SUBST(kernel_dir)
AC_SUBST(OWNER)
AC_SUBST(GROUP)
AC_SUBST(LIBS)
dnl First and last lines should not contain files to generate in order to
dnl keep utility scripts running properly
AC_OUTPUT( \
Makefile \
make.tmpl \
include/Makefile \
lib/Makefile \
man/Makefile \
tools/Makefile \
test/mm/Makefile \
test/device/Makefile \
test/format1/Makefile \
test/regex/Makefile \
test/filters/Makefile \
)

View File

@@ -1,146 +0,0 @@
/*
* Copyright (C) 2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Coverity usage:
*
* translate model into xml
* cov-make-library -of coverity_model.xml coverity_model.c
*
* compile (using outdir 'cov'):
* cov-build --dir=cov make CC=gcc
*
* analyze (agressively, using 'cov')
* cov-analyze --dir cov --wait-for-license --hfa --concurrency --enable-fnptr --enable-constraint-fpp --security --all --aggressiveness-level=high --field-offset-escape --user-model-file=coverity/coverity_model.xml
*
* generate html output (to 'html' from 'cov'):
* cov-format-errors --dir cov --html-output html
*/
struct lv_segment;
struct logical_volume;
struct lv_segment *first_seg(const struct logical_volume *lv)
{
return ((struct lv_segment **)lv)[0];
}
struct lv_segment *last_seg(const struct logical_volume *lv)
{
return ((struct lv_segment **)lv)[0];
}
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
{
return "STRING";
}
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
{
if (lv)
return lv;
__coverity_panic__();
}
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, size_t n)
{
const char *s = src;
char *d = dest;
while (n-- > 0)
if ((*d++ = *s++) == (char) c)
return d;
return 0;
}
/*
* 2 lines bellow needs to be placed in coverity/config/user_nodefs.h
* Not sure about any other way.
* Without them, coverity shows warning since x86 system header files
* are using inline assembly to reset fdset
*/
//#nodef FD_ZERO model_FD_ZERO
//void model_FD_ZERO(void *fdset);
void model_FD_ZERO(void *fdset)
{
unsigned i;
for (i = 0; i < 1024 / 8 / sizeof(long); ++i)
((long*)fdset)[i] = 0;
}
/* Resent Coverity reports quite weird errors... */
int *__errno_location(void)
{
}
const unsigned short **__ctype_b_loc (void)
{
}
/*
* Added extra pointer check to not need these models,
* for now just keep then in file
*/
/*
struct cmd_context;
struct profile;
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
{
return "text";
}
const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, struct profile *profile)
{
return "text";
}
*/
/*
* Until fixed coverity case# 00531860:
* A FORWARD_NULL false positive on a recursive function call
*
* model also these functions:
*/
/*
const struct dm_config_node;
const struct dm_config_node *find_config_tree_array(struct cmd_context *cmd, int id, struct profile *profile)
{
const struct dm_config_node *cn;
return cn;
}
const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile)
{
const struct dm_config_node *cn;
return cn;
}
int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile)
{
int b;
return b;
}
*/

View File

@@ -1,51 +0,0 @@
#
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
.PHONY: dmeventd cmirrord lvmpolld lvmlockd
ifeq ("@BUILD_CMIRRORD@", "yes")
SUBDIRS += cmirrord
endif
ifeq ("@BUILD_DMEVENTD@", "yes")
SUBDIRS += dmeventd
ifneq ("$(CFLOW_CMD)", "")
daemons.cflow: dmeventd.cflow
endif
endif
ifeq ("@BUILD_LVMPOLLD@", "yes")
SUBDIRS += lvmpolld
endif
ifeq ("@BUILD_LVMLOCKD@", "yes")
SUBDIRS += lvmlockd
endif
ifeq ("@BUILD_LVMDBUSD@", "yes")
SUBDIRS += lvmdbusd
endif
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS = cmirrord dmeventd lvmpolld lvmlockd lvmdbusd
endif
include $(top_builddir)/make.tmpl
ifeq ("@BUILD_DMEVENTD@", "yes")
device-mapper: dmeventd.device-mapper
endif

View File

@@ -1 +0,0 @@
cmirrord

View File

@@ -1,38 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CPG_LIBS = @CPG_LIBS@
CPG_CFLAGS = @CPG_CFLAGS@
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
TARGETS = cmirrord
include $(top_builddir)/make.tmpl
LMLIBS += $(CPG_LIBS)
CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
cmirrord: $(OBJECTS)
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install: $(TARGETS)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord

View File

@@ -1,292 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "logging.h"
#include "common.h"
#include "functions.h"
#include "link_mon.h"
#include "local.h"
#include <getopt.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);
static void usage (FILE *dest)
{
fprintf (dest, "Usage: cmirrord [options]\n"
" -f, --foreground stay in the foreground, log to the terminal\n"
" -h, --help print this help\n");
}
int main(int argc, char *argv[])
{
int foreground_mode = 0;
struct option longopts[] = {
{ "foreground", no_argument, NULL, 'f' },
{ "help" , no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
int opt;
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
switch (opt) {
case 'f':
foreground_mode = 1;
break;
case 'h':
usage (stdout);
exit (0);
default:
usage (stderr);
exit (2);
}
}
if (optind < argc) {
usage (stderr);
exit (2);
}
if (!foreground_mode)
daemonize();
init_all();
/* Parent can now exit, we're ready to handle requests */
if (!foreground_mode)
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);
}
/*
* init_all
*
* Initialize modules. Exit on failure.
*/
static void init_all(void)
{
int r;
(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;
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_CLOG_CLUSTER_H
#define _LVM_CLOG_CLUSTER_H
#include "libdm/misc/dm-log-userspace.h"
#include "libdm/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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,210 +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 "lib/mm/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]);
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_CLOG_FUNCTIONS_H
#define _LVM_CLOG_FUNCTIONS_H
#include "device_mapper/misc/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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,73 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_CLOG_LOGGING_H
#define _LVM_CLOG_LOGGING_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 +0,0 @@
dmeventd

View File

@@ -1,114 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
dmeventd: $(LIB_SHARED) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
dmeventd.static: $(LIB_STATIC) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
INSTALL_LIB_TARGETS += install_pkgconfig
endif
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-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
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
install_lib_dynamic: install_lib_shared
install_lib_static: $(LIB_STATIC)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
install_lib: $(INSTALL_LIB_TARGETS)
install_dmeventd_dynamic: dmeventd
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmeventd_static: dmeventd.static
@echo " [INSTALL] $<"
$(Q) $(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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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,997 +0,0 @@
/*
* Copyright (C) 2005-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libdevmapper-event.h"
#include "dmeventd.h"
#include "libdm/misc/dm-logging.h"
#include "base/memory/zalloc.h"
#include "lib/misc/intl.h"
#include <fcntl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
#include <pthread.h>
#include <syslog.h>
#include <unistd.h>
static int _debug_level = 0;
static int _use_syslog = 0;
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)
{
free(dmevh->dev_name);
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 = 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);
free(dmevh->dso);
free(dmevh->dmeventd_path);
free(dmevh);
}
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
{
if (!dmeventd_path) /* noop */
return 0;
free(dmevh->dmeventd_path);
if (!(dmevh->dmeventd_path = 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;
free(dmevh->dso);
if (!(dmevh->dso = 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 = 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 = 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;
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 = malloc(msg->size);
size = msg->size;
bytes = 0;
header = 0;
}
}
if (bytes != size) {
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;
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;
free(msg->data);
msg->data = NULL;
return -EIO;
}
do {
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 };
/*
* FIXME Explicitly verify the code's requirement that client_path is secure:
* - All parent directories owned by root without group/other write access unless sticky.
*/
/* If client fifo path exists, only use it if it is root-owned fifo mode 0600 */
if ((lstat(fifos->client_path, &statbuf) < 0)) {
if (errno == ENOENT)
/* Jump ahead if fifo does not already exist. */
goto start_server;
else {
log_sys_error("stat", fifos->client_path);
return 0;
}
} else if (!S_ISFIFO(statbuf.st_mode)) {
log_error("%s must be a fifo.", fifos->client_path);
return 0;
} else if (statbuf.st_uid) {
log_error("%s must be owned by uid 0.", fifos->client_path);
return 0;
} else if (statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO)) {
log_error("%s must have mode 0600.", 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) {
/* Should never happen if all the above checks passed. */
if ((fstat(fifos->client, &statbuf) < 0) ||
!S_ISFIFO(statbuf.st_mode) || statbuf.st_uid ||
(statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
return 0;
}
/* server is running and listening */
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
return 1;
}
if (errno != ENXIO && errno != ENOENT) {
/* 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)) {
ret = -ESRCH;
goto_out;
}
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
free(msg->data);
msg->data = 0;
if (!ret)
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
out:
/* 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-lvm2vdo.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;
}
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;
}
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 = 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);
free(id);
return 0;
}
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);
/* FIXME Distinguish errors connecting to daemon */
if ((ret = _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));
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;
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 = 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);
free(reply_dso);
reply_dso = NULL;
free(reply_uuid);
reply_uuid = NULL;
if (!(dmevh->dev_name = 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:
free(msg.data);
free(reply_dso);
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;
}
void dm_event_log_set(int debug_log_level, int use_syslog)
{
_debug_level = debug_log_level;
_use_syslog = use_syslog;
}
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,
const char *format, va_list ap)
{
static int _abort_on_internal_errors = -1;
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t start = 0;
const char *indent = "";
FILE *stream = log_stderr(level) ? stderr : stdout;
int prio;
time_t now;
int log_with_debug = 0;
if (subsys[0] == '#') {
/* Subsystems starting with '#' are logged
* only when debugging is enabled. */
log_with_debug++;
subsys++;
}
switch (log_level(level)) {
case _LOG_DEBUG:
/* Never shown without -ddd */
if (_debug_level < 3)
return;
prio = LOG_DEBUG;
indent = " ";
break;
case _LOG_INFO:
if (log_with_debug && _debug_level < 2)
return;
prio = LOG_INFO;
indent = " ";
break;
case _LOG_NOTICE:
if (log_with_debug && _debug_level < 1)
return;
prio = LOG_NOTICE;
indent = " ";
break;
case _LOG_WARN:
prio = LOG_WARNING;
break;
case _LOG_ERR:
prio = LOG_ERR;
stream = stderr;
break;
default:
prio = LOG_CRIT;
}
/* Serialize to keep lines readable */
pthread_mutex_lock(&_log_mutex);
if (_use_syslog) {
vsyslog(prio, format, ap);
} else {
now = time(NULL);
if (!start)
start = now;
now -= start;
if (_debug_level)
fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
(int)now / 60, (int)now % 60,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
if (_debug_level > 3)
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
fputc('\n', stream);
fflush(stream);
}
pthread_mutex_unlock(&_log_mutex);
if (_abort_on_internal_errors < 0)
/* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
_abort_on_internal_errors =
strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
if (_abort_on_internal_errors &&
!strncmp(format, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
abort();
}
#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'.",
msg.data);
free(msg.data);
return -EIO;
}
*timeout = atoi(p);
}
free(msg.data);
return ret;
}
#endif

View File

@@ -1,136 +0,0 @@
/*
* Copyright (C) 2005-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <stdarg.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);
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
void dm_event_log_set(int debug_log_level, int use_syslog);
/* Log messages acroding to current debug level */
__attribute__((format(printf, 6, 0)))
void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,
const char *format, va_list ap);
/* Macro to route print_log do dm_event_log() */
#define DM_EVENT_LOG_FN(subsys) \
void print_log(int level, const char *file, int line, int dm_errno_or_class,\
const char *format, ...)\
{\
va_list ap;\
va_start(ap, format);\
dm_event_log(subsys, level, file, line, dm_errno_or_class, format, ap);\
va_end(ap);\
}
/* 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,10 +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

View File

@@ -1,27 +0,0 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SUBDIRS += lvm2 snapshot raid thin mirror vdo
include $(top_builddir)/make.tmpl
snapshot: lvm2
mirror: lvm2
raid: lvm2
thin: lvm2
vdo: 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,30 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/tools
LIBS += $(DMEVENT_LIBS) $(PTHREAD_LIBS) @LVM2CMD_LIB@
SOURCES = dmeventd_lvm.c
LIB_SHARED = libdevmapper-event-lvm2.$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
install_lvm2: install_lib_shared
install: install_lvm2

View File

@@ -1,192 +0,0 @@
/*
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "tools/lvm2cmd.h"
#include <pthread.h>
/*
* 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;
static DM_LIST_INIT(_env_registry);
struct env_data {
struct dm_list list;
const char *cmd;
const char *data;
};
DM_EVENT_LOG_FN("#lvm")
static void _lvm2_print_log(int level, const char *file, int line,
int dm_errno_or_class, const char *msg)
{
print_log(level, file, line, dm_errno_or_class, "%s", msg);
}
/*
* Currently only one event can be processed at a time.
*/
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
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);
if (!_lvm_handle) {
lvm2_log_fn(_lvm2_print_log);
if (!(_lvm_handle = lvm2_init()))
goto out;
/*
* 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))) {
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
goto out;
}
lvm2_disable_dmeventd_monitoring(_lvm_handle);
/* FIXME Temporary: move to dmeventd core */
lvm2_run(_lvm_handle, "_memlock_inc");
log_debug("lvm plugin initilized.");
}
_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) {
log_debug("lvm plugin shuting down.");
lvm2_run(_lvm_handle, "_memlock_dec");
dm_pool_destroy(_mem_pool);
_mem_pool = NULL;
dm_list_init(&_env_registry);
lvm2_exit(_lvm_handle);
_lvm_handle = NULL;
log_debug("lvm plugin exited.");
}
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)
{
static char _internal_prefix[] = "_dmeventd_";
char *vg = NULL, *lv = NULL, *layer;
int r;
struct env_data *env_data;
const char *env = NULL;
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
log_error("Unable to determine VG name from %s.",
device);
return 0;
}
/* strip off the mirror component designations */
if ((layer = strstr(lv, "_mimagetmp")) ||
(layer = strstr(lv, "_mlog")))
*layer = '\0';
if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) {
/* check if ENVVAR wasn't already resolved */
dm_list_iterate_items(env_data, &_env_registry)
if (!strcmp(cmd, env_data->cmd)) {
env = env_data->data;
break;
}
if (!env) {
/* run lvm2 command to find out setting value */
dmeventd_lvm2_lock();
if (!dmeventd_lvm2_run(cmd) ||
!(env = getenv(cmd))) {
dmeventd_lvm2_unlock();
log_error("Unable to find configured command.");
return 0;
}
/* output of internal command passed via env var */
env = dm_pool_strdup(_mem_pool, env); /* copy with lock */
dmeventd_lvm2_unlock();
if (!env ||
!(env_data = dm_pool_zalloc(_mem_pool, sizeof(*env_data))) ||
!(env_data->cmd = dm_pool_strdup(_mem_pool, cmd))) {
log_error("Unable to allocate env memory.");
return 0;
}
env_data->data = env;
/* add to ENVVAR registry */
dm_list_add(&_env_registry, &env_data->list);
}
cmd = env;
}
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
dm_pool_free(mem, vg);
if (r < 0) {
log_error("Unable to form LVM command. (too long).");
return 0;
}
return 1;
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* 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);
#define dmeventd_lvm2_run_with_lock(cmdline) \
({\
int rc;\
dmeventd_lvm2_lock();\
rc = dmeventd_lvm2_run(cmdline);\
dmeventd_lvm2_unlock();\
rc;\
})
#define dmeventd_lvm2_init_with_pool(name, st) \
({\
struct dm_pool *mem;\
st = NULL;\
if (dmeventd_lvm2_init()) {\
if ((mem = dm_pool_create(name, 2048)) &&\
(st = dm_pool_zalloc(mem, sizeof(*st))))\
st->mem = mem;\
else {\
if (mem)\
dm_pool_destroy(mem);\
dmeventd_lvm2_exit();\
}\
}\
st;\
})
#define dmeventd_lvm2_exit_with_pool(pool) \
do {\
dm_pool_destroy(pool->mem);\
dmeventd_lvm2_exit();\
} while(0)
#endif /* _DMEVENTD_LVMWRAP_H */

View File

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

View File

@@ -1,35 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-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
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -1,211 +0,0 @@
/*
* Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/activate/activate.h"
/* FIXME Reformat to 80 char lines. */
#define ME_IGNORE 0
#define ME_INSYNC 1
#define ME_FAILURE 2
struct dso_state {
struct dm_pool *mem;
char cmd_lvconvert[512];
};
DM_EVENT_LOG_FN("mirr")
static void _process_status_code(dm_status_mirror_health_t health,
uint32_t major, uint32_t minor,
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)
*/
switch (health) {
case DM_STATUS_MIRROR_ALIVE:
return;
case DM_STATUS_MIRROR_FLUSH_FAILED:
log_error("%s device %u:%u flush failed.",
dev_type, major, minor);
*r = ME_FAILURE;
break;
case DM_STATUS_MIRROR_SYNC_FAILED:
log_error("%s device %u:%u sync failed.",
dev_type, major, minor);
break;
case DM_STATUS_MIRROR_READ_FAILED:
log_error("%s device %u:%u read failed.",
dev_type, major, minor);
break;
default:
log_error("%s device %u:%u has failed (%c).",
dev_type, major, minor, (char)health);
*r = ME_FAILURE;
break;
}
}
static int _get_mirror_event(struct dso_state *state, char *params)
{
int r = ME_INSYNC;
unsigned i;
struct dm_status_mirror *ms;
if (!dm_get_status_mirror(state->mem, params, &ms)) {
log_error("Unable to parse mirror status string.");
return ME_IGNORE;
}
/* Check for bad mirror devices */
for (i = 0; i < ms->dev_count; ++i)
_process_status_code(ms->devs[i].health,
ms->devs[i].major, ms->devs[i].minor,
i ? "Secondary mirror" : "Primary mirror", &r);
/* Check for bad disk log device */
for (i = 0; i < ms->log_count; ++i)
_process_status_code(ms->logs[i].health,
ms->logs[i].major, ms->logs[i].minor,
"Log", &r);
/* Ignore if not in-sync */
if ((r == ME_INSYNC) && (ms->insync_regions != ms->total_regions))
r = ME_IGNORE;
dm_pool_free(state->mem, ms);
return r;
}
static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
{
/* if repair goes OK, report success even if lvscan has failed */
if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
log_error("Repair of mirrored device %s failed.", device);
return 0;
}
log_info("Repair of mirrored device %s finished successfully.", device);
return 1;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
log_info("%s mapping lost.", device);
continue;
}
if (strcmp(target_type, TARGET_NAME_MIRROR)) {
log_info("%s has unmirrored portion.", device);
continue;
}
switch(_get_mirror_event(state, 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
*/
log_notice("%s is now in-sync.", device);
break;
case ME_FAILURE:
log_error("Device failure in %s.", device);
if (!_remove_failed_devices(state->cmd_lvconvert, device))
/* FIXME Why are all the error return codes unused? Get rid of them? */
log_error("Failed to remove faulty devices in %s.",
device);
/* Should check before warning user that device is now linear
else
log_notice("%s is now a linear device.",
device);
*/
break;
case ME_IGNORE:
break;
default:
/* FIXME Provide value then! */
log_warn("WARNING: %s received unknown event.", device);
}
} while (next);
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state;
if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
goto_bad;
/* CANNOT use --config as this disables cached content */
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --repair --use-policies", device))
goto_bad;
*user = state;
log_info("Monitoring mirror device %s for events.", device);
return 1;
bad:
log_error("Failed to monitor mirror %s.", device);
if (state)
dmeventd_lvm2_exit_with_pool(state);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring mirror device %s for events.",
device);
return 1;
}

View File

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

View File

@@ -1,34 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-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
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -1,182 +0,0 @@
/*
* Copyright (C) 2005-2017 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/config/defaults.h"
/* Hold enough elements for the mximum number of RAID images */
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
struct dso_state {
struct dm_pool *mem;
char cmd_lvconvert[512];
uint64_t raid_devs[RAID_DEVS_ELEMS];
int failed;
int warned;
};
DM_EVENT_LOG_FN("raid")
/* FIXME Reformat to 80 char lines. */
static int _process_raid_event(struct dso_state *state, char *params, const char *device)
{
struct dm_status_raid *status;
const char *d;
int dead = 0, r = 1;
uint32_t dev;
if (!dm_get_status_raid(state->mem, params, &status)) {
log_error("Failed to process status line for %s.", device);
return 0;
}
d = status->dev_health;
while ((d = strchr(d, 'D'))) {
dev = (uint32_t)(d - status->dev_health);
if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64)))) {
state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64));
log_warn("WARNING: Device #%u of %s array, %s, has failed.",
dev, status->raid_type, device);
}
d++;
dead = 1;
}
/*
* if we are converting from non-RAID to RAID (e.g. linear -> raid1)
* and too many original devices die, such that we cannot continue
* the "recover" operation, the sync action will go to "idle", the
* unsynced devs will remain at 'a', and the original devices will
* NOT SWITCH TO 'D', but will remain at 'A' - hoping to be revived.
*
* This is simply the way the kernel works...
*/
if (!strcmp(status->sync_action, "idle") &&
(status->dev_health[0] == 'a') &&
(status->insync_regions < status->total_regions)) {
log_error("Primary sources for new RAID, %s, have failed.",
device);
dead = 1; /* run it through LVM repair */
}
if (dead) {
/*
* Use the first event to run a repair ignoring any additonal ones.
*
* We presume lvconvert to do pre-repair
* checks to avoid bloat in this plugin.
*/
if (state->failed)
goto out; /* already reported */
state->failed = 1;
/* if repair goes OK, report success even if lvscan has failed */
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
log_error("Repair of RAID device %s failed.", device);
r = 0;
}
} else {
state->failed = 0;
if (status->insync_regions == status->total_regions)
memset(&state->raid_devs, 0, sizeof(state->raid_devs));
log_info("%s array, %s, is %s in-sync.",
status->raid_type, device,
(status->insync_regions == status->total_regions) ? "now" : "not");
}
out:
dm_pool_free(state->mem, status);
return r;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
const char *device = dm_task_get_name(dmt);
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type) {
log_info("%s mapping lost.", device);
continue;
}
if (strcmp(target_type, "raid")) {
log_info("%s has non-raid portion.", device);
continue;
}
if (!_process_raid_event(state, params, device))
log_error("Failed to process event for %s.",
device);
} while (next);
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state;
if (!dmeventd_lvm2_init_with_pool("raid_state", state))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
"lvconvert --repair --use-policies", device))
goto_bad;
*user = state;
log_info("Monitoring RAID device %s for events.", device);
return 1;
bad:
log_error("Failed to monitor RAID %s.", device);
if (state)
dmeventd_lvm2_exit_with_pool(state);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring RAID device %s for events.",
device);
return 1;
}

View File

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

View File

@@ -1,31 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_snapshot.c
LIB_SHARED = libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -1,290 +0,0 @@
/*
* Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include <sys/sysmacros.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <pthread.h>
/* First warning when snapshot is 80% full. */
#define WARNING_THRESH (DM_PERCENT_1 * 80)
/* Run a check every 5%. */
#define CHECK_STEP (DM_PERCENT_1 * 5)
/* Do not bother checking snapshots less than 50% full. */
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
#define UMOUNT_COMMAND "/bin/umount"
struct dso_state {
struct dm_pool *mem;
dm_percent_t percent_check;
uint64_t known_size;
char cmd_lvextend[512];
};
DM_EVENT_LOG_FN("snap")
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);
log_sys_error("exec", cmd);
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)
{
log_debug("Extending snapshot via %s.", cmd);
return dmeventd_lvm2_run_with_lock(cmd);
}
#ifdef SNAPSHOT_REMOVE
/* Remove invalid snapshot from dm-table */
/* Experimental for now and not used by default */
static int _remove(const char *uuid)
{
int r = 1;
uint32_t cookie = 0;
struct dm_task *dmt;
if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
return 0;
if (!dm_task_set_uuid(dmt, uuid)) {
r = 0;
goto_out;
}
dm_task_retry_remove(dmt);
if (!dm_task_set_cookie(dmt, &cookie, 0)) {
r = 0;
goto_out;
}
if (!dm_task_run(dmt)) {
r = 0;
goto_out;
}
out:
dm_task_destroy(dmt);
return r;
}
#endif /* SNAPSHOT_REMOVE */
static void _umount(const char *device, int major, int minor)
{
FILE *mounts;
char buffer[4096];
char *words[3];
struct stat st;
const char procmounts[] = "/proc/mounts";
if (!(mounts = fopen(procmounts, "r"))) {
log_sys_error("fopen", procmounts);
log_error("Not umounting %s.", 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) &&
(int) major(st.st_rdev) == major &&
(int) minor(st.st_rdev) == minor) {
log_error("Unmounting invalid snapshot %s from %s.", device, words[1]);
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
log_error("Failed to umount snapshot %s from %s: %s.",
device, words[1], strerror(errno));
}
}
if (fclose(mounts))
log_sys_error("close", procmounts);
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
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 dm_info info;
int ret;
/* No longer monitoring, waiting for remove */
if (!state->percent_check)
return;
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || strcmp(target_type, "snapshot")) {
log_error("Target %s is not snapshot.", target_type);
return;
}
if (!dm_get_status_snapshot(state->mem, params, &status)) {
log_error("Cannot parse snapshot %s state: %s.", device, params);
return;
}
/*
* 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->overflow || !status->total_sectors) {
log_warn("WARNING: Snapshot %s changed state to: %s and should be removed.",
device, params);
state->percent_check = 0;
if (dm_task_get_info(dmt, &info))
_umount(device, info.major, info.minor);
#ifdef SNAPSHOT_REMOVE
/* Maybe configurable ? */
_remove(dm_task_get_uuid(dmt));
#endif
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
log_sys_error("pthread_kill", "self");
goto out;
}
if (length <= (status->used_sectors - status->metadata_sectors)) {
/* TODO eventually recognize earlier when room is enough */
log_info("Dropping monitoring of fully provisioned snapshot %s.",
device);
if ((ret = pthread_kill(pthread_self(), SIGALRM)) && (ret != ESRCH))
log_sys_error("pthread_kill", "self");
goto out;
}
/* 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;
}
percent = dm_make_percent(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. */
log_warn("WARNING: Snapshot %s is now %.2f%% full.",
device, dm_percent_to_round_float(percent, 2));
/* Try to extend the snapshot, in accord with user-set policies */
if (!_extend(state->cmd_lvextend))
log_error("Failed to extend snapshot %s.", device);
}
out:
dm_pool_free(state->mem, status);
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state;
if (!dmeventd_lvm2_init_with_pool("snapshot_state", state))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend,
sizeof(state->cmd_lvextend),
"lvextend --use-policies", device))
goto_bad;
state->percent_check = CHECK_MINIMUM;
*user = state;
log_info("Monitoring snapshot %s.", device);
return 1;
bad:
log_error("Failed to monitor snapshot %s.", device);
if (state)
dmeventd_lvm2_exit_with_pool(state);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring snapshot %s.", device);
return 1;
}

View File

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

View File

@@ -1,34 +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-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
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -1,436 +0,0 @@
/*
* Copyright (C) 2011-2017 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include <sys/wait.h>
#include <stdarg.h>
/* TODO - move this mountinfo code into library to be reusable */
#ifdef __linux__
# include "libdm/misc/kdev_t.h"
#else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
#endif
/* First warning when thin data or metadata is 80% full. */
#define WARNING_THRESH (DM_PERCENT_1 * 80)
/* Umount thin LVs when thin data or metadata LV is >=
* and lvextend --use-policies has failed. */
#define UMOUNT_THRESH (DM_PERCENT_1 * 95)
/* Run a check every 5%. */
#define CHECK_STEP (DM_PERCENT_1 * 5)
/* Do not bother checking thin data or metadata is less than 50% full. */
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
#define UMOUNT_COMMAND "/bin/umount"
#define MAX_FAILS (256) /* ~42 mins between cmd call retry with 10s delay */
#define THIN_DEBUG 0
struct dso_state {
struct dm_pool *mem;
int metadata_percent_check;
int metadata_percent;
int data_percent_check;
int data_percent;
uint64_t known_metadata_size;
uint64_t known_data_size;
unsigned fails;
unsigned max_fails;
int restore_sigset;
sigset_t old_sigset;
pid_t pid;
char *argv[3];
char *cmd_str;
};
DM_EVENT_LOG_FN("thin")
static int _run_command(struct dso_state *state)
{
char val[16];
int i;
/* Mark for possible lvm2 command we are running from dmeventd
* lvm2 will not try to talk back to dmeventd while processing it */
(void) setenv("LVM_RUN_BY_DMEVENTD", "1", 1);
if (state->data_percent) {
/* Prepare some known data to env vars for easy use */
if (dm_snprintf(val, sizeof(val), "%d",
state->data_percent / DM_PERCENT_1) != -1)
(void) setenv("DMEVENTD_THIN_POOL_DATA", val, 1);
if (dm_snprintf(val, sizeof(val), "%d",
state->metadata_percent / DM_PERCENT_1) != -1)
(void) setenv("DMEVENTD_THIN_POOL_METADATA", val, 1);
} else {
/* For an error event it's for a user to check status and decide */
log_debug("Error event processing.");
}
log_verbose("Executing command: %s", state->cmd_str);
/* TODO:
* Support parallel run of 'task' and it's waitpid maintainence
* ATM we can't handle signaling of SIGALRM
* as signalling is not allowed while 'process_event()' is running
*/
if (!(state->pid = fork())) {
/* child */
(void) close(0);
for (i = 3; i < 255; ++i) (void) close(i);
execvp(state->argv[0], state->argv);
_exit(errno);
} else if (state->pid == -1) {
log_error("Can't fork command %s.", state->cmd_str);
state->fails = 1;
return 0;
}
return 1;
}
static int _use_policy(struct dm_task *dmt, struct dso_state *state)
{
#if THIN_DEBUG
log_debug("dmeventd executes: %s.", state->cmd_str);
#endif
if (state->argv[0])
return _run_command(state);
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
log_error("Failed command for %s.", dm_task_get_name(dmt));
state->fails = 1;
return 0;
}
state->fails = 0;
return 1;
}
/* Check if executed command has finished
* Only 1 command may run */
static int _wait_for_pid(struct dso_state *state)
{
int status = 0;
if (state->pid == -1)
return 1;
if (!waitpid(state->pid, &status, WNOHANG))
return 0;
/* Wait for finish */
if (WIFEXITED(status)) {
log_verbose("Child %d exited with status %d.",
state->pid, WEXITSTATUS(status));
state->fails = WEXITSTATUS(status) ? 1 : 0;
} else {
if (WIFSIGNALED(status))
log_verbose("Child %d was terminated with status %d.",
state->pid, WTERMSIG(status));
state->fails = 1;
}
state->pid = -1;
return 1;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **user)
{
const char *device = dm_task_get_name(dmt);
struct dso_state *state = *user;
struct dm_status_thin_pool *tps = NULL;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
int needs_policy = 0;
struct dm_task *new_dmt = NULL;
#if THIN_DEBUG
log_debug("Watch for tp-data:%.2f%% tp-metadata:%.2f%%.",
dm_percent_to_round_float(state->data_percent_check, 2),
dm_percent_to_round_float(state->metadata_percent_check, 2));
#endif
if (!_wait_for_pid(state)) {
log_warn("WARNING: Skipping event, child %d is still running (%s).",
state->pid, state->cmd_str);
return;
}
if (event & DM_EVENT_DEVICE_ERROR) {
/* Error -> no need to check and do instant resize */
state->data_percent = state->metadata_percent = 0;
if (_use_policy(dmt, state))
goto out;
stack;
/*
* Rather update oldish status
* since after 'command' processing
* percentage info could have changed a lot.
* If we would get above UMOUNT_THRESH
* we would wait for next sigalarm.
*/
if (!(new_dmt = dm_task_create(DM_DEVICE_STATUS)))
goto_out;
if (!dm_task_set_uuid(new_dmt, dm_task_get_uuid(dmt)))
goto_out;
/* Non-blocking status read */
if (!dm_task_no_flush(new_dmt))
log_warn("WARNING: Can't set no_flush for dm status.");
if (!dm_task_run(new_dmt))
goto_out;
dmt = new_dmt;
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
log_error("Invalid target type.");
goto out;
}
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
log_error("Failed to parse status.");
goto out;
}
#if THIN_DEBUG
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
FMTu64 "/" FMTu64 ".",
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;
state->fails = 0;
}
if (state->known_data_size != tps->total_data_blocks) {
state->data_percent_check = CHECK_MINIMUM;
state->known_data_size = tps->total_data_blocks;
state->fails = 0;
}
/*
* Trigger action when threshold boundary is exceeded.
* Report 80% threshold warning when it's used above 80%.
* Only 100% is exception as it cannot be surpased so policy
* action is called for: >50%, >55% ... >95%, 100%
*/
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
if ((state->metadata_percent > WARNING_THRESH) &&
(state->metadata_percent > state->metadata_percent_check))
log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
device, dm_percent_to_round_float(state->metadata_percent, 2));
if (state->metadata_percent > CHECK_MINIMUM) {
/* Run action when usage raised more than CHECK_STEP since the last time */
if (state->metadata_percent > state->metadata_percent_check)
needs_policy = 1;
state->metadata_percent_check = (state->metadata_percent / CHECK_STEP + 1) * CHECK_STEP;
if (state->metadata_percent_check == DM_PERCENT_100)
state->metadata_percent_check--; /* Can't get bigger then 100% */
} else
state->metadata_percent_check = CHECK_MINIMUM;
state->data_percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
if ((state->data_percent > WARNING_THRESH) &&
(state->data_percent > state->data_percent_check))
log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
device, dm_percent_to_round_float(state->data_percent, 2));
if (state->data_percent > CHECK_MINIMUM) {
/* Run action when usage raised more than CHECK_STEP since the last time */
if (state->data_percent > state->data_percent_check)
needs_policy = 1;
state->data_percent_check = (state->data_percent / CHECK_STEP + 1) * CHECK_STEP;
if (state->data_percent_check == DM_PERCENT_100)
state->data_percent_check--; /* Can't get bigger then 100% */
} else
state->data_percent_check = CHECK_MINIMUM;
/* Reduce number of _use_policy() calls by power-of-2 factor till frequency of MAX_FAILS is reached.
* Avoids too high number of error retries, yet shows some status messages in log regularly.
* i.e. PV could have been pvmoved and VG/LV was locked for a while...
*/
if (state->fails) {
if (state->fails++ <= state->max_fails) {
log_debug("Postponing frequently failing policy (%u <= %u).",
state->fails - 1, state->max_fails);
goto out;
}
if (state->max_fails < MAX_FAILS)
state->max_fails <<= 1;
state->fails = needs_policy = 1; /* Retry failing command */
} else
state->max_fails = 1; /* Reset on success */
if (needs_policy)
_use_policy(dmt, state);
out:
if (tps)
dm_pool_free(state->mem, tps);
if (new_dmt)
dm_task_destroy(new_dmt);
}
/* Handle SIGCHLD for a thread */
static void _sig_child(int signum __attribute__((unused)))
{
/* empty SIG_IGN */;
}
/* Setup handler for SIGCHLD when executing external command
* to get quick 'waitpid()' reaction
* It will interrupt syscall just like SIGALRM and
* invoke process_event().
*/
static void _init_thread_signals(struct dso_state *state)
{
struct sigaction act = { .sa_handler = _sig_child };
sigset_t my_sigset;
sigemptyset(&my_sigset);
if (sigaction(SIGCHLD, &act, NULL))
log_warn("WARNING: Failed to set SIGCHLD action.");
else if (sigaddset(&my_sigset, SIGCHLD))
log_warn("WARNING: Failed to add SIGCHLD to set.");
else if (pthread_sigmask(SIG_UNBLOCK, &my_sigset, &state->old_sigset))
log_warn("WARNING: Failed to unblock SIGCHLD.");
else
state->restore_sigset = 1;
}
static void _restore_thread_signals(struct dso_state *state)
{
if (state->restore_sigset &&
pthread_sigmask(SIG_SETMASK, &state->old_sigset, NULL))
log_warn("WARNING: Failed to block SIGCHLD.");
}
int register_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state;
char *str;
char cmd_str[PATH_MAX + 128 + 2]; /* cmd ' ' vg/lv \0 */
if (!dmeventd_lvm2_init_with_pool("thin_pool_state", state))
goto_bad;
if (!dmeventd_lvm2_command(state->mem, cmd_str, sizeof(cmd_str),
"_dmeventd_thin_command", device))
goto_bad;
if (strncmp(cmd_str, "lvm ", 4) == 0) {
if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str + 4))) {
log_error("Failed to copy lvm command.");
goto bad;
}
} else if (cmd_str[0] == '/') {
if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str))) {
log_error("Failed to copy thin command.");
goto bad;
}
/* Find last space before 'vg/lv' */
if (!(str = strrchr(state->cmd_str, ' ')))
goto inval;
if (!(state->argv[0] = dm_pool_strndup(state->mem, state->cmd_str,
str - state->cmd_str))) {
log_error("Failed to copy command.");
goto bad;
}
state->argv[1] = str + 1; /* 1 argument - vg/lv */
_init_thread_signals(state);
} else /* Unuspported command format */
goto inval;
state->pid = -1;
*user = state;
log_info("Monitoring thin pool %s.", device);
return 1;
inval:
log_error("Invalid command for monitoring: %s.", cmd_str);
bad:
log_error("Failed to monitor thin pool %s.", device);
if (state)
dmeventd_lvm2_exit_with_pool(state);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
int i;
for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) {
if (i == 0)
/* Give it 2 seconds, then try to terminate & kill it */
log_verbose("Child %d still not finished (%s) waiting.",
state->pid, state->cmd_str);
else if (i == 3) {
log_warn("WARNING: Terminating child %d.", state->pid);
kill(state->pid, SIGINT);
kill(state->pid, SIGTERM);
} else if (i == 5) {
log_warn("WARNING: Killing child %d.", state->pid);
kill(state->pid, SIGKILL);
}
sleep(1);
}
if (state->pid != -1)
log_warn("WARNING: Cannot kill child %d!", state->pid);
_restore_thread_signals(state);
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring thin pool %s.", device);
return 1;
}

View File

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

View File

@@ -1,34 +0,0 @@
#
# Copyright (C) 2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
LIBS += -ldevmapper-event-lvm2
SOURCES = dmeventd_vdo.c
LIB_NAME = libdevmapper-event-lvm2vdo
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
install_lvm2: install_dm_plugin
install: install_lvm2

View File

@@ -1,407 +0,0 @@
/*
* Copyright (C) 2018 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/misc/lib.h"
#include "daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
/* Use parser from new device_mapper library */
#include "device_mapper/vdo/status.c"
#include <sys/wait.h>
#include <stdarg.h>
/* First warning when VDO pool is 80% full. */
#define WARNING_THRESH (DM_PERCENT_1 * 80)
/* Run a check every 5%. */
#define CHECK_STEP (DM_PERCENT_1 * 5)
/* Do not bother checking VDO pool is less than 50% full. */
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
#define MAX_FAILS (256) /* ~42 mins between cmd call retry with 10s delay */
#define VDO_DEBUG 0
struct dso_state {
struct dm_pool *mem;
int percent_check;
int percent;
uint64_t known_data_size;
unsigned fails;
unsigned max_fails;
int restore_sigset;
sigset_t old_sigset;
pid_t pid;
char *argv[3];
const char *cmd_str;
const char *name;
};
DM_EVENT_LOG_FN("vdo")
static int _run_command(struct dso_state *state)
{
char val[16];
int i;
/* Mark for possible lvm2 command we are running from dmeventd
* lvm2 will not try to talk back to dmeventd while processing it */
(void) setenv("LVM_RUN_BY_DMEVENTD", "1", 1);
if (state->percent) {
/* Prepare some known data to env vars for easy use */
if (dm_snprintf(val, sizeof(val), "%d",
state->percent / DM_PERCENT_1) != -1)
(void) setenv("DMEVENTD_VDO_POOL", val, 1);
} else {
/* For an error event it's for a user to check status and decide */
log_debug("Error event processing.");
}
log_verbose("Executing command: %s", state->cmd_str);
/* TODO:
* Support parallel run of 'task' and it's waitpid maintainence
* ATM we can't handle signaling of SIGALRM
* as signalling is not allowed while 'process_event()' is running
*/
if (!(state->pid = fork())) {
/* child */
(void) close(0);
for (i = 3; i < 255; ++i) (void) close(i);
execvp(state->argv[0], state->argv);
_exit(errno);
} else if (state->pid == -1) {
log_error("Can't fork command %s.", state->cmd_str);
state->fails = 1;
return 0;
}
return 1;
}
static int _use_policy(struct dm_task *dmt, struct dso_state *state)
{
#if VDO_DEBUG
log_debug("dmeventd executes: %s.", state->cmd_str);
#endif
if (state->argv[0])
return _run_command(state);
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
log_error("Failed command for %s.", dm_task_get_name(dmt));
state->fails = 1;
return 0;
}
state->fails = 0;
return 1;
}
/* Check if executed command has finished
* Only 1 command may run */
static int _wait_for_pid(struct dso_state *state)
{
int status = 0;
if (state->pid == -1)
return 1;
if (!waitpid(state->pid, &status, WNOHANG))
return 0;
/* Wait for finish */
if (WIFEXITED(status)) {
log_verbose("Child %d exited with status %d.",
state->pid, WEXITSTATUS(status));
state->fails = WEXITSTATUS(status) ? 1 : 0;
} else {
if (WIFSIGNALED(status))
log_verbose("Child %d was terminated with status %d.",
state->pid, WTERMSIG(status));
state->fails = 1;
}
state->pid = -1;
return 1;
}
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **user)
{
const char *device = dm_task_get_name(dmt);
struct dso_state *state = *user;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
int needs_policy = 0;
struct dm_task *new_dmt = NULL;
struct dm_vdo_status_parse_result vdop = { .status = NULL };
#if VDO_DEBUG
log_debug("Watch for VDO %s:%.2f%%.", state->name,
dm_percent_to_round_float(state->percent_check, 2));
#endif
if (!_wait_for_pid(state)) {
log_warn("WARNING: Skipping event, child %d is still running (%s).",
state->pid, state->cmd_str);
return;
}
if (event & DM_EVENT_DEVICE_ERROR) {
#if VDO_DEBUG
log_debug("VDO event error.");
#endif
/* Error -> no need to check and do instant resize */
state->percent = 0;
if (_use_policy(dmt, state))
goto out;
stack;
if (!(new_dmt = dm_task_create(DM_DEVICE_STATUS)))
goto_out;
if (!dm_task_set_uuid(new_dmt, dm_task_get_uuid(dmt)))
goto_out;
/* Non-blocking status read */
if (!dm_task_no_flush(new_dmt))
log_warn("WARNING: Can't set no_flush for dm status.");
if (!dm_task_run(new_dmt))
goto_out;
dmt = new_dmt;
}
dm_get_next_target(dmt, next, &start, &length, &target_type, &params);
if (!target_type || (strcmp(target_type, "vdo") != 0)) {
log_error("Invalid target type.");
goto out;
}
if (!dm_vdo_status_parse(state->mem, params, &vdop)) {
log_error("Failed to parse status.");
goto out;
}
state->percent = dm_make_percent(vdop.status->used_blocks,
vdop.status->total_blocks);
#if VDO_DEBUG
log_debug("VDO %s status %.2f%% " FMTu64 "/" FMTu64 ".",
state->name, dm_percent_to_round_float(state->percent, 2),
vdop.status->used_blocks, vdop.status->total_blocks);
#endif
/* VDO pool size had changed. Clear the threshold. */
if (state->known_data_size != vdop.status->total_blocks) {
state->percent_check = CHECK_MINIMUM;
state->known_data_size = vdop.status->total_blocks;
state->fails = 0;
}
/*
* Trigger action when threshold boundary is exceeded.
* Report 80% threshold warning when it's used above 80%.
* Only 100% is exception as it cannot be surpased so policy
* action is called for: >50%, >55% ... >95%, 100%
*/
if ((state->percent > WARNING_THRESH) &&
(state->percent > state->percent_check))
log_warn("WARNING: VDO %s %s is now %.2f%% full.",
state->name, device,
dm_percent_to_round_float(state->percent, 2));
if (state->percent > CHECK_MINIMUM) {
/* Run action when usage raised more than CHECK_STEP since the last time */
if (state->percent > state->percent_check)
needs_policy = 1;
state->percent_check = (state->percent / CHECK_STEP + 1) * CHECK_STEP;
if (state->percent_check == DM_PERCENT_100)
state->percent_check--; /* Can't get bigger then 100% */
} else
state->percent_check = CHECK_MINIMUM;
/* Reduce number of _use_policy() calls by power-of-2 factor till frequency of MAX_FAILS is reached.
* Avoids too high number of error retries, yet shows some status messages in log regularly.
* i.e. PV could have been pvmoved and VG/LV was locked for a while...
*/
if (state->fails) {
if (state->fails++ <= state->max_fails) {
log_debug("Postponing frequently failing policy (%u <= %u).",
state->fails - 1, state->max_fails);
goto out;
}
if (state->max_fails < MAX_FAILS)
state->max_fails <<= 1;
state->fails = needs_policy = 1; /* Retry failing command */
} else
state->max_fails = 1; /* Reset on success */
if (needs_policy)
_use_policy(dmt, state);
out:
if (vdop.status)
dm_pool_free(state->mem, vdop.status);
if (new_dmt)
dm_task_destroy(new_dmt);
}
/* Handle SIGCHLD for a thread */
static void _sig_child(int signum __attribute__((unused)))
{
/* empty SIG_IGN */;
}
/* Setup handler for SIGCHLD when executing external command
* to get quick 'waitpid()' reaction
* It will interrupt syscall just like SIGALRM and
* invoke process_event().
*/
static void _init_thread_signals(struct dso_state *state)
{
struct sigaction act = { .sa_handler = _sig_child };
sigset_t my_sigset;
sigemptyset(&my_sigset);
if (sigaction(SIGCHLD, &act, NULL))
log_warn("WARNING: Failed to set SIGCHLD action.");
else if (sigaddset(&my_sigset, SIGCHLD))
log_warn("WARNING: Failed to add SIGCHLD to set.");
else if (pthread_sigmask(SIG_UNBLOCK, &my_sigset, &state->old_sigset))
log_warn("WARNING: Failed to unblock SIGCHLD.");
else
state->restore_sigset = 1;
}
static void _restore_thread_signals(struct dso_state *state)
{
if (state->restore_sigset &&
pthread_sigmask(SIG_SETMASK, &state->old_sigset, NULL))
log_warn("WARNING: Failed to block SIGCHLD.");
}
int register_device(const char *device,
const char *uuid,
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state;
const char *cmd;
char *str;
char cmd_str[PATH_MAX + 128 + 2]; /* cmd ' ' vg/lv \0 */
const char *name = "pool";
if (!dmeventd_lvm2_init_with_pool("vdo_pool_state", state))
goto_bad;
state->cmd_str = "";
/* Search for command for LVM- prefixed devices only */
cmd = (strncmp(uuid, "LVM-", 4) == 0) ? "_dmeventd_vdo_command" : "";
if (!dmeventd_lvm2_command(state->mem, cmd_str, sizeof(cmd_str), cmd, device))
goto_bad;
if (strncmp(cmd_str, "lvm ", 4) == 0) {
if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str + 4))) {
log_error("Failed to copy lvm VDO command.");
goto bad;
}
} else if (cmd_str[0] == '/') {
if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str))) {
log_error("Failed to copy VDO command.");
goto bad;
}
/* Find last space before 'vg/lv' */
if (!(str = strrchr(state->cmd_str, ' ')))
goto inval;
if (!(state->argv[0] = dm_pool_strndup(state->mem, state->cmd_str,
str - state->cmd_str))) {
log_error("Failed to copy command.");
goto bad;
}
state->argv[1] = str + 1; /* 1 argument - vg/lv */
_init_thread_signals(state);
} else if (cmd[0] == 0) {
state->name = "volume"; /* What to use with 'others?' */
} else/* Unuspported command format */
goto inval;
state->pid = -1;
state->name = name;
*user = state;
log_info("Monitoring VDO %s %s.", name, device);
return 1;
inval:
log_error("Invalid command for monitoring: %s.", cmd_str);
bad:
log_error("Failed to monitor VDO %s %s.", name, device);
if (state)
dmeventd_lvm2_exit_with_pool(state);
return 0;
}
int unregister_device(const char *device,
const char *uuid __attribute__((unused)),
int major __attribute__((unused)),
int minor __attribute__((unused)),
void **user)
{
struct dso_state *state = *user;
const char *name = state->name;
int i;
for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) {
if (i == 0)
/* Give it 2 seconds, then try to terminate & kill it */
log_verbose("Child %d still not finished (%s) waiting.",
state->pid, state->cmd_str);
else if (i == 3) {
log_warn("WARNING: Terminating child %d.", state->pid);
kill(state->pid, SIGINT);
kill(state->pid, SIGTERM);
} else if (i == 5) {
log_warn("WARNING: Killing child %d.", state->pid);
kill(state->pid, SIGKILL);
}
sleep(1);
}
if (state->pid != -1)
log_warn("WARNING: Cannot kill child %d!", state->pid);
_restore_thread_signals(state);
dmeventd_lvm2_exit_with_pool(state);
log_info("No longer monitoring VDO %s %s.", name, device);
return 1;
}

View File

@@ -1,4 +0,0 @@
path.py
lvmdbusd
lvmdb.py
lvm_shell_proxy.py

View File

@@ -1,73 +0,0 @@
#
# Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
lvmdbusdir = $(python3dir)/lvmdbusd
LVMDBUS_SRCDIR_FILES = \
automatedproperties.py \
background.py \
cfg.py \
cmdhandler.py \
fetch.py \
job.py \
loader.py \
lv.py \
main.py \
manager.py \
objectmanager.py \
pv.py \
request.py \
state.py \
udevwatch.py \
utils.py \
vg.py \
__init__.py
LVMDBUS_BUILDDIR_FILES = \
lvmdb.py \
lvm_shell_proxy.py \
path.py
LVMDBUSD = lvmdbusd
CLEAN_DIRS += __pycache__
include $(top_builddir)/make.tmpl
.PHONY: install_lvmdbusd
all:
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd:
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
install_lvm2: install_lvmdbusd
install: install_lvm2
DISTCLEAN_TARGETS+= \
$(LVMDBUS_BUILDDIR_FILES) \
$(LVMDBUSD)

View File

@@ -1,10 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
from .main import main

View File

@@ -1,194 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
import dbus
import dbus.service
from . import cfg
from .utils import get_properties, add_properties, get_object_property_diff, \
log_debug
from .state import State
# noinspection PyPep8Naming,PyUnresolvedReferences
class AutomatedProperties(dbus.service.Object):
"""
This class implements the needed interfaces for:
org.freedesktop.DBus.Properties
Other classes inherit from it to get the same behavior
"""
def __init__(self, object_path, search_method=None):
dbus.service.Object.__init__(self, cfg.bus, object_path)
self._ap_interface = []
self._ap_o_path = object_path
self._ap_search_method = search_method
self.state = None
def dbus_object_path(self):
return self._ap_o_path
def emit_data(self):
props = {}
for i in self.interface():
props[i] = AutomatedProperties._get_all_prop(self, i)
return self._ap_o_path, props
def set_interface(self, interface):
"""
With inheritance we can't easily tell what interfaces a class provides
so we will have each class that implements an interface tell the
base AutomatedProperties what it is they do provide. This is kind of
clunky and perhaps we can figure out a better way to do this later.
:param interface: An interface the object supports
:return:
"""
if interface not in self._ap_interface:
self._ap_interface.append(interface)
# noinspection PyUnusedLocal
def interface(self, all_interfaces=False):
if all_interfaces:
cpy = list(self._ap_interface)
cpy.extend(
["org.freedesktop.DBus.Introspectable",
"org.freedesktop.DBus.Properties"])
return cpy
return self._ap_interface
@staticmethod
def _get_prop(obj, interface_name, property_name):
value = getattr(obj, property_name)
# Note: If we get an exception in this handler we won't know about it,
# only the side effect of no returned value!
log_debug('Get (%s), type (%s), value(%s)' %
(property_name, str(type(value)), str(value)))
return value
# Properties
# noinspection PyUnusedLocal
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='ss', out_signature='v',
async_callbacks=('cb', 'cbe'))
def Get(self, interface_name, property_name, cb, cbe):
# Note: If we get an exception in this handler we won't know about it,
# only the side effect of no returned value!
r = cfg.create_request_entry(
-1, AutomatedProperties._get_prop,
(self, interface_name, property_name),
cb, cbe, False)
cfg.worker_q.put(r)
@staticmethod
def _get_all_prop(obj, interface_name):
if interface_name in obj.interface(True):
# Using introspection, lets build this dynamically
properties = get_properties(obj)
if interface_name in properties:
return properties[interface_name][1]
return {}
raise dbus.exceptions.DBusException(
obj._ap_interface,
'The object %s does not implement the %s interface'
% (obj.__class__, interface_name))
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='s', out_signature='a{sv}',
async_callbacks=('cb', 'cbe'))
def GetAll(self, interface_name, cb, cbe):
r = cfg.create_request_entry(
-1, AutomatedProperties._get_all_prop,
(self, interface_name),
cb, cbe, False)
cfg.worker_q.put(r)
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
in_signature='ssv')
def Set(self, interface_name, property_name, new_value):
setattr(self, property_name, new_value)
self.PropertiesChanged(interface_name,
{property_name: new_value}, [])
# As dbus-python does not support introspection for properties we will
# get the autogenerated xml and then add our wanted properties to it.
@dbus.service.method(dbus_interface=dbus.INTROSPECTABLE_IFACE,
out_signature='s')
def Introspect(self):
r = dbus.service.Object.Introspect(self, self._ap_o_path, cfg.bus)
# Look at the properties in the class
props = get_properties(self)
for int_f, v in props.items():
r = add_properties(r, int_f, v[0])
return r
@dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE,
signature='sa{sv}as')
def PropertiesChanged(self, interface_name, changed_properties,
invalidated_properties):
log_debug(('SIGNAL: PropertiesChanged(%s, %s, %s, %s)' %
(str(self._ap_o_path), str(interface_name),
str(changed_properties), str(invalidated_properties))))
def refresh(self, search_key=None, object_state=None):
"""
Take the values (properties) of an object and update them with what
lvm currently has. You can either fetch the new ones or supply the
new state to be updated with
:param search_key: The value to use to search for
:param object_state: Use this as the new object state
"""
num_changed = 0
# If we can't do a lookup, bail now, this happens if we blindly walk
# through all dbus objects as some don't have a search method, like
# 'Manager' object.
if not self._ap_search_method:
return 0
search = self.lvm_id
if search_key:
search = search_key
# Either we have the new object state or we need to go fetch it
if object_state:
new_state = object_state
else:
new_state = self._ap_search_method([search])[0]
assert isinstance(new_state, State)
assert new_state
# When we refresh an object the object identifiers might have changed
# because LVM allows the user to change them (name & uuid), thus if
# they have changed we need to update the object manager so that
# look-ups will happen correctly
old_id = self.state.identifiers()
new_id = new_state.identifiers()
if old_id[0] != new_id[0] or old_id[1] != new_id[1]:
cfg.om.lookup_update(self, new_id[0], new_id[1])
# Grab the properties values, then replace the state of the object
# and retrieve the new values.
o_prop = get_properties(self)
self.state = new_state
n_prop = get_properties(self)
changed = get_object_property_diff(o_prop, n_prop)
if changed:
for int_f, v in changed.items():
self.PropertiesChanged(int_f, v, [])
num_changed += 1
return num_changed

View File

@@ -1,163 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
import subprocess
from . import cfg
from .cmdhandler import options_to_cli_args, LvmExecutionMeta
import dbus
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
add_no_notify
import os
import threading
import time
def pv_move_lv_cmd(move_options, lv_full_name,
pv_source, pv_source_range, pv_dest_range_list):
cmd = ['pvmove', '-i', '1']
cmd.extend(options_to_cli_args(move_options))
if lv_full_name:
cmd.extend(['-n', lv_full_name])
pv_range_append(cmd, pv_source, *pv_source_range)
pv_dest_ranges(cmd, pv_dest_range_list)
return cmd
def lv_merge_cmd(merge_options, lv_full_name):
cmd = ['lvconvert', '--merge', '-i', '1']
cmd.extend(options_to_cli_args(merge_options))
cmd.append(lv_full_name)
return cmd
def _move_merge(interface_name, command, job_state):
# We need to execute these command stand alone by forking & exec'ing
# the command always as we will be getting periodic output from them on
# the status of the long running operation.
command.insert(0, cfg.LVM_CMD)
# Instruct lvm to not register an event with us
command = add_no_notify(command)
#(self, start, ended, cmd, ec, stdout_txt, stderr_txt)
meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
cfg.blackbox.add(meta)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ,
stderr=subprocess.PIPE, close_fds=True)
log_debug("Background process for %s is %d" %
(str(command), process.pid))
lines_iterator = iter(process.stdout.readline, b"")
for line in lines_iterator:
line_str = line.decode("utf-8")
# Check to see if the line has the correct number of separators
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = round(
float(percentage.strip()[:-1]), 1)
# While the move is in progress we need to periodically update
# the state to reflect where everything is at.
cfg.load()
except ValueError:
log_error("Trying to parse percentage which failed for %s" %
line_str)
out = process.communicate()
with meta.lock:
meta.ended = time.time()
meta.ec = process.returncode
meta.stderr_txt = out[1]
if process.returncode == 0:
job_state.Percent = 100
else:
raise dbus.exceptions.DBusException(
interface_name,
'Exit code %s, stderr = %s' % (str(process.returncode), out[1]))
cfg.load()
return '/'
def move(interface_name, lv_name, pv_src_obj, pv_source_range,
pv_dests_and_ranges, move_options, job_state):
"""
Common code for the pvmove handling.
:param interface_name: What dbus interface we are providing for
:param lv_name: Optional (None or name of LV to move)
:param pv_src_obj: dbus object patch for source PV
:param pv_source_range: (0,0 to ignore, else start, end segments)
:param pv_dests_and_ranges: Array of PV object paths and start/end segs
:param move_options: Hash with optional arguments
:param job_state: Used to convey information about jobs between processes
:return: '/' When complete, the empty object path
"""
pv_dests = []
pv_src = cfg.om.get_object_by_path(pv_src_obj)
if pv_src:
# Check to see if we are handling a move to a specific
# destination(s)
if len(pv_dests_and_ranges):
for pr in pv_dests_and_ranges:
pv_dbus_obj = cfg.om.get_object_by_path(pr[0])
if not pv_dbus_obj:
raise dbus.exceptions.DBusException(
interface_name,
'PV Destination (%s) not found' % pr[0])
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
cmd = pv_move_lv_cmd(move_options,
lv_name,
pv_src.lvm_id,
pv_source_range,
pv_dests)
return _move_merge(interface_name, cmd, job_state)
else:
raise dbus.exceptions.DBusException(
interface_name, 'pv_src_obj (%s) not found' % pv_src_obj)
def merge(interface_name, lv_uuid, lv_name, merge_options, job_state):
# Make sure we have a dbus object representing it
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
if dbo:
cmd = lv_merge_cmd(merge_options, dbo.lvm_id)
return _move_merge(interface_name, cmd, job_state)
else:
raise dbus.exceptions.DBusException(
interface_name,
'LV with uuid %s and name %s not present!' % (lv_uuid, lv_name))
def _run_cmd(req):
log_debug(
"_run_cmd: Running method: %s with args %s" %
(str(req.method), str(req.arguments)))
req.run_cmd()
log_debug("_run_cmd: complete!")
def cmd_runner(request):
t = threading.Thread(target=_run_cmd, args=(request,),
name="cmd_runner %s" % str(request.method))
t.start()

View File

@@ -1,99 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
import os
import multiprocessing
import queue
import itertools
from lvmdbusd import path
LVM_CMD = os.getenv('LVM_BINARY', path.LVM_BINARY)
# This is the global object manager
om = None
# This is the global bus connection
bus = None
# Command line args
args = None
# Set to true if we are depending on external events for updates
got_external_event = False
# Shared state variable across all processes
run = multiprocessing.Value('i', 1)
# If this is set to true, the current setup support lvm shell and we are
# running in that mode of operation
SHELL_IN_USE = None
# Lock used by pprint
stdout_lock = multiprocessing.Lock()
worker_q = queue.Queue()
# Main event loop
loop = None
BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1')
BASE_INTERFACE = 'com.redhat.lvmdbus1'
PV_INTERFACE = BASE_INTERFACE + '.Pv'
VG_INTERFACE = BASE_INTERFACE + '.Vg'
LV_INTERFACE = BASE_INTERFACE + '.Lv'
LV_COMMON_INTERFACE = BASE_INTERFACE + '.LvCommon'
THIN_POOL_INTERFACE = BASE_INTERFACE + '.ThinPool'
CACHE_POOL_INTERFACE = BASE_INTERFACE + '.CachePool'
LV_CACHED = BASE_INTERFACE + '.CachedLv'
SNAPSHOT_INTERFACE = BASE_INTERFACE + '.Snapshot'
MANAGER_INTERFACE = BASE_INTERFACE + '.Manager'
JOB_INTERFACE = BASE_INTERFACE + '.Job'
BASE_OBJ_PATH = '/' + BASE_INTERFACE.replace('.', '/')
PV_OBJ_PATH = BASE_OBJ_PATH + '/Pv'
VG_OBJ_PATH = BASE_OBJ_PATH + '/Vg'
LV_OBJ_PATH = BASE_OBJ_PATH + '/Lv'
THIN_POOL_PATH = BASE_OBJ_PATH + "/ThinPool"
CACHE_POOL_PATH = BASE_OBJ_PATH + "/CachePool"
HIDDEN_LV_PATH = BASE_OBJ_PATH + "/HiddenLv"
MANAGER_OBJ_PATH = BASE_OBJ_PATH + '/Manager'
JOB_OBJ_PATH = BASE_OBJ_PATH + '/Job'
# Counters for object path generation
pv_id = itertools.count()
vg_id = itertools.count()
lv_id = itertools.count()
thin_id = itertools.count()
cache_pool_id = itertools.count()
job_id = itertools.count()
hidden_lv = itertools.count()
# Used to prevent circular imports...
load = None
event = None
# Global cached state
db = None
# lvm flight recorder
blackbox = None
# RequestEntry ctor
create_request_entry = None
def exit_daemon():
"""
Exit the daemon cleanly
:return:
"""
if run and loop:
run.value = 0
loop.quit()

View File

@@ -1,758 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
from subprocess import Popen, PIPE
import time
import threading
from itertools import chain
import collections
import traceback
import os
from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try:
import simplejson as json
except ImportError:
import json
SEP = '{|}'
total_time = 0.0
total_count = 0
# We need to prevent different threads from using the same lvm shell
# at the same time.
cmd_lock = threading.RLock()
class LvmExecutionMeta(object):
def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
self.lock = threading.RLock()
self.start = start
self.ended = ended
self.cmd = cmd
self.ec = ec
self.stdout_txt = stdout_txt
self.stderr_txt = stderr_txt
def __str__(self):
with self.lock:
return "EC= %d for %s\n" \
"STARTED: %f, ENDED: %f\n" \
"STDOUT=%s\n" \
"STDERR=%s\n" % \
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
self.stderr_txt)
class LvmFlightRecorder(object):
def __init__(self, size=16):
self.queue = collections.deque(maxlen=size)
def add(self, lvm_exec_meta):
self.queue.append(lvm_exec_meta)
def dump(self):
with cmd_lock:
if len(self.queue):
log_error("LVM dbus flight recorder START")
for c in reversed(self.queue):
log_error(str(c))
log_error("LVM dbus flight recorder END")
cfg.blackbox = LvmFlightRecorder()
def _debug_c(cmd, exit_code, out):
log_error('CMD= %s' % ' '.join(cmd))
log_error(("EC= %d" % exit_code))
log_error(("STDOUT=\n %s\n" % out[0]))
log_error(("STDERR=\n %s\n" % out[1]))
def call_lvm(command, debug=False):
"""
Call an executable and return a tuple of exitcode, stdout, stderr
:param command: Command to execute
:param debug: Dump debug to stdout
"""
# print 'STACK:'
# for line in traceback.format_stack():
# print line.strip()
# Prepend the full lvm executable so that we can run different versions
# in different locations on the same box
command.insert(0, cfg.LVM_CMD)
command = add_no_notify(command)
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ)
out = process.communicate()
stdout_text = bytes(out[0]).decode("utf-8")
stderr_text = bytes(out[1]).decode("utf-8")
if debug or process.returncode != 0:
_debug_c(command, process.returncode, (stdout_text, stderr_text))
return process.returncode, stdout_text, stderr_text
# The actual method which gets called to invoke the lvm command, can vary
# from forking a new process to using lvm shell
_t_call = call_lvm
def _shell_cfg():
global _t_call
# noinspection PyBroadException
try:
lvm_shell = LVMShellProxy()
_t_call = lvm_shell.call_lvm
cfg.SHELL_IN_USE = lvm_shell
return True
except Exception:
_t_call = call_lvm
cfg.SHELL_IN_USE = None
log_error(traceback.format_exc())
log_error("Unable to utilize lvm shell, dropping back to fork & exec")
return False
def set_execution(shell):
global _t_call
with cmd_lock:
# If the user requested lvm shell and we are currently setup that
# way, just return
if cfg.SHELL_IN_USE and shell:
return True
else:
if not shell and cfg.SHELL_IN_USE:
cfg.SHELL_IN_USE.exit_shell()
cfg.SHELL_IN_USE = None
_t_call = call_lvm
if shell:
if cfg.args.use_json:
return _shell_cfg()
else:
return False
return True
def time_wrapper(command, debug=False):
global total_time
global total_count
with cmd_lock:
start = time.time()
results = _t_call(command, debug)
ended = time.time()
total_time += (ended - start)
total_count += 1
cfg.blackbox.add(LvmExecutionMeta(start, ended, command, *results))
return results
call = time_wrapper
# Default cmd
# Place default arguments for every command here.
def _dc(cmd, args):
c = [cmd, '--noheading', '--separator', '%s' % SEP, '--nosuffix',
'--unbuffered', '--units', 'b']
c.extend(args)
return c
def parse(out):
rc = []
for line in out.split('\n'):
# This line includes separators, so process them
if SEP in line:
elem = line.split(SEP)
cleaned_elem = []
for e in elem:
e = e.strip()
cleaned_elem.append(e)
if len(cleaned_elem) > 1:
rc.append(cleaned_elem)
else:
t = line.strip()
if len(t) > 0:
rc.append(t)
return rc
def parse_column_names(out, column_names):
lines = parse(out)
rc = []
for i in range(0, len(lines)):
d = dict(list(zip(column_names, lines[i])))
rc.append(d)
return rc
def options_to_cli_args(options):
rc = []
for k, v in list(dict(options).items()):
if k.startswith("-"):
rc.append(k)
else:
rc.append("--%s" % k)
if v != "":
if isinstance(v, int):
rc.append(str(int(v)))
else:
rc.append(str(v))
return rc
def pv_remove(device, remove_options):
cmd = ['pvremove']
cmd.extend(options_to_cli_args(remove_options))
cmd.append(device)
return call(cmd)
def _qt(tag_name):
return '@%s' % tag_name
def _tag(operation, what, add, rm, tag_options):
cmd = [operation]
cmd.extend(options_to_cli_args(tag_options))
if isinstance(what, list):
cmd.extend(what)
else:
cmd.append(what)
if add:
cmd.extend(list(chain.from_iterable(
('--addtag', _qt(x)) for x in add)))
if rm:
cmd.extend(list(chain.from_iterable(
('--deltag', _qt(x)) for x in rm)))
return call(cmd, False)
def pv_tag(pv_devices, add, rm, tag_options):
return _tag('pvchange', pv_devices, add, rm, tag_options)
def vg_tag(vg_name, add, rm, tag_options):
return _tag('vgchange', vg_name, add, rm, tag_options)
def lv_tag(lv_name, add, rm, tag_options):
return _tag('lvchange', lv_name, add, rm, tag_options)
def vg_rename(vg_uuid, new_name, rename_options):
cmd = ['vgrename']
cmd.extend(options_to_cli_args(rename_options))
cmd.extend([vg_uuid, new_name])
return call(cmd)
def vg_remove(vg_name, remove_options):
cmd = ['vgremove']
cmd.extend(options_to_cli_args(remove_options))
cmd.extend(['-f', vg_name])
return call(cmd)
def vg_lv_create(vg_name, create_options, name, size_bytes, pv_dests):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--size', '%dB' % size_bytes])
cmd.extend(['--name', name, vg_name, '--yes'])
pv_dest_ranges(cmd, pv_dests)
return call(cmd)
def vg_lv_snapshot(vg_name, snapshot_options, name, size_bytes):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(snapshot_options))
cmd.extend(["-s"])
if size_bytes != 0:
cmd.extend(['--size', '%dB' % size_bytes])
cmd.extend(['--name', name, vg_name])
return call(cmd)
def _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
if not thin_pool:
cmd.extend(['--size', '%dB' % size_bytes])
else:
cmd.extend(['--thin', '--size', '%dB' % size_bytes])
cmd.extend(['--yes'])
return cmd
def vg_lv_create_linear(vg_name, create_options, name, size_bytes, thin_pool):
cmd = _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool)
cmd.extend(['--name', name, vg_name])
return call(cmd)
def vg_lv_create_striped(vg_name, create_options, name, size_bytes,
num_stripes, stripe_size_kb, thin_pool):
cmd = _vg_lv_create_common_cmd(create_options, size_bytes, thin_pool)
cmd.extend(['--stripes', str(int(num_stripes))])
if stripe_size_kb != 0:
cmd.extend(['--stripesize', str(int(stripe_size_kb))])
cmd.extend(['--name', name, vg_name])
return call(cmd)
def _vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
num_stripes, stripe_size_kb):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--type', raid_type])
cmd.extend(['--size', '%dB' % size_bytes])
if num_stripes != 0:
cmd.extend(['--stripes', str(int(num_stripes))])
if stripe_size_kb != 0:
cmd.extend(['--stripesize', str(int(stripe_size_kb))])
cmd.extend(['--name', name, vg_name, '--yes'])
return call(cmd)
def vg_lv_create_raid(vg_name, create_options, name, raid_type, size_bytes,
num_stripes, stripe_size_kb):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
return _vg_lv_create_raid(vg_name, create_options, name, raid_type,
size_bytes, num_stripes, stripe_size_kb)
def vg_lv_create_mirror(
vg_name, create_options, name, size_bytes, num_copies):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--type', 'mirror'])
cmd.extend(['--mirrors', str(int(num_copies))])
cmd.extend(['--size', '%dB' % size_bytes])
cmd.extend(['--name', name, vg_name, '--yes'])
return call(cmd)
def vg_create_cache_pool(md_full_name, data_full_name, create_options):
cmd = ['lvconvert']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--type', 'cache-pool', '--force', '-y',
'--poolmetadata', md_full_name, data_full_name])
return call(cmd)
def vg_create_thin_pool(md_full_name, data_full_name, create_options):
cmd = ['lvconvert']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--type', 'thin-pool', '--force', '-y',
'--poolmetadata', md_full_name, data_full_name])
return call(cmd)
def lv_remove(lv_path, remove_options):
cmd = ['lvremove']
cmd.extend(options_to_cli_args(remove_options))
cmd.extend(['-f', lv_path])
return call(cmd)
def lv_rename(lv_path, new_name, rename_options):
cmd = ['lvrename']
cmd.extend(options_to_cli_args(rename_options))
cmd.extend([lv_path, new_name])
return call(cmd)
def lv_resize(lv_full_name, size_change, pv_dests,
resize_options):
cmd = ['lvresize', '--force']
cmd.extend(options_to_cli_args(resize_options))
if size_change < 0:
cmd.append("-L-%dB" % (-size_change))
else:
cmd.append("-L+%dB" % (size_change))
cmd.append(lv_full_name)
pv_dest_ranges(cmd, pv_dests)
return call(cmd)
def lv_lv_create(lv_full_name, create_options, name, size_bytes):
cmd = ['lvcreate']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(['--virtualsize', '%dB' % size_bytes, '-T'])
cmd.extend(['--name', name, lv_full_name, '--yes'])
return call(cmd)
def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
# lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
cmd = ['lvconvert']
cmd.extend(options_to_cli_args(cache_options))
cmd.extend(['-y', '--type', 'cache', '--cachepool',
cache_pool_full_name, lv_full_name])
return call(cmd)
def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
cmd = ['lvconvert']
if destroy_cache:
option = '--uncache'
else:
# Currently fairly dangerous
# see: https://bugzilla.redhat.com/show_bug.cgi?id=1248972
option = '--splitcache'
cmd.extend(options_to_cli_args(detach_options))
# needed to prevent interactive questions
cmd.extend(["--yes", "--force"])
cmd.extend([option, lv_full_name])
return call(cmd)
def supports_json():
cmd = ['help']
rc, out, err = call(cmd)
if rc == 0:
if cfg.SHELL_IN_USE:
return True
else:
if 'fullreport' in err:
return True
return False
def lvm_full_report_json():
pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
'vg_uuid', 'pv_missing']
pv_seg_columns = ['pvseg_start', 'pvseg_size', 'segtype',
'pv_uuid', 'lv_uuid', 'pv_name']
vg_columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
'vg_mda_used_count', 'vg_attr', 'vg_tags']
lv_columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
'origin', 'data_percent',
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout',
'snap_percent', 'metadata_percent', 'copy_percent',
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
cmd = _dc('fullreport', [
'-a', # Need hidden too
'--configreport', 'pv', '-o', ','.join(pv_columns),
'--configreport', 'vg', '-o', ','.join(vg_columns),
'--configreport', 'lv', '-o', ','.join(lv_columns),
'--configreport', 'seg', '-o', ','.join(lv_seg_columns),
'--configreport', 'pvseg', '-o', ','.join(pv_seg_columns),
'--reportformat', 'json'
])
rc, out, err = call(cmd)
# When we have an exported vg the exit code of lvs or fullreport will be 5
if rc == 0 or rc == 5:
# With the current implementation, if we are using the shell then we
# are using JSON and JSON is returned back to us as it was parsed to
# figure out if we completed OK or not
if cfg.SHELL_IN_USE:
assert(type(out) == dict)
return out
else:
return json.loads(out)
return None
def pv_retrieve_with_segs(device=None):
d = []
err = ""
out = ""
rc = 0
columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
# Lvm has some issues where it returns failure when querying pvs when other
# operations are in process, see:
# https://bugzilla.redhat.com/show_bug.cgi?id=1274085
for i in range(0, 10):
cmd = _dc('pvs', ['-o', ','.join(columns)])
if device:
cmd.extend(device)
rc, out, err = call(cmd)
if rc == 0:
d = parse_column_names(out, columns)
break
else:
time.sleep(0.2)
log_debug("LVM Bug workaround, retrying pvs command...")
if rc != 0:
msg = "We were unable to get pvs to return without error after " \
"trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
(rc, err, out)
log_error(msg)
raise RuntimeError(msg)
return d
def pv_resize(device, size_bytes, create_options):
cmd = ['pvresize']
cmd.extend(options_to_cli_args(create_options))
if size_bytes != 0:
cmd.extend(['--yes', '--setphysicalvolumesize', '%dB' % size_bytes])
cmd.extend([device])
return call(cmd)
def pv_create(create_options, devices):
cmd = ['pvcreate', '-ff']
cmd.extend(options_to_cli_args(create_options))
cmd.extend(devices)
return call(cmd)
def pv_allocatable(device, yes, allocation_options):
yn = 'n'
if yes:
yn = 'y'
cmd = ['pvchange']
cmd.extend(options_to_cli_args(allocation_options))
cmd.extend(['-x', yn, device])
return call(cmd)
def pv_scan(activate, cache, device_paths, major_minors, scan_options):
cmd = ['pvscan']
cmd.extend(options_to_cli_args(scan_options))
if activate:
cmd.extend(['--activate', "ay"])
if cache:
cmd.append('--cache')
if len(device_paths) > 0:
for d in device_paths:
cmd.append(d)
if len(major_minors) > 0:
for mm in major_minors:
cmd.append("%s:%s" % (mm))
return call(cmd)
def vg_create(create_options, pv_devices, name):
cmd = ['vgcreate']
cmd.extend(options_to_cli_args(create_options))
cmd.append(name)
cmd.extend(pv_devices)
return call(cmd)
def vg_change(change_options, name):
cmd = ['vgchange']
cmd.extend(options_to_cli_args(change_options))
cmd.append(name)
return call(cmd)
def vg_reduce(vg_name, missing, pv_devices, reduce_options):
cmd = ['vgreduce']
cmd.extend(options_to_cli_args(reduce_options))
if missing:
cmd.append('--removemissing')
elif len(pv_devices) == 0:
cmd.append('--all')
cmd.append(vg_name)
cmd.extend(pv_devices)
return call(cmd)
def vg_extend(vg_name, extend_devices, extend_options):
cmd = ['vgextend']
cmd.extend(options_to_cli_args(extend_options))
cmd.append(vg_name)
cmd.extend(extend_devices)
return call(cmd)
def _vg_value_set(name, arguments, options):
cmd = ['vgchange']
cmd.extend(options_to_cli_args(options))
cmd.append(name)
cmd.extend(arguments)
return call(cmd)
def vg_allocation_policy(vg_name, policy, policy_options):
return _vg_value_set(vg_name, ['--alloc', policy], policy_options)
def vg_max_pv(vg_name, number, max_options):
return _vg_value_set(vg_name, ['--maxphysicalvolumes', str(int(number))],
max_options)
def vg_max_lv(vg_name, number, max_options):
return _vg_value_set(vg_name, ['-l', str(int(number))], max_options)
def vg_uuid_gen(vg_name, ignore, options):
assert ignore is None
return _vg_value_set(vg_name, ['--uuid'], options)
def activate_deactivate(op, name, activate, control_flags, options):
cmd = [op]
cmd.extend(options_to_cli_args(options))
op = '-a'
if control_flags:
# Autoactivation
if (1 << 0) & control_flags:
op += 'a'
# Exclusive locking (Cluster)
if (1 << 1) & control_flags:
op += 'e'
# Local node activation
if (1 << 2) & control_flags:
op += 'l'
# Activation modes
if (1 << 3) & control_flags:
cmd.extend(['--activationmode', 'complete'])
elif (1 << 4) & control_flags:
cmd.extend(['--activationmode', 'partial'])
# Ignore activation skip
if (1 << 5) & control_flags:
cmd.append('--ignoreactivationskip')
if activate:
op += 'y'
else:
op += 'n'
cmd.append(op)
cmd.append(name)
return call(cmd)
def vg_retrieve(vg_specific):
if vg_specific:
assert isinstance(vg_specific, list)
columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
'vg_mda_used_count', 'vg_attr', 'vg_tags']
cmd = _dc('vgs', ['-o', ','.join(columns)])
if vg_specific:
cmd.extend(vg_specific)
d = []
rc, out, err = call(cmd)
if rc == 0:
d = parse_column_names(out, columns)
return d
def lv_retrieve_with_segments():
columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
'origin', 'data_percent',
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
'lv_role', 'lv_layout',
'snap_percent', 'metadata_percent', 'copy_percent',
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
rc, out, err = call(cmd)
d = []
if rc == 0:
d = parse_column_names(out, columns)
return d
if __name__ == '__main__':
pv_data = pv_retrieve_with_segs()
for p in pv_data:
print(str(p))

View File

@@ -1,185 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
from .pv import load_pvs
from .vg import load_vgs
from .lv import load_lvs
from . import cfg
from .utils import MThreadRunner, log_debug, log_error
import threading
import queue
import time
import traceback
def _main_thread_load(refresh=True, emit_signal=True):
num_total_changes = 0
num_total_changes += load_pvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_lvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
return num_total_changes
def load(refresh=True, emit_signal=True, cache_refresh=True, log=True,
need_main_thread=True):
# Go through and load all the PVs, VGs and LVs
if cache_refresh:
cfg.db.refresh(log)
if need_main_thread:
rc = MThreadRunner(_main_thread_load, refresh, emit_signal).done()
else:
rc = _main_thread_load(refresh, emit_signal)
return rc
# Even though lvm can handle multiple changes concurrently it really doesn't
# make sense to make a 1-1 fetch of data for each change of lvm because when
# we fetch the data once all previous changes are reflected.
class StateUpdate(object):
class UpdateRequest(object):
def __init__(self, refresh, emit_signal, cache_refresh, log,
need_main_thread):
self.is_done = False
self.refresh = refresh
self.emit_signal = emit_signal
self.cache_refresh = cache_refresh
self.log = log
self.need_main_thread = need_main_thread
self.result = None
self.cond = threading.Condition(threading.Lock())
def done(self):
with self.cond:
if not self.is_done:
self.cond.wait()
return self.result
def set_result(self, result):
with self.cond:
self.result = result
self.is_done = True
self.cond.notify_all()
@staticmethod
def update_thread(obj):
exception_count = 0
queued_requests = []
while cfg.run.value != 0:
# noinspection PyBroadException
try:
refresh = True
emit_signal = True
cache_refresh = True
log = True
need_main_thread = True
with obj.lock:
wait = not obj.deferred
obj.deferred = False
if len(queued_requests) == 0 and wait:
queued_requests.append(obj.queue.get(True, 2))
# Ok we have one or the deferred queue has some,
# check if any others
try:
while True:
queued_requests.append(obj.queue.get(False))
except queue.Empty:
pass
if len(queued_requests) > 1:
log_debug("Processing %d updates!" % len(queued_requests),
'bg_black', 'fg_light_green')
# We have what we can, run the update with the needed options
for i in queued_requests:
if not i.refresh:
refresh = False
if not i.emit_signal:
emit_signal = False
if not i.cache_refresh:
cache_refresh = False
if not i.log:
log = False
if not i.need_main_thread:
need_main_thread = False
num_changes = load(refresh, emit_signal, cache_refresh, log,
need_main_thread)
# Update is done, let everyone know!
for i in queued_requests:
i.set_result(num_changes)
# Only clear out the requests after we have given them a result
# otherwise we can orphan the waiting threads and they never
# wake up if we get an exception
queued_requests = []
# We retrieved OK, clear exception count
exception_count = 0
except queue.Empty:
pass
except Exception as e:
st = traceback.format_exc()
log_error("update_thread exception: \n%s" % st)
cfg.blackbox.dump()
exception_count += 1
if exception_count >= 5:
for i in queued_requests:
i.set_result(e)
log_error("Too many errors in update_thread, exiting daemon")
cfg.exit_daemon()
else:
# Slow things down when encountering errors
time.sleep(1)
def __init__(self):
self.lock = threading.RLock()
self.queue = queue.Queue()
self.deferred = False
# Do initial load
load(refresh=False, emit_signal=False, need_main_thread=False)
self.thread = threading.Thread(target=StateUpdate.update_thread,
args=(self,),
name="StateUpdate.update_thread")
def load(self, refresh=True, emit_signal=True, cache_refresh=True,
log=True, need_main_thread=True):
# Place this request on the queue and wait for it to be completed
req = StateUpdate.UpdateRequest(refresh, emit_signal, cache_refresh,
log, need_main_thread)
self.queue.put(req)
return req.done()
def event(self):
with self.lock:
self.deferred = True

View File

@@ -1,228 +0,0 @@
# Copyright (C) 2015-2016 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, see <http://www.gnu.org/licenses/>.
from .automatedproperties import AutomatedProperties
from .utils import job_obj_path_generate, mt_async_call
from . import cfg
from .cfg import JOB_INTERFACE
import dbus
import threading
# noinspection PyUnresolvedReferences
from gi.repository import GLib
# Class that handles a client waiting for something to be complete. We either
# get a timeout or the operation is done.
class WaitingClient(object):
# A timeout occurred
@staticmethod
def _timeout(wc):
with wc.rlock:
if wc.in_use:
wc.in_use = False
# Remove ourselves from waiting client
wc.job_state.remove_waiting_client(wc)
wc.timer_id = -1
mt_async_call(wc.cb, wc.job_state.Complete)
wc.job_state = None
def __init__(self, job_state, tmo, cb, cbe):
self.rlock = threading.RLock()
self.job_state = job_state
self.cb = cb
self.cbe = cbe
self.in_use = True # Indicates if object is in play
self.timer_id = -1
if tmo > 0:
self.timer_id = GLib.timeout_add_seconds(
tmo, WaitingClient._timeout, self)
# The job finished before the timer popped and we are being notified that
# it's done
def notify(self):
with self.rlock:
if self.in_use:
self.in_use = False
# Clear timer
if self.timer_id != -1:
GLib.source_remove(self.timer_id)
self.timer_id = -1
mt_async_call(self.cb, self.job_state.Complete)
self.job_state = None
# noinspection PyPep8Naming
class JobState(object):
def __init__(self, request=None):
self.rlock = threading.RLock()
self._percent = 0
self._complete = False
self._request = request
self._ec = 0
self._stderr = ''
self._waiting_clients = []
# This is an lvm command that is just taking too long and doesn't
# support background operation
if self._request:
# Faking the percentage when we don't have one
self._percent = 1
@property
def Percent(self):
with self.rlock:
return self._percent
@Percent.setter
def Percent(self, value):
with self.rlock:
self._percent = value
@property
def Complete(self):
with self.rlock:
if self._request:
self._complete = self._request.is_done()
return self._complete
@Complete.setter
def Complete(self, value):
with self.rlock:
self._complete = value
self._percent = 100
self.notify_waiting_clients()
@property
def GetError(self):
with self.rlock:
if self.Complete:
if self._request:
(rc, error) = self._request.get_errors()
return (rc, str(error))
else:
return (self._ec, self._stderr)
else:
return (-1, 'Job is not complete!')
def dtor(self):
with self.rlock:
self._request = None
@property
def Result(self):
with self.rlock:
if self._request:
return self._request.result()
return '/'
def add_waiting_client(self, client):
with self.rlock:
# Avoid race condition where it goes complete before we get added
# to the list of waiting clients
if self.Complete:
client.notify()
else:
self._waiting_clients.append(client)
def remove_waiting_client(self, client):
# If a waiting client timer pops before the job is done we will allow
# the client to remove themselves from the list. As we have a lock
# here and a lock in the waiting client too, and they can be obtained
# in different orders, a dead lock can occur.
# As this remove is really optional, we will try to acquire the lock
# and remove. If we are unsuccessful it's not fatal, we just delay
# the time when the objects can be garbage collected by python
if self.rlock.acquire(False):
try:
self._waiting_clients.remove(client)
finally:
self.rlock.release()
def notify_waiting_clients(self):
with self.rlock:
for c in self._waiting_clients:
c.notify()
self._waiting_clients = []
# noinspection PyPep8Naming
class Job(AutomatedProperties):
_Percent_meta = ('d', JOB_INTERFACE)
_Complete_meta = ('b', JOB_INTERFACE)
_Result_meta = ('o', JOB_INTERFACE)
_GetError_meta = ('(is)', JOB_INTERFACE)
def __init__(self, request, job_state=None):
super(Job, self).__init__(job_obj_path_generate())
self.set_interface(JOB_INTERFACE)
if job_state:
self.state = job_state
else:
self.state = JobState(request)
@property
def Percent(self):
return dbus.Double(float(self.state.Percent))
@property
def Complete(self):
return dbus.Boolean(self.state.Complete)
@staticmethod
def _signal_complete(obj):
obj.PropertiesChanged(
JOB_INTERFACE, dict(Complete=dbus.Boolean(obj.state.Complete)), [])
@Complete.setter
def Complete(self, value):
self.state.Complete = value
mt_async_call(Job._signal_complete, self)
@property
def GetError(self):
return dbus.Struct(self.state.GetError, signature="(is)")
@dbus.service.method(dbus_interface=JOB_INTERFACE)
def Remove(self):
if self.state.Complete:
cfg.om.remove_object(self, True)
self.state.dtor()
else:
raise dbus.exceptions.DBusException(
JOB_INTERFACE, 'Job is not complete!')
@dbus.service.method(dbus_interface=JOB_INTERFACE,
in_signature='i',
out_signature='b',
async_callbacks=('cb', 'cbe'))
def Wait(self, timeout, cb, cbe):
if timeout == 0 or self.state.Complete:
cb(dbus.Boolean(self.state.Complete))
else:
self.state.add_waiting_client(
WaitingClient(self.state, timeout, cb, cbe))
@property
def Result(self):
return dbus.ObjectPath(self.state.Result)
@property
def lvm_id(self):
return str(id(self))
@property
def Uuid(self):
import uuid
return uuid.uuid1()

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