mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-05 16:23:51 +03:00
Compare commits
17 Commits
dev-bmr-dm
...
dev-mornfa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c9eddbab5 | ||
|
|
a2d9a818cf | ||
|
|
e83984dca5 | ||
|
|
f4d8d73ad3 | ||
|
|
0217311997 | ||
|
|
4db47137a4 | ||
|
|
4e9bbccb33 | ||
|
|
93108125ac | ||
|
|
d17cbf112b | ||
|
|
d838501c44 | ||
|
|
db59f5661c | ||
|
|
8e5d18afd3 | ||
|
|
ec5f5564de | ||
|
|
1650e1467c | ||
|
|
94d9562bea | ||
|
|
57795df365 | ||
|
|
0f49180ea7 |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,18 +1,13 @@
|
|||||||
*.5
|
*.5
|
||||||
*.7
|
|
||||||
*.8
|
*.8
|
||||||
*.a
|
*.a
|
||||||
*.d
|
*.d
|
||||||
*.o
|
*.o
|
||||||
*.orig
|
|
||||||
*.pc
|
*.pc
|
||||||
*.pot
|
*.pot
|
||||||
*.pyc
|
|
||||||
*.pyo
|
|
||||||
*.rej
|
|
||||||
*.so
|
*.so
|
||||||
*.so.*
|
*.so.*
|
||||||
*.sw*
|
*.swp
|
||||||
*~
|
*~
|
||||||
|
|
||||||
.export.sym
|
.export.sym
|
||||||
@@ -22,11 +17,11 @@
|
|||||||
Makefile
|
Makefile
|
||||||
make.tmpl
|
make.tmpl
|
||||||
|
|
||||||
|
configure.h
|
||||||
|
version.h
|
||||||
|
|
||||||
/autom4te.cache/
|
/autom4te.cache/
|
||||||
/autoscan.log
|
|
||||||
/config.log
|
/config.log
|
||||||
/config.status
|
/config.status
|
||||||
/configure.scan
|
|
||||||
/cscope.out
|
/cscope.out
|
||||||
/tags
|
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|||||||
4
COPYING
4
COPYING
@@ -2,7 +2,7 @@
|
|||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
@@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|||||||
83
Makefile.in
83
Makefile.in
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -10,15 +10,13 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
abs_top_builddir = @abs_top_builddir@
|
|
||||||
abs_top_srcdir = @abs_top_srcdir@
|
|
||||||
|
|
||||||
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
|
SUBDIRS = doc include man
|
||||||
|
|
||||||
ifeq ("@UDEV_RULES@", "yes")
|
ifeq ("@UDEV_RULES@", "yes")
|
||||||
SUBDIRS += udev
|
SUBDIRS += udev
|
||||||
@@ -28,6 +26,8 @@ ifeq ("@INTL@", "yes")
|
|||||||
SUBDIRS += po
|
SUBDIRS += po
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
SUBDIRS += lib tools daemons libdm libdaemon
|
||||||
|
|
||||||
ifeq ("@APPLIB@", "yes")
|
ifeq ("@APPLIB@", "yes")
|
||||||
SUBDIRS += liblvm
|
SUBDIRS += liblvm
|
||||||
endif
|
endif
|
||||||
@@ -36,12 +36,11 @@ ifeq ("@PYTHON_BINDINGS@", "yes")
|
|||||||
SUBDIRS += python
|
SUBDIRS += python
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),clean)
|
SUBDIRS += scripts
|
||||||
SUBDIRS += test
|
|
||||||
endif
|
|
||||||
# FIXME Should use intermediate Makefiles here!
|
# FIXME Should use intermediate Makefiles here!
|
||||||
ifeq ($(MAKECMDGOALS),distclean)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS = conf include man test scripts \
|
SUBDIRS = doc include man test scripts \
|
||||||
libdaemon lib tools daemons libdm \
|
libdaemon lib tools daemons libdm \
|
||||||
udev po liblvm python \
|
udev po liblvm python \
|
||||||
unit-tests/datastruct unit-tests/mm unit-tests/regex
|
unit-tests/datastruct unit-tests/mm unit-tests/regex
|
||||||
@@ -53,7 +52,6 @@ DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
|
|||||||
include make.tmpl
|
include make.tmpl
|
||||||
|
|
||||||
libdm: include
|
libdm: include
|
||||||
libdaemon: include
|
|
||||||
lib: libdm libdaemon
|
lib: libdm libdaemon
|
||||||
liblvm: lib
|
liblvm: lib
|
||||||
daemons: lib libdaemon tools
|
daemons: lib libdaemon tools
|
||||||
@@ -66,7 +64,6 @@ libdm.device-mapper: include.device-mapper
|
|||||||
liblvm.device-mapper: include.device-mapper
|
liblvm.device-mapper: include.device-mapper
|
||||||
daemons.device-mapper: libdm.device-mapper
|
daemons.device-mapper: libdm.device-mapper
|
||||||
tools.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
|
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
|
||||||
|
|
||||||
ifeq ("@INTL@", "yes")
|
ifeq ("@INTL@", "yes")
|
||||||
@@ -93,47 +90,10 @@ cscope.out:
|
|||||||
all: cscope.out
|
all: cscope.out
|
||||||
endif
|
endif
|
||||||
DISTCLEAN_TARGETS += cscope.out
|
DISTCLEAN_TARGETS += cscope.out
|
||||||
CLEAN_DIRS += autom4te.cache
|
|
||||||
|
|
||||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
|
check check_cluster check_local check_lvmetad unit: all
|
||||||
$(MAKE) -C test $(@)
|
$(MAKE) -C test $(@)
|
||||||
|
|
||||||
conf.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
|
|
||||||
$(MAKE) -C conf generate
|
|
||||||
|
|
||||||
all_man:
|
|
||||||
$(MAKE) -C man all_man
|
|
||||||
|
|
||||||
install_system_dirs:
|
install_system_dirs:
|
||||||
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
|
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
|
||||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
|
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
|
||||||
@@ -148,14 +108,10 @@ install_initscripts:
|
|||||||
|
|
||||||
install_systemd_generators:
|
install_systemd_generators:
|
||||||
$(MAKE) -C scripts install_systemd_generators
|
$(MAKE) -C scripts install_systemd_generators
|
||||||
$(MAKE) -C man install_systemd_generators
|
|
||||||
|
|
||||||
install_systemd_units:
|
install_systemd_units:
|
||||||
$(MAKE) -C scripts install_systemd_units
|
$(MAKE) -C scripts install_systemd_units
|
||||||
|
|
||||||
install_all_man:
|
|
||||||
$(MAKE) -C man install_all_man
|
|
||||||
|
|
||||||
ifeq ("@PYTHON_BINDINGS@", "yes")
|
ifeq ("@PYTHON_BINDINGS@", "yes")
|
||||||
install_python_bindings:
|
install_python_bindings:
|
||||||
$(MAKE) -C liblvm/python install_python_bindings
|
$(MAKE) -C liblvm/python install_python_bindings
|
||||||
@@ -164,14 +120,8 @@ endif
|
|||||||
install_tmpfiles_configuration:
|
install_tmpfiles_configuration:
|
||||||
$(MAKE) -C scripts install_tmpfiles_configuration
|
$(MAKE) -C scripts install_tmpfiles_configuration
|
||||||
|
|
||||||
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
|
LCOV_TRACES = libdm.info lib.info tools.info \
|
||||||
libdaemon/client.info libdaemon/server.info \
|
daemons/dmeventd.info daemons/clvmd.info
|
||||||
daemons/clvmd.info \
|
|
||||||
daemons/dmeventd.info \
|
|
||||||
daemons/lvmetad.info \
|
|
||||||
daemons/lvmlockd.info \
|
|
||||||
daemons/lvmpolld.info
|
|
||||||
|
|
||||||
CLEAN_TARGETS += $(LCOV_TRACES)
|
CLEAN_TARGETS += $(LCOV_TRACES)
|
||||||
|
|
||||||
ifneq ("$(LCOV)", "")
|
ifneq ("$(LCOV)", "")
|
||||||
@@ -200,7 +150,7 @@ lcov: $(LCOV_TRACES)
|
|||||||
$(RM) -r $(LCOV_REPORTS_DIR)
|
$(RM) -r $(LCOV_REPORTS_DIR)
|
||||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||||
for i in $(LCOV_TRACES); do \
|
for i in $(LCOV_TRACES); do \
|
||||||
test -s $$i -a $$(wc -w <$$i) -ge 100 && lc="$$lc $$i"; \
|
test -s $$i && lc="$$lc $$i"; \
|
||||||
done; \
|
done; \
|
||||||
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
|
test -z "$$lc" || $(GENHTML) -p @abs_top_builddir@ \
|
||||||
-o $(LCOV_REPORTS_DIR) $$lc
|
-o $(LCOV_REPORTS_DIR) $$lc
|
||||||
@@ -232,12 +182,3 @@ memcheck: test-programs
|
|||||||
ruby-test:
|
ruby-test:
|
||||||
$(RUBY) report-generators/test/ts.rb
|
$(RUBY) report-generators/test/ts.rb
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(shell which ctags),)
|
|
||||||
.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
|
|
||||||
|
|||||||
2
README
2
README
@@ -18,7 +18,7 @@ Mailing list for general discussion related to LVM2:
|
|||||||
|
|
||||||
Mailing lists for LVM2 development, patches and commits:
|
Mailing lists for LVM2 development, patches and commits:
|
||||||
lvm-devel@redhat.com
|
lvm-devel@redhat.com
|
||||||
Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel
|
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||||
|
|
||||||
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
|
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
|
||||||
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
|
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.02.138-git (2016-11-30)
|
1.02.78-git (2012-10-22)
|
||||||
|
|||||||
488
WHATS_NEW_DM
488
WHATS_NEW_DM
@@ -1,489 +1,5 @@
|
|||||||
Version 1.02.138 -
|
Version 1.02.78 -
|
||||||
=====================================
|
|
||||||
Support configurable command executed from dmeventd thin plugin.
|
|
||||||
Support new R|r human readable units output format.
|
|
||||||
Thin dmeventd plugin reacts faster on lvextend failure path with umount.
|
|
||||||
Add dm_stats_bind_from_fd() to bind a stats handle from a file descriptor.
|
|
||||||
Do not try call callback when reverting activation on error path.
|
|
||||||
Fix file mapping for extents with physically adjacent extents.
|
|
||||||
Validation vsnprintf result in runtime translate of dm_log (1.02.136).
|
|
||||||
Separate filemap extent allocation from region table.
|
|
||||||
Fix segmentation fault when filemap region creation fails.
|
|
||||||
Fix performance of region cleanup for failed filemap creation.
|
|
||||||
Fix very slow region deletion with many regions.
|
|
||||||
|
|
||||||
Version 1.02.137 - 30th November 2016
|
|
||||||
=====================================
|
|
||||||
Document raid status values.
|
|
||||||
Always exit dmsetup with success when asked to display help/version.
|
|
||||||
|
|
||||||
Version 1.02.136 - 5th November 2016
|
|
||||||
====================================
|
|
||||||
Log failure of raid device with log_error level.
|
|
||||||
Use dm_log_with_errno and translate runtime to dm_log only when needed.
|
|
||||||
Make log messages from dm and lvm library different from dmeventd.
|
|
||||||
Notice and Info messages are again logged from dmeventd and its plugins.
|
|
||||||
Dmeventd now also respects DM_ABORT_ON_INTERNAL_ERRORS as libdm based tool.
|
|
||||||
Report as non default dm logging also when logging with errno was changed.
|
|
||||||
Use log_level() macro to consistently decode message log level in dmeventd.
|
|
||||||
Still produce output when dmsetup dependency tree building finds dev missing.
|
|
||||||
Check and report pthread_sigmask() failure in dmeventd.
|
|
||||||
Check mem alloc fail in _canonicalize_field_ids().
|
|
||||||
Use unsigned math when checking more then 31 legs of raid.
|
|
||||||
Fix 'dmstats delete' with dmsetup older than v1.02.129
|
|
||||||
Fix stats walk segfault with dmsetup older than v1.02.129
|
|
||||||
|
|
||||||
Version 1.02.135 - 26th September 2016
|
|
||||||
======================================
|
|
||||||
Fix man entry for dmsetup status.
|
|
||||||
Introduce new dm_config_parse_without_dup_node_check().
|
|
||||||
Don't omit last entry in dmstats list --group.
|
|
||||||
|
|
||||||
Version 1.02.134 - 7th September 2016
|
|
||||||
=====================================
|
|
||||||
Improve explanation of udev fallback in libdevmapper.h.
|
|
||||||
|
|
||||||
Version 1.02.133 - 10th August 2016
|
|
||||||
===================================
|
===================================
|
||||||
Add dm_report_destroy_rows/dm_report_group_output_and_pop_all for lvm shell.
|
|
||||||
Adjust group handling and json production for lvm shell.
|
|
||||||
|
|
||||||
Version 1.02.132 - 28th July 2016
|
|
||||||
=================================
|
|
||||||
Fix json reporting to escape '"' character that may appear in reported string.
|
|
||||||
|
|
||||||
Version 1.02.131 - 15th July 2016
|
|
||||||
=================================
|
|
||||||
Disable queueing on mpath devs in blk-availability systemd service/initscript.
|
|
||||||
Add new -m|--mpathoption disablequeueing to blkdeactivate.
|
|
||||||
Automatically group regions with 'create --segments' unless --nogroup.
|
|
||||||
Fix resource leak when deleting the first member of a group.
|
|
||||||
Allow --bounds with 'create --filemap' for dmstats.
|
|
||||||
Enable creation of filemap regions with histograms.
|
|
||||||
Enable histogram aggregation for regions with more than one area.
|
|
||||||
Enable histogram aggregation for groups of regions.
|
|
||||||
Add a --filemap option to 'dmstats create' to allow mapping of files.
|
|
||||||
Add dm_stats_create_regions_from_fd() to map file extents to regions.
|
|
||||||
|
|
||||||
Version 1.02.130 - 6th July 2016
|
|
||||||
================================
|
|
||||||
Minor fixes from coverity.
|
|
||||||
|
|
||||||
Version 1.02.129 - 6th July 2016
|
|
||||||
================================
|
|
||||||
Update default dmstats field selections for groups.
|
|
||||||
Add 'obj_type', 'group_id', and 'statsname' fields to dmstats reports.
|
|
||||||
Add --area, --region, and --group to dmstats to control object selection.
|
|
||||||
Add --alias, --groupid, --regions to dmstats for group creation and deletion.
|
|
||||||
Add 'group' and 'ungroup' commands to dmstats.
|
|
||||||
Allow dm_stats_delete_group() to optionally delete all group members.
|
|
||||||
Add dm_stats_get_object_type() to return the type of object present.
|
|
||||||
Add dm_stats_walk_init() allowing control of objects visited by walks.
|
|
||||||
Add dm_stats_get_group_descriptor() to return the member list as a string.
|
|
||||||
Introduce dm_stats_get_nr_groups() and dm_stats_group_present().
|
|
||||||
Add dm_stats_{get,set}_alias() to set and retrieve alias names for groups.
|
|
||||||
Add dm_stats_get_group_id() to return the group ID for a given region.
|
|
||||||
Add dm_stats_{create,delete}_group() to allow grouping of stats regions.
|
|
||||||
Add enum-driven dm_stats_get_{metric,counter}() interfaces.
|
|
||||||
Add dm_bitset_parse_list() to parse a string representation of a bitset.
|
|
||||||
Thin dmeventd plugin umounts lvm2 volume only when pool is 95% or more.
|
|
||||||
|
|
||||||
Version 1.02.128 - 25th June 2016
|
|
||||||
=================================
|
|
||||||
Recognize 'all' keyword used in selection as synonym for "" (no selection).
|
|
||||||
Add dm_report_set_selection to set selection for multiple output of report.
|
|
||||||
Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
|
|
||||||
Move field width handling/sort init from dm_report_object to dm_report_output.
|
|
||||||
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
|
|
||||||
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
|
|
||||||
Introduce DM_REPORT_GROUP_BASIC for report group with basic report output.
|
|
||||||
Introduce DM_REPORT_GROUP_SINGLE for report group having single report only.
|
|
||||||
Add dm_report_group_{create,push,pop,destroy} to support report grouping.
|
|
||||||
|
|
||||||
Version 1.02.127 - 11th June 2016
|
|
||||||
=================================
|
|
||||||
Fix blkdeactivate regression causing skipping of dm + md devices. (1.02.126)
|
|
||||||
|
|
||||||
Version 1.02.126 - 3rd June 2016
|
|
||||||
================================
|
|
||||||
Report passthrough caching mode when parsing cache mode.
|
|
||||||
|
|
||||||
Version 1.02.125 - 14th May 2016
|
|
||||||
================================
|
|
||||||
Show library version in message even if dm driver version is unavailable.
|
|
||||||
|
|
||||||
Version 1.02.124 - 30th April 2016
|
|
||||||
==================================
|
|
||||||
Add dm_udev_wait_immediate to libdevmapper for waiting outside the library.
|
|
||||||
|
|
||||||
Version 1.02.123 - 23rd April 2016
|
|
||||||
==================================
|
|
||||||
Do not strip LVM- when debug reporting not found uuid.
|
|
||||||
|
|
||||||
Version 1.02.122 - 9th April 2016
|
|
||||||
=================================
|
|
||||||
Change log_debug ioctl flags from single characters into words.
|
|
||||||
|
|
||||||
Version 1.02.121 - 26th March 2016
|
|
||||||
==================================
|
|
||||||
Adjust raid status function.
|
|
||||||
|
|
||||||
Version 1.02.120 - 11th March 2016
|
|
||||||
==================================
|
|
||||||
Improve parsing of cache status and report Fail, Error, needs_check, ro.
|
|
||||||
|
|
||||||
Version 1.02.119 - 4th March 2016
|
|
||||||
=================================
|
|
||||||
Fix dm_config_write_node and variants to return error on subsection failures.
|
|
||||||
Remove 4096 char limit due to buffer size if writing dm_config_node.
|
|
||||||
|
|
||||||
Version 1.02.118 - 26th February 2016
|
|
||||||
=====================================
|
|
||||||
Fix string boundary check in _get_canonical_field_name().
|
|
||||||
Always initialized hist struct in _stats_parse_histogram().
|
|
||||||
|
|
||||||
Version 1.02.117 - 21st February 2016
|
|
||||||
=====================================
|
|
||||||
Improve status parsing for thin-pool and thin devices.
|
|
||||||
|
|
||||||
Version 1.02.116 - 15th February 2016
|
|
||||||
=====================================
|
|
||||||
Use fully aligned allocations for dm_pool_strdup/strndup() (1.02.64).
|
|
||||||
Fix thin-pool table parameter feature order to match kernel output.
|
|
||||||
|
|
||||||
Version 1.02.115 - 25th January 2016
|
|
||||||
====================================
|
|
||||||
Fix man page for dmsetup udevcreatecookie.
|
|
||||||
|
|
||||||
Version 1.02.114 - 14th December 2015
|
|
||||||
=====================================
|
|
||||||
Better support for dmsetup static linkage.
|
|
||||||
Extend validity checks on dmeventd client socket.
|
|
||||||
|
|
||||||
Version 1.02.113 - 5th December 2015
|
|
||||||
====================================
|
|
||||||
Mirror plugin in dmeventd uses dm_get_status_mirror().
|
|
||||||
Add dm_get_status_mirror() for parsing mirror status line.
|
|
||||||
|
|
||||||
Version 1.02.112 - 28th November 2015
|
|
||||||
=====================================
|
|
||||||
Show error message when trying to create unsupported raid type.
|
|
||||||
Improve preloading sequence of an active thin-pool target.
|
|
||||||
Drop extra space from cache target line to fix unneded table reloads.
|
|
||||||
|
|
||||||
Version 1.02.111 - 23rd November 2015
|
|
||||||
=====================================
|
|
||||||
Extend dm_hash to support multiple values with the same key.
|
|
||||||
Add missing check for allocation inside dm_split_lvm_name().
|
|
||||||
Test dm_task_get_message_response for !NULL in dm_stats_print_region().
|
|
||||||
Add checks for failing dm_stats_create() in dmsetup.
|
|
||||||
Add missing fifo close when failed to initialize client connection.
|
|
||||||
|
|
||||||
Version 1.02.110 - 30th October 2015
|
|
||||||
====================================
|
|
||||||
Disable thin monitoring plugin when it fails too often (>10 times).
|
|
||||||
Fix/restore parsing of empty field '-' when processing dmeventd event.
|
|
||||||
Enhance dm_tree_node_size_changed() to recognize size reduction.
|
|
||||||
Support exit on idle for dmenventd (1 hour).
|
|
||||||
Add support to allow unmonitor device from plugin itself.
|
|
||||||
New design for thread co-operation in dmeventd.
|
|
||||||
Dmeventd read device status with 'noflush'.
|
|
||||||
Dmeventd closes control device when no device is monitored.
|
|
||||||
Thin plugin for dmeventd improved percentage usage.
|
|
||||||
Snapshot plugin for dmeventd improved percentage usage.
|
|
||||||
Add dm_hold_control_dev to allow holding of control device open.
|
|
||||||
Add dm_report_compact_given_fields to remove given empty fields from report.
|
|
||||||
Use libdm status parsing and local mem raid dmeventd plugin.
|
|
||||||
Use local mem pool and lock only lvm2 execution for mirror dmeventd plugin.
|
|
||||||
Lock protect only lvm2 execution for snapshot and thin dmeventd plugin.
|
|
||||||
Use local mempool for raid and mirror plugins.
|
|
||||||
Reworked thread initialization for dmeventd plugins.
|
|
||||||
Dmeventd handles snapshot overflow for now equally as invalid.
|
|
||||||
Convert dmeventd to use common logging macro system from libdm.
|
|
||||||
Return -ENOMEM when device registration fails instead of 0 (=success).
|
|
||||||
Enforce writethrough mode for cleaner policy.
|
|
||||||
Add support for recognition and deactivation of MD devices to blkdeactivate.
|
|
||||||
Move target status functions out of libdm-deptree.
|
|
||||||
Correct use of max_write_behind parameter when generating raid target line.
|
|
||||||
Fix dm-event systemd service to make sure it is executed before mounting.
|
|
||||||
|
|
||||||
Version 1.02.109 - 22nd September 2015
|
|
||||||
======================================
|
|
||||||
Update man pages for dmsetup and dmstats.
|
|
||||||
Improve help text for dmsetup.
|
|
||||||
Use --noflush and --nolockfs when removing device with --force.
|
|
||||||
Parse new Overflow status string for snapshot target.
|
|
||||||
Check dir path components are valid if using dm_create_dir, error out if not.
|
|
||||||
Fix /dev/mapper handling to remove dangling entries if symlinks are found.
|
|
||||||
Make it possible to use blank value as selection for string list report field.
|
|
||||||
|
|
||||||
Version 1.02.108 - 15th September 2015
|
|
||||||
======================================
|
|
||||||
Do not check for full thin pool when activating without messages (1.02.107).
|
|
||||||
|
|
||||||
Version 1.02.107 - 5th September 2015
|
|
||||||
=====================================
|
|
||||||
Parse thin-pool status with one single routine internally.
|
|
||||||
Add --histogram to select default histogram fields for list and report.
|
|
||||||
Add report fields for displaying latency histogram configuration and data.
|
|
||||||
Add dmstats --bounds to specify histogram boundaries for a new region.
|
|
||||||
Add dm_histogram_to_string() to format histogram data in string form.
|
|
||||||
Add public methods to libdm to access numerical histogram config and data.
|
|
||||||
Parse and store histogram data in dm_stats_list() and dm_stats_populate().
|
|
||||||
Add an argument to specify histogram bounds to dm_stats_create_region().
|
|
||||||
Add dm_histogram_bounds_from_{string,uint64_t}() to parse histogram bounds.
|
|
||||||
Add dm_histogram handle type to represent a latency histogram and its bounds.
|
|
||||||
Fix devmapper.pc pkgconfig file to not reference non-existent rt.pc file.
|
|
||||||
Reinstate dm_task_get_info@Base to libdevmapper exports. (1.02.106)
|
|
||||||
|
|
||||||
Version 1.02.106 - 26th August 2015
|
|
||||||
===================================
|
|
||||||
Add 'precise' column to statistics reports.
|
|
||||||
Add --precise switch to 'dmstats create' to request nanosecond counters.
|
|
||||||
Add precise argument to dm_stats_create_region().
|
|
||||||
Add support to libdm-stats for precise_timestamps
|
|
||||||
|
|
||||||
Version 1.02.105 - 17th August 2015
|
|
||||||
===================================
|
|
||||||
Fix 'dmstats list -o all' segfault.
|
|
||||||
Separate dmstats statistics fields from region information fields.
|
|
||||||
Add interval and interval_ns fields to dmstats reports.
|
|
||||||
Do not include internal glibc headers in libdm-timestamp.c (1.02.104)
|
|
||||||
Exit immediately if no device is supplied to dmsetup wipe_table.
|
|
||||||
Suppress dmsetup report headings when no data is output. (1.02.104)
|
|
||||||
Adjust dmsetup usage/help output selection to match command invoked.
|
|
||||||
Fix dmsetup -o all to select correct fields in splitname report.
|
|
||||||
Restructure internal dmsetup argument handling across all commands.
|
|
||||||
Add dm_report_is_empty() to indicate there is no data awaiting output.
|
|
||||||
Add more arg validation for dm_tree_node_add_cache_target().
|
|
||||||
Add --alldevices switch to replace use of --force for stats create / delete.
|
|
||||||
|
|
||||||
Version 1.02.104 - 10th August 2015
|
|
||||||
===================================
|
|
||||||
Add dmstats.8 man page
|
|
||||||
Add dmstats --segments switch to create one region per device segment.
|
|
||||||
Add dmstats --regionid, --allregions to specify a single / all stats regions.
|
|
||||||
Add dmstats --allprograms for stats commands that filter by program ID.
|
|
||||||
Add dmstats --auxdata and --programid args to specify aux data and program ID.
|
|
||||||
Add report stats sub-command to provide repeating stats reports.
|
|
||||||
Add clear, delete, list, and print stats sub-commands.
|
|
||||||
Add create stats sub-command and --start, --length, --areas and --areasize.
|
|
||||||
Recognize 'dmstats' as an alias for 'dmsetup stats' when run with this name.
|
|
||||||
Add a 'stats' command to dmsetup to configure, manage and report stats data.
|
|
||||||
Add statistics fields to dmsetup -o.
|
|
||||||
Add libdm-stats library to allow management of device-mapper statistics.
|
|
||||||
Add --nosuffix to suppress dmsetup unit suffixes in report output.
|
|
||||||
Add --units to control dmsetup report field output units.
|
|
||||||
Add support to redisplay column headings for repeating column reports.
|
|
||||||
Fix report header and row resource leaks.
|
|
||||||
Report timestamps of ioctls with dmsetup -vvv.
|
|
||||||
Recognize report field name variants without any underscores too.
|
|
||||||
Add dmsetup --interval and --count to repeat reports at specified intervals.
|
|
||||||
Add dm_timestamp functions to libdevmapper.
|
|
||||||
Recognise vg/lv name format in dmsetup.
|
|
||||||
Move size display code to libdevmapper as dm_size_to_string.
|
|
||||||
|
|
||||||
Version 1.02.103 - 24th July 2015
|
|
||||||
=================================
|
|
||||||
Introduce libdevmapper wrappers for all malloc-related functions.
|
|
||||||
|
|
||||||
Version 1.02.102 - 7th July 2015
|
|
||||||
================================
|
|
||||||
Include tool.h for default non-library use.
|
|
||||||
Introduce format macros with embedded % such as FMTu64.
|
|
||||||
|
|
||||||
Version 1.02.101 - 3rd July 2015
|
|
||||||
================================
|
|
||||||
Add experimental support to passing messages in suspend tree.
|
|
||||||
Add dm_report_value_cache_{set,get} to support caching during report/select.
|
|
||||||
Add dm_report_reserved_handler to handle report reserved value actions.
|
|
||||||
Support dynamic value in select: DM_REPORT_FIELD_RESERVED_VALUE_DYNAMIC_VALUE.
|
|
||||||
Support fuzzy names in select: DM_REPORT_FIELD_RESERVED_VALUE_FUZZY_NAMES.
|
|
||||||
Thin pool trace messages show a device name and major:minor.
|
|
||||||
|
|
||||||
Version 1.02.100 - 30th June 2015
|
|
||||||
=================================
|
|
||||||
Add since, after, until and before time operators to be used in selection.
|
|
||||||
Add support for time in reports and selection: DM_REPORT_FIELD_TYPE_TIME.
|
|
||||||
Support report reserved value ranges: DM_REPORT_FIELD_RESERVED_VALUE_RANGE.
|
|
||||||
Support report reserved value names: DM_REPORT_FIELD_RESERVED_VALUE_NAMED.
|
|
||||||
Add DM_CONFIG_VALUE_FMT_{INT_OCTAL,STRING_NO_QUOTES} config value format flag.
|
|
||||||
Add DM_CONFIG_VALUE_FMT_COMMON_{ARRAY,EXTRA_SPACE} config value format flag.
|
|
||||||
Add dm_config_value_{get,set}_format_flags to get and set config value format.
|
|
||||||
|
|
||||||
Version 1.02.99 - 20th June 2015
|
|
||||||
================================
|
|
||||||
New dm_tree_node_set_thin_pool_read_only(DM_1_02_99) for read-only thin pool.
|
|
||||||
Enhance error message when thin-pool message fails.
|
|
||||||
Fix dmeventd logging to avoid threaded use of static variable.
|
|
||||||
Remove redundant dmeventd SIGALRM coded.
|
|
||||||
|
|
||||||
Version 1.02.98 - 12th June 2015
|
|
||||||
================================
|
|
||||||
Add dm_task_get_errno() to return any unexpected errno from a dm ioctl call.
|
|
||||||
Use copy of errno made after each dm ioctl call in case errno changes later.
|
|
||||||
|
|
||||||
Version 1.02.97 - 15th May 2015
|
|
||||||
===============================
|
|
||||||
New dm_task_get_info(DM_1_02_97) supports internal_suspend state.
|
|
||||||
New symbols are versioned and comes with versioned symbol name (DM_1_02_97).
|
|
||||||
|
|
||||||
Version 1.02.96 - 2nd May 2015
|
|
||||||
==============================
|
|
||||||
Fix selection to not match if using reserved value in criteria with >,<,>=,<.
|
|
||||||
Fix selection to not match reserved values for size fields if using >,<,>=,<.
|
|
||||||
Include uuid or device number in log message after ioctl failure.
|
|
||||||
Add DM_INTERNAL_SUSPEND_FLAG to dm-ioctl.h.
|
|
||||||
Install blkdeactivate script and its man page with make install_device-mapper.
|
|
||||||
|
|
||||||
Version 1.02.95 - 15th March 2015
|
|
||||||
=================================
|
|
||||||
Makefile regenerated.
|
|
||||||
|
|
||||||
Version 1.02.94 - 4th March 2015
|
|
||||||
================================
|
|
||||||
Add dm_report_object_is_selected for generalized interface for report/select.
|
|
||||||
|
|
||||||
Version 1.02.93 - 21st January 2015
|
|
||||||
===================================
|
|
||||||
Reduce severity of ioctl error message when dmeventd waitevent is interrupted.
|
|
||||||
Report 'unknown version' when incompatible version numbers were not obtained.
|
|
||||||
Report more info from thin pool status (out of data, metadata-ro, fail).
|
|
||||||
Support error_if_no_space for thin pool target.
|
|
||||||
Fix segfault while using selection with regex and unbuffered reporting.
|
|
||||||
Add dm_report_compact_fields to remove empty fields from report output.
|
|
||||||
Remove unimplemented dm_report_set_output_selection from libdevmapper.h.
|
|
||||||
|
|
||||||
Version 1.02.92 - 24th November 2014
|
|
||||||
====================================
|
|
||||||
Fix memory corruption with sorting empty string lists (1.02.86).
|
|
||||||
Fix man dmsetup.8 syntax warning of Groff
|
|
||||||
Accept unquoted strings and / in place of {} when parsing configs.
|
|
||||||
|
|
||||||
Version 1.02.91 - 11th November 2014
|
|
||||||
====================================
|
|
||||||
Update cache creation and dm_config_node to pass policy.
|
|
||||||
Allow activation of any thin-pool if transaction_id supplied is 0.
|
|
||||||
Don't print uninitialized stack bytes when non-root uses dm_check_version().
|
|
||||||
Fix selection criteria to not match reserved values when using >, <, >=, <.
|
|
||||||
Add DM_LIST_HEAD_INIT macro to libdevmapper.h.
|
|
||||||
Fix dm_is_dm_major to not issue error about missing /proc lines for dm module.
|
|
||||||
|
|
||||||
Version 1.02.90 - 1st September 2014
|
|
||||||
====================================
|
|
||||||
Restore proper buffer size for parsing mountinfo line (1.02.89)
|
|
||||||
|
|
||||||
Version 1.02.89 - 26th August 2014
|
|
||||||
==================================
|
|
||||||
Improve libdevmapper-event select() error handling.
|
|
||||||
Add extra check for matching transation_id after message submitting.
|
|
||||||
Add dm_report_field_string_list_unsorted for str. list report without sorting.
|
|
||||||
Support --deferred with dmsetup remove to defer removal of open devices.
|
|
||||||
Update dm-ioctl.h to include DM_DEFERRED_REMOVE flag.
|
|
||||||
Add support for selection to match string list subset, recognize { } operator.
|
|
||||||
Fix string list selection with '[value]' to not match list that's superset.
|
|
||||||
Fix string list selection to match whole words only, not prefixes.
|
|
||||||
|
|
||||||
Version 1.02.88 - 5th August 2014
|
|
||||||
=================================
|
|
||||||
Add dm_tree_set_optional_uuid_suffixes to handle upgrades.
|
|
||||||
|
|
||||||
Version 1.02.87 - 23rd July 2014
|
|
||||||
================================
|
|
||||||
Fix dm_report_field_string_list to handle delimiter with multiple chars.
|
|
||||||
Add dm_report_field_reserved_value for per-field reserved value definition.
|
|
||||||
|
|
||||||
Version 1.02.86 - 23rd June 2014
|
|
||||||
================================
|
|
||||||
Make "help" and "?" reporting fields implicit.
|
|
||||||
Recognize implicit "selected" field if using dm_report_init_with_selection.
|
|
||||||
Add support for implicit reporting fields which are predefined in libdm.
|
|
||||||
Add DM_REPORT_FIELD_TYPE_PERCENT: separate number and percent fields.
|
|
||||||
Add dm_percent_range_t,dm_percent_to_float,dm_make_percent to libdm for reuse.
|
|
||||||
Add dm_report_reserved_value to libdevmapper for reserved value definition.
|
|
||||||
Also display field types when listing all fields in selection help.
|
|
||||||
Recognize "help" keyword in selection string to show brief help for selection.
|
|
||||||
Always order items reported as string list field lexicographically.
|
|
||||||
Add dm_report_field_string_list to libdevmapper for direct string list report.
|
|
||||||
Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
|
|
||||||
Add dm_str_list to libdevmapper for string list type definition and its reuse.
|
|
||||||
Add dmsetup -S/--select to define selection criteria for dmsetup reports.
|
|
||||||
Add dm_report_init_with_selection to intialize report with selection criteria.
|
|
||||||
Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
|
|
||||||
Use RemoveOnStop for dm-event.socket systemd unit.
|
|
||||||
Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.
|
|
||||||
Warn user about incorrect use of cookie with 'dmsetup remove --force'.
|
|
||||||
Also recognize 'help'/'?' as reserved sort key name to show help.
|
|
||||||
Add dm_units_to_factor for size unit parsing.
|
|
||||||
Increase bitset size for minors for thin dmeventd plugin.
|
|
||||||
|
|
||||||
Version 1.02.85 - 10th April 2014
|
|
||||||
=================================
|
|
||||||
Check for sprintf error when building internal device path.
|
|
||||||
Check for sprintf error when creating path for dm control node.
|
|
||||||
When buffer for dm_get_library_version() is too small, return error code.
|
|
||||||
Always reinitialize _name_mangling_mode in dm_lib_init().
|
|
||||||
Add tracking flag about implicitly added devices into dm_tree.
|
|
||||||
Stop timeout thread immediately when the last worker thread is finished.
|
|
||||||
Fix dmeventd logging with parallel wait event processing.
|
|
||||||
Reuse _node_send_messages() for validation of transaction_id in preload.
|
|
||||||
Transaction_id could be lower by one only when messages are prepared.
|
|
||||||
Do not call callback when preload fails.
|
|
||||||
Wrap is_selinux_enabled() to be called just once.
|
|
||||||
Use correctly signed 64b constant when working with raid volumes.
|
|
||||||
Exit dmeventd with pidfile cleanup instead of raising SIGKILL on DIE request.
|
|
||||||
Add new DM_EVENT_GET_PARAMETERS request to dmeventd protocol.
|
|
||||||
Do not use systemd's reload for dmeventd restart, use dmeventd -R instead.
|
|
||||||
Drop cryptsetup rules from 10-dm.rules - cryptsetup >= 1.1.3 sets them.
|
|
||||||
|
|
||||||
Version 1.02.84 - 20th January 2014
|
|
||||||
===================================
|
|
||||||
Revert activation of activated nodes if a node preload callback fails.
|
|
||||||
Avoid busy looping on CPU when dmeventd reads event DM_WAIT_RETRY.
|
|
||||||
Ensure global mutex is held when working with dmeventd thread.
|
|
||||||
Drop taking timeout mutex for un/registering dmeventd monitor.
|
|
||||||
Allow section names in config file data to be quoted strings.
|
|
||||||
Close fifos before exiting in dmeventd restart() error path.
|
|
||||||
Move printf format string directly into dm_asprintf args list.
|
|
||||||
Catch invalid use of string sort values when reporting numerical fields.
|
|
||||||
|
|
||||||
Version 1.02.83 - 13th November 2013
|
|
||||||
====================================
|
|
||||||
Consistently report on stderr when device is not found for dmsetup info.
|
|
||||||
Skip race errors when non-udev dmsetup build runs on udev-enabled system.
|
|
||||||
Skip error message when holders are not present in sysfs.
|
|
||||||
Use __linux__ instead of linux define to make libdevmapper.h C compliant.
|
|
||||||
Use mutex to avoid possible race while creating/destroying memory pools.
|
|
||||||
Require libpthread to build now.
|
|
||||||
|
|
||||||
Version 1.02.82 - 4th October 2013
|
|
||||||
==================================
|
|
||||||
Define symbolic names for subsystem udev flags in libdevmapper for easier use.
|
|
||||||
Make subsystem udev rules responsible for importing DM_SUBSYSTEM_UDEV_FLAG*.
|
|
||||||
|
|
||||||
Version 1.02.81 - 23rd September 2013
|
|
||||||
=====================================
|
|
||||||
Tidy dmeventd fifo initialisation.
|
|
||||||
|
|
||||||
Version 1.02.80 - 20th September 2013
|
|
||||||
=====================================
|
|
||||||
Detect invalid sector supplied to 'dmsetup message'.
|
|
||||||
Free any previously-set string if a dm_task_set_* function is called again.
|
|
||||||
Do not allow passing empty new name for dmsetup rename.
|
|
||||||
Display any output returned by 'dmsetup message'.
|
|
||||||
Add dm_task_get_message_response to libdevmapper.
|
|
||||||
|
|
||||||
Version 1.02.79 - 13th August 2013
|
|
||||||
==================================
|
|
||||||
Create dmeventd timeout threads as "detached" so exit status is freed.
|
|
||||||
Add DM_ABORT_ON_INTERNAL_ERRORS env var support to abort on internal errors.
|
|
||||||
|
|
||||||
Version 1.02.78 - 24th July 2013
|
|
||||||
================================
|
|
||||||
Process thin messages once to active thin pool target for dm_tree.
|
|
||||||
Optimize out setting the same value or read_ahead.
|
|
||||||
Add DM_ARRAY_SIZE public macro.
|
|
||||||
Move syslog code out of signal handle in dmeventd.
|
|
||||||
Add DM_TO_STRING public macro.
|
Add DM_TO_STRING public macro.
|
||||||
Always return success on dmeventd -V command call.
|
Always return success on dmeventd -V command call.
|
||||||
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
|
Fix parsing of 64bit snapshot status in dmeventd snapshot plugin.
|
||||||
@@ -498,7 +14,7 @@ Version 1.02.78 - 24th July 2013
|
|||||||
Add dm_config_write_{node_out/one_node_out} for enhanced config output.
|
Add dm_config_write_{node_out/one_node_out} for enhanced config output.
|
||||||
Add dm_config_value_is_bool to check for boolean value in supported formats.
|
Add dm_config_value_is_bool to check for boolean value in supported formats.
|
||||||
Fix config node lookup inside empty sections to not return the section itself.
|
Fix config node lookup inside empty sections to not return the section itself.
|
||||||
Append discards and read-only fields to exported struct dm_status_thin_pool.
|
Extend support for status info of thin pool target.
|
||||||
Fix segfault for truncated string token in config file after the first '"'.
|
Fix segfault for truncated string token in config file after the first '"'.
|
||||||
Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
|
Close open dmeventd FIFO file descriptors on exec (FD_CLOEXEC).
|
||||||
Fix resource leak in error path of dmeventd's umount of thin volume.
|
Fix resource leak in error path of dmeventd's umount of thin volume.
|
||||||
|
|||||||
234
acinclude.m4
234
acinclude.m4
@@ -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])
|
|
||||||
])
|
|
||||||
387
aclocal.m4
vendored
387
aclocal.m4
vendored
@@ -1,7 +1,7 @@
|
|||||||
# generated automatically by aclocal 1.15 -*- Autoconf -*-
|
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
|
||||||
|
|
||||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
|
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||||
|
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||||
# This file is free software; the Free Software Foundation
|
# This file is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
# with or without modifications, as long as this notice is preserved.
|
# with or without modifications, as long as this notice is preserved.
|
||||||
@@ -11,64 +11,6 @@
|
|||||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
# PARTICULAR PURPOSE.
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
|
|
||||||
# ===========================================================================
|
|
||||||
# http://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 8
|
|
||||||
|
|
||||||
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 -*-
|
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
# serial 1 (pkg-config-0.24)
|
# serial 1 (pkg-config-0.24)
|
||||||
#
|
#
|
||||||
@@ -97,8 +39,7 @@ AC_DEFUN([AX_PYTHON_MODULE],[
|
|||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||||
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 to pkg-config utility])
|
||||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
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])
|
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||||
@@ -144,8 +85,7 @@ m4_define([_PKG_CONFIG],
|
|||||||
pkg_cv_[]$1="$$1"
|
pkg_cv_[]$1="$$1"
|
||||||
elif test -n "$PKG_CONFIG"; then
|
elif test -n "$PKG_CONFIG"; then
|
||||||
PKG_CHECK_EXISTS([$3],
|
PKG_CHECK_EXISTS([$3],
|
||||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||||
test "x$?" != "x0" && pkg_failed=yes ],
|
|
||||||
[pkg_failed=yes])
|
[pkg_failed=yes])
|
||||||
else
|
else
|
||||||
pkg_failed=untried
|
pkg_failed=untried
|
||||||
@@ -193,9 +133,9 @@ if test $pkg_failed = yes; then
|
|||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
_PKG_SHORT_ERRORS_SUPPORTED
|
_PKG_SHORT_ERRORS_SUPPORTED
|
||||||
if test $_pkg_short_errors_supported = yes; then
|
if test $_pkg_short_errors_supported = yes; then
|
||||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
|
||||||
else
|
else
|
||||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
|
||||||
fi
|
fi
|
||||||
# Put the nasty error message in config.log where it belongs
|
# Put the nasty error message in config.log where it belongs
|
||||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||||
@@ -208,7 +148,7 @@ $$1_PKG_ERRORS
|
|||||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||||
installed software in a non-standard prefix.
|
installed software in a non-standard prefix.
|
||||||
|
|
||||||
_PKG_TEXT])[]dnl
|
_PKG_TEXT])
|
||||||
])
|
])
|
||||||
elif test $pkg_failed = untried; then
|
elif test $pkg_failed = untried; then
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
@@ -219,7 +159,7 @@ path to pkg-config.
|
|||||||
|
|
||||||
_PKG_TEXT
|
_PKG_TEXT
|
||||||
|
|
||||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])
|
||||||
])
|
])
|
||||||
else
|
else
|
||||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||||
@@ -229,312 +169,3 @@ else
|
|||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# PKG_CHECK_MODULES
|
])# PKG_CHECK_MODULES
|
||||||
|
|
||||||
|
|
||||||
# PKG_INSTALLDIR(DIRECTORY)
|
|
||||||
# -------------------------
|
|
||||||
# Substitutes the variable pkgconfigdir as the location where a module
|
|
||||||
# should install pkg-config .pc files. By default the directory is
|
|
||||||
# $libdir/pkgconfig, but the default can be changed by passing
|
|
||||||
# DIRECTORY. The user can override through the --with-pkgconfigdir
|
|
||||||
# parameter.
|
|
||||||
AC_DEFUN([PKG_INSTALLDIR],
|
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
|
||||||
m4_pushdef([pkg_description],
|
|
||||||
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
|
||||||
AC_ARG_WITH([pkgconfigdir],
|
|
||||||
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
|
||||||
[with_pkgconfigdir=]pkg_default)
|
|
||||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
|
||||||
m4_popdef([pkg_default])
|
|
||||||
m4_popdef([pkg_description])
|
|
||||||
]) dnl PKG_INSTALLDIR
|
|
||||||
|
|
||||||
|
|
||||||
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
|
|
||||||
# -------------------------
|
|
||||||
# Substitutes the variable noarch_pkgconfigdir as the location where a
|
|
||||||
# module should install arch-independent pkg-config .pc files. By
|
|
||||||
# default the directory is $datadir/pkgconfig, but the default can be
|
|
||||||
# changed by passing DIRECTORY. The user can override through the
|
|
||||||
# --with-noarch-pkgconfigdir parameter.
|
|
||||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
|
||||||
m4_pushdef([pkg_description],
|
|
||||||
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
|
||||||
AC_ARG_WITH([noarch-pkgconfigdir],
|
|
||||||
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
|
||||||
[with_noarch_pkgconfigdir=]pkg_default)
|
|
||||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
|
||||||
m4_popdef([pkg_default])
|
|
||||||
m4_popdef([pkg_description])
|
|
||||||
]) dnl PKG_NOARCH_INSTALLDIR
|
|
||||||
|
|
||||||
|
|
||||||
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
|
||||||
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
|
||||||
# -------------------------------------------
|
|
||||||
# Retrieves the value of the pkg-config variable for the given module.
|
|
||||||
AC_DEFUN([PKG_CHECK_VAR],
|
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
|
||||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
|
||||||
|
|
||||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
|
||||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
|
||||||
|
|
||||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
|
||||||
])# PKG_CHECK_VAR
|
|
||||||
|
|
||||||
# Copyright (C) 1999-2014 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).
|
|
||||||
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
|
|
||||||
[python python2 python3 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-2014 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])
|
|
||||||
|
|||||||
415
autoconf/config.guess
vendored
415
autoconf/config.guess
vendored
@@ -1,12 +1,14 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Attempt to guess a canonical system name.
|
# Attempt to guess a canonical system name.
|
||||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
|
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
|
# Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2014-01-01'
|
timestamp='2009-11-20'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation; either version 3 of the License, or
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful, but
|
# This program is distributed in the hope that it will be useful, but
|
||||||
@@ -15,22 +17,26 @@ timestamp='2014-01-01'
|
|||||||
# General Public License for more details.
|
# General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
|
# 02110-1301, USA.
|
||||||
#
|
#
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
# configuration script generated by Autoconf, you may include it under
|
# configuration script generated by Autoconf, you may include it under
|
||||||
# the same distribution terms that you use for the rest of that
|
# the same distribution terms that you use for the rest of that program.
|
||||||
# program. This Exception is an additional permission under section 7
|
|
||||||
# of the GNU General Public License, version 3 ("GPLv3").
|
|
||||||
|
# Originally written by Per Bothner. Please send patches (context
|
||||||
|
# diff format) to <config-patches@gnu.org> and include a ChangeLog
|
||||||
|
# entry.
|
||||||
#
|
#
|
||||||
# Originally written by Per Bothner.
|
# This script attempts to guess a canonical system name similar to
|
||||||
|
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||||
|
# exits with 0. Otherwise, it exits with 1.
|
||||||
#
|
#
|
||||||
# You can get the latest version of this script from:
|
# You can get the latest version of this script from:
|
||||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||||
#
|
|
||||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
|
||||||
|
|
||||||
|
|
||||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||||
|
|
||||||
@@ -50,7 +56,8 @@ version="\
|
|||||||
GNU config.guess ($timestamp)
|
GNU config.guess ($timestamp)
|
||||||
|
|
||||||
Originally written by Per Bothner.
|
Originally written by Per Bothner.
|
||||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||||
@@ -132,33 +139,12 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
|||||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||||
|
|
||||||
case "${UNAME_SYSTEM}" in
|
|
||||||
Linux|GNU|GNU/*)
|
|
||||||
# If the system lacks a compiler, then just pick glibc.
|
|
||||||
# We could probably try harder.
|
|
||||||
LIBC=gnu
|
|
||||||
|
|
||||||
eval $set_cc_for_build
|
|
||||||
cat <<-EOF > $dummy.c
|
|
||||||
#include <features.h>
|
|
||||||
#if defined(__UCLIBC__)
|
|
||||||
LIBC=uclibc
|
|
||||||
#elif defined(__dietlibc__)
|
|
||||||
LIBC=dietlibc
|
|
||||||
#else
|
|
||||||
LIBC=gnu
|
|
||||||
#endif
|
|
||||||
EOF
|
|
||||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Note: order is significant - the case branches are not exclusive.
|
# Note: order is significant - the case branches are not exclusive.
|
||||||
|
|
||||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||||
*:NetBSD:*:*)
|
*:NetBSD:*:*)
|
||||||
# NetBSD (nbsd) targets should (where applicable) match one or
|
# NetBSD (nbsd) targets should (where applicable) match one or
|
||||||
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
|
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
|
||||||
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
|
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
|
||||||
# switched to ELF, *-*-netbsd* would select the old
|
# switched to ELF, *-*-netbsd* would select the old
|
||||||
# object file format. This provides both forward
|
# object file format. This provides both forward
|
||||||
@@ -194,7 +180,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
os=netbsd
|
os=netbsd
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
# The OS release
|
# The OS release
|
||||||
@@ -215,10 +201,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||||
echo "${machine}-${os}${release}"
|
echo "${machine}-${os}${release}"
|
||||||
exit ;;
|
exit ;;
|
||||||
*:Bitrig:*:*)
|
|
||||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
|
||||||
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
|
|
||||||
exit ;;
|
|
||||||
*:OpenBSD:*:*)
|
*:OpenBSD:*:*)
|
||||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||||
@@ -241,7 +223,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||||
;;
|
;;
|
||||||
*5.*)
|
*5.*)
|
||||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
|
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
# According to Compaq, /usr/sbin/psrinfo has been available on
|
# According to Compaq, /usr/sbin/psrinfo has been available on
|
||||||
@@ -287,10 +269,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
# A Xn.n version is an unreleased experimental baselevel.
|
# A Xn.n version is an unreleased experimental baselevel.
|
||||||
# 1.2 uses "1.2" for uname -r.
|
# 1.2 uses "1.2" for uname -r.
|
||||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
exit ;;
|
||||||
exitcode=$?
|
|
||||||
trap '' 0
|
|
||||||
exit $exitcode ;;
|
|
||||||
Alpha\ *:Windows_NT*:*)
|
Alpha\ *:Windows_NT*:*)
|
||||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||||
@@ -316,12 +295,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
echo s390-ibm-zvmoe
|
echo s390-ibm-zvmoe
|
||||||
exit ;;
|
exit ;;
|
||||||
*:OS400:*:*)
|
*:OS400:*:*)
|
||||||
echo powerpc-ibm-os400
|
echo powerpc-ibm-os400
|
||||||
exit ;;
|
exit ;;
|
||||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
arm*:riscos:*:*|arm*:RISCOS:*:*)
|
arm:riscos:*:*|arm:RISCOS:*:*)
|
||||||
echo arm-unknown-riscos
|
echo arm-unknown-riscos
|
||||||
exit ;;
|
exit ;;
|
||||||
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
|
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
|
||||||
@@ -415,23 +394,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
# MiNT. But MiNT is downward compatible to TOS, so this should
|
# MiNT. But MiNT is downward compatible to TOS, so this should
|
||||||
# be no problem.
|
# be no problem.
|
||||||
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
|
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||||
echo m68k-atari-mint${UNAME_RELEASE}
|
echo m68k-atari-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
|
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||||
echo m68k-atari-mint${UNAME_RELEASE}
|
echo m68k-atari-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
|
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
|
||||||
echo m68k-atari-mint${UNAME_RELEASE}
|
echo m68k-atari-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
|
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
|
||||||
echo m68k-milan-mint${UNAME_RELEASE}
|
echo m68k-milan-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
|
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
|
||||||
echo m68k-hades-mint${UNAME_RELEASE}
|
echo m68k-hades-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
||||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
m68k:machten:*:*)
|
m68k:machten:*:*)
|
||||||
echo m68k-apple-machten${UNAME_RELEASE}
|
echo m68k-apple-machten${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -501,8 +480,8 @@ EOF
|
|||||||
echo m88k-motorola-sysv3
|
echo m88k-motorola-sysv3
|
||||||
exit ;;
|
exit ;;
|
||||||
AViiON:dgux:*:*)
|
AViiON:dgux:*:*)
|
||||||
# DG/UX returns AViiON for all architectures
|
# DG/UX returns AViiON for all architectures
|
||||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||||
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
|
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
|
||||||
then
|
then
|
||||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
|
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
|
||||||
@@ -515,7 +494,7 @@ EOF
|
|||||||
else
|
else
|
||||||
echo i586-dg-dgux${UNAME_RELEASE}
|
echo i586-dg-dgux${UNAME_RELEASE}
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||||
echo m88k-dolphin-sysv3
|
echo m88k-dolphin-sysv3
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -572,7 +551,7 @@ EOF
|
|||||||
echo rs6000-ibm-aix3.2
|
echo rs6000-ibm-aix3.2
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
*:AIX:*:[4567])
|
*:AIX:*:[456])
|
||||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||||
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
||||||
IBM_ARCH=rs6000
|
IBM_ARCH=rs6000
|
||||||
@@ -615,52 +594,52 @@ EOF
|
|||||||
9000/[678][0-9][0-9])
|
9000/[678][0-9][0-9])
|
||||||
if [ -x /usr/bin/getconf ]; then
|
if [ -x /usr/bin/getconf ]; then
|
||||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||||
case "${sc_cpu_version}" in
|
case "${sc_cpu_version}" in
|
||||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||||
532) # CPU_PA_RISC2_0
|
532) # CPU_PA_RISC2_0
|
||||||
case "${sc_kernel_bits}" in
|
case "${sc_kernel_bits}" in
|
||||||
32) HP_ARCH="hppa2.0n" ;;
|
32) HP_ARCH="hppa2.0n" ;;
|
||||||
64) HP_ARCH="hppa2.0w" ;;
|
64) HP_ARCH="hppa2.0w" ;;
|
||||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||||
esac ;;
|
esac ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
if [ "${HP_ARCH}" = "" ]; then
|
if [ "${HP_ARCH}" = "" ]; then
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
sed 's/^ //' << EOF >$dummy.c
|
sed 's/^ //' << EOF >$dummy.c
|
||||||
|
|
||||||
#define _HPUX_SOURCE
|
#define _HPUX_SOURCE
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
#if defined(_SC_KERNEL_BITS)
|
#if defined(_SC_KERNEL_BITS)
|
||||||
long bits = sysconf(_SC_KERNEL_BITS);
|
long bits = sysconf(_SC_KERNEL_BITS);
|
||||||
#endif
|
#endif
|
||||||
long cpu = sysconf (_SC_CPU_VERSION);
|
long cpu = sysconf (_SC_CPU_VERSION);
|
||||||
|
|
||||||
switch (cpu)
|
switch (cpu)
|
||||||
{
|
{
|
||||||
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
||||||
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
||||||
case CPU_PA_RISC2_0:
|
case CPU_PA_RISC2_0:
|
||||||
#if defined(_SC_KERNEL_BITS)
|
#if defined(_SC_KERNEL_BITS)
|
||||||
switch (bits)
|
switch (bits)
|
||||||
{
|
{
|
||||||
case 64: puts ("hppa2.0w"); break;
|
case 64: puts ("hppa2.0w"); break;
|
||||||
case 32: puts ("hppa2.0n"); break;
|
case 32: puts ("hppa2.0n"); break;
|
||||||
default: puts ("hppa2.0"); break;
|
default: puts ("hppa2.0"); break;
|
||||||
} break;
|
} break;
|
||||||
#else /* !defined(_SC_KERNEL_BITS) */
|
#else /* !defined(_SC_KERNEL_BITS) */
|
||||||
puts ("hppa2.0"); break;
|
puts ("hppa2.0"); break;
|
||||||
#endif
|
#endif
|
||||||
default: puts ("hppa1.0"); break;
|
default: puts ("hppa1.0"); break;
|
||||||
}
|
}
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||||
@@ -751,22 +730,22 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||||
echo c1-convex-bsd
|
echo c1-convex-bsd
|
||||||
exit ;;
|
exit ;;
|
||||||
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
|
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
|
||||||
if getsysinfo -f scalar_acc
|
if getsysinfo -f scalar_acc
|
||||||
then echo c32-convex-bsd
|
then echo c32-convex-bsd
|
||||||
else echo c2-convex-bsd
|
else echo c2-convex-bsd
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
|
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
|
||||||
echo c34-convex-bsd
|
echo c34-convex-bsd
|
||||||
exit ;;
|
exit ;;
|
||||||
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
|
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
|
||||||
echo c38-convex-bsd
|
echo c38-convex-bsd
|
||||||
exit ;;
|
exit ;;
|
||||||
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
||||||
echo c4-convex-bsd
|
echo c4-convex-bsd
|
||||||
exit ;;
|
exit ;;
|
||||||
CRAY*Y-MP:*:*:*)
|
CRAY*Y-MP:*:*:*)
|
||||||
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -790,14 +769,14 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||||
exit ;;
|
exit ;;
|
||||||
5000:UNIX_System_V:4.*:*)
|
5000:UNIX_System_V:4.*:*)
|
||||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||||
@@ -809,35 +788,30 @@ EOF
|
|||||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
*:FreeBSD:*:*)
|
*:FreeBSD:*:*)
|
||||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
case ${UNAME_MACHINE} in
|
||||||
case ${UNAME_PROCESSOR} in
|
pc98)
|
||||||
|
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
||||||
amd64)
|
amd64)
|
||||||
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
||||||
*)
|
*)
|
||||||
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
||||||
esac
|
esac
|
||||||
exit ;;
|
exit ;;
|
||||||
i*:CYGWIN*:*)
|
i*:CYGWIN*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-cygwin
|
echo ${UNAME_MACHINE}-pc-cygwin
|
||||||
exit ;;
|
exit ;;
|
||||||
*:MINGW64*:*)
|
|
||||||
echo ${UNAME_MACHINE}-pc-mingw64
|
|
||||||
exit ;;
|
|
||||||
*:MINGW*:*)
|
*:MINGW*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-mingw32
|
echo ${UNAME_MACHINE}-pc-mingw32
|
||||||
exit ;;
|
exit ;;
|
||||||
i*:MSYS*:*)
|
|
||||||
echo ${UNAME_MACHINE}-pc-msys
|
|
||||||
exit ;;
|
|
||||||
i*:windows32*:*)
|
i*:windows32*:*)
|
||||||
# uname -m includes "-pc" on this system.
|
# uname -m includes "-pc" on this system.
|
||||||
echo ${UNAME_MACHINE}-mingw32
|
echo ${UNAME_MACHINE}-mingw32
|
||||||
exit ;;
|
exit ;;
|
||||||
i*:PW*:*)
|
i*:PW*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-pw32
|
echo ${UNAME_MACHINE}-pc-pw32
|
||||||
exit ;;
|
exit ;;
|
||||||
*:Interix*:*)
|
*:Interix*:*)
|
||||||
case ${UNAME_MACHINE} in
|
case ${UNAME_MACHINE} in
|
||||||
x86)
|
x86)
|
||||||
echo i586-pc-interix${UNAME_RELEASE}
|
echo i586-pc-interix${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -874,22 +848,15 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
*:GNU:*:*)
|
*:GNU:*:*)
|
||||||
# the GNU system
|
# the GNU system
|
||||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||||
exit ;;
|
exit ;;
|
||||||
*:GNU/*:*:*)
|
*:GNU/*:*:*)
|
||||||
# other systems with GNU libc and userland
|
# other systems with GNU libc and userland
|
||||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:Minix:*:*)
|
i*86:Minix:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-minix
|
echo ${UNAME_MACHINE}-pc-minix
|
||||||
exit ;;
|
exit ;;
|
||||||
aarch64:Linux:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
|
||||||
aarch64_be:Linux:*:*)
|
|
||||||
UNAME_MACHINE=aarch64_be
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
|
||||||
alpha:Linux:*:*)
|
alpha:Linux:*:*)
|
||||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||||
@@ -899,56 +866,52 @@ EOF
|
|||||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||||
esac
|
esac
|
||||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||||
exit ;;
|
|
||||||
arc:Linux:*:* | arceb:Linux:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
exit ;;
|
||||||
arm*:Linux:*:*)
|
arm*:Linux:*:*)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||||
| grep -q __ARM_EABI__
|
| grep -q __ARM_EABI__
|
||||||
then
|
then
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
else
|
else
|
||||||
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
|
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||||
| grep -q __ARM_PCS_VFP
|
|
||||||
then
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
|
|
||||||
else
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
avr32*:Linux:*:*)
|
avr32*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
cris:Linux:*:*)
|
cris:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
echo cris-axis-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
crisv32:Linux:*:*)
|
crisv32:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
echo crisv32-axis-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
frv:Linux:*:*)
|
frv:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo frv-unknown-linux-gnu
|
||||||
exit ;;
|
|
||||||
hexagon:Linux:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:Linux:*:*)
|
i*86:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
LIBC=gnu
|
||||||
|
eval $set_cc_for_build
|
||||||
|
sed 's/^ //' << EOF >$dummy.c
|
||||||
|
#ifdef __dietlibc__
|
||||||
|
LIBC=dietlibc
|
||||||
|
#endif
|
||||||
|
EOF
|
||||||
|
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||||
|
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||||
exit ;;
|
exit ;;
|
||||||
ia64:Linux:*:*)
|
ia64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
m32r*:Linux:*:*)
|
m32r*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
m68*:Linux:*:*)
|
m68*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
mips:Linux:*:* | mips64:Linux:*:*)
|
mips:Linux:*:* | mips64:Linux:*:*)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
@@ -967,63 +930,51 @@ EOF
|
|||||||
#endif
|
#endif
|
||||||
EOF
|
EOF
|
||||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||||
;;
|
;;
|
||||||
or1k:Linux:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
|
||||||
or32:Linux:*:*)
|
or32:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo or32-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
padre:Linux:*:*)
|
padre:Linux:*:*)
|
||||||
echo sparc-unknown-linux-${LIBC}
|
echo sparc-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||||
echo hppa64-unknown-linux-${LIBC}
|
echo hppa64-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||||
# Look for CPU level
|
# Look for CPU level
|
||||||
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
||||||
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
|
PA7*) echo hppa1.1-unknown-linux-gnu ;;
|
||||||
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
|
PA8*) echo hppa2.0-unknown-linux-gnu ;;
|
||||||
*) echo hppa-unknown-linux-${LIBC} ;;
|
*) echo hppa-unknown-linux-gnu ;;
|
||||||
esac
|
esac
|
||||||
exit ;;
|
exit ;;
|
||||||
ppc64:Linux:*:*)
|
ppc64:Linux:*:*)
|
||||||
echo powerpc64-unknown-linux-${LIBC}
|
echo powerpc64-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
ppc:Linux:*:*)
|
ppc:Linux:*:*)
|
||||||
echo powerpc-unknown-linux-${LIBC}
|
echo powerpc-unknown-linux-gnu
|
||||||
exit ;;
|
|
||||||
ppc64le:Linux:*:*)
|
|
||||||
echo powerpc64le-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
|
||||||
ppcle:Linux:*:*)
|
|
||||||
echo powerpcle-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
exit ;;
|
||||||
s390:Linux:*:* | s390x:Linux:*:*)
|
s390:Linux:*:* | s390x:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
echo ${UNAME_MACHINE}-ibm-linux
|
||||||
exit ;;
|
exit ;;
|
||||||
sh64*:Linux:*:*)
|
sh64*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
sh*:Linux:*:*)
|
sh*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
sparc:Linux:*:* | sparc64:Linux:*:*)
|
sparc:Linux:*:* | sparc64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
|
||||||
tile*:Linux:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
|
||||||
exit ;;
|
exit ;;
|
||||||
vax:Linux:*:*)
|
vax:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
echo ${UNAME_MACHINE}-dec-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
x86_64:Linux:*:*)
|
x86_64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo x86_64-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
xtensa*:Linux:*:*)
|
xtensa*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:DYNIX/ptx:4*:*)
|
i*86:DYNIX/ptx:4*:*)
|
||||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||||
@@ -1032,11 +983,11 @@ EOF
|
|||||||
echo i386-sequent-sysv4
|
echo i386-sequent-sysv4
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:UNIX_SV:4.2MP:2.*)
|
i*86:UNIX_SV:4.2MP:2.*)
|
||||||
# Unixware is an offshoot of SVR4, but it has its own version
|
# Unixware is an offshoot of SVR4, but it has its own version
|
||||||
# number series starting with 2...
|
# number series starting with 2...
|
||||||
# I am not positive that other SVR4 systems won't match this,
|
# I am not positive that other SVR4 systems won't match this,
|
||||||
# I just have to hope. -- rms.
|
# I just have to hope. -- rms.
|
||||||
# Use sysv4.2uw... so that sysv4* matches it.
|
# Use sysv4.2uw... so that sysv4* matches it.
|
||||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:OS/2:*:*)
|
i*86:OS/2:*:*)
|
||||||
@@ -1068,7 +1019,7 @@ EOF
|
|||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:*:5:[678]*)
|
i*86:*:5:[678]*)
|
||||||
# UnixWare 7.x, OpenUNIX and OpenServer 6.
|
# UnixWare 7.x, OpenUNIX and OpenServer 6.
|
||||||
case `/bin/uname -X | grep "^Machine"` in
|
case `/bin/uname -X | grep "^Machine"` in
|
||||||
*486*) UNAME_MACHINE=i486 ;;
|
*486*) UNAME_MACHINE=i486 ;;
|
||||||
*Pentium) UNAME_MACHINE=i586 ;;
|
*Pentium) UNAME_MACHINE=i586 ;;
|
||||||
@@ -1096,13 +1047,13 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
pc:*:*:*)
|
pc:*:*:*)
|
||||||
# Left here for compatibility:
|
# Left here for compatibility:
|
||||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||||
# the processor, so we play safe by assuming i586.
|
# the processor, so we play safe by assuming i586.
|
||||||
# Note: whatever this is, it MUST be the same as what config.sub
|
# Note: whatever this is, it MUST be the same as what config.sub
|
||||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||||
# this is a cross-build.
|
# this is a cross-build.
|
||||||
echo i586-pc-msdosdjgpp
|
echo i586-pc-msdosdjgpp
|
||||||
exit ;;
|
exit ;;
|
||||||
Intel:Mach:3*:*)
|
Intel:Mach:3*:*)
|
||||||
echo i386-pc-mach3
|
echo i386-pc-mach3
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1137,8 +1088,8 @@ EOF
|
|||||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
|
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
|
||||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||||
&& { echo i486-ncr-sysv4; exit; } ;;
|
&& { echo i486-ncr-sysv4; exit; } ;;
|
||||||
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
||||||
OS_REL='.3'
|
OS_REL='.3'
|
||||||
test -r /etc/.relid \
|
test -r /etc/.relid \
|
||||||
@@ -1181,10 +1132,10 @@ EOF
|
|||||||
echo ns32k-sni-sysv
|
echo ns32k-sni-sysv
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||||
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
||||||
echo i586-unisys-sysv4
|
echo i586-unisys-sysv4
|
||||||
exit ;;
|
exit ;;
|
||||||
*:UNIX_System_V:4*:FTX*)
|
*:UNIX_System_V:4*:FTX*)
|
||||||
# From Gerald Hewes <hewes@openmarket.com>.
|
# From Gerald Hewes <hewes@openmarket.com>.
|
||||||
# How about differentiating between stratus architectures? -djm
|
# How about differentiating between stratus architectures? -djm
|
||||||
@@ -1210,11 +1161,11 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
||||||
if [ -d /usr/nec ]; then
|
if [ -d /usr/nec ]; then
|
||||||
echo mips-nec-sysv${UNAME_RELEASE}
|
echo mips-nec-sysv${UNAME_RELEASE}
|
||||||
else
|
else
|
||||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||||
fi
|
fi
|
||||||
exit ;;
|
exit ;;
|
||||||
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
|
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
|
||||||
echo powerpc-be-beos
|
echo powerpc-be-beos
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1227,9 +1178,6 @@ EOF
|
|||||||
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
|
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
|
||||||
echo i586-pc-haiku
|
echo i586-pc-haiku
|
||||||
exit ;;
|
exit ;;
|
||||||
x86_64:Haiku:*:*)
|
|
||||||
echo x86_64-unknown-haiku
|
|
||||||
exit ;;
|
|
||||||
SX-4:SUPER-UX:*:*)
|
SX-4:SUPER-UX:*:*)
|
||||||
echo sx4-nec-superux${UNAME_RELEASE}
|
echo sx4-nec-superux${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
@@ -1256,31 +1204,19 @@ EOF
|
|||||||
exit ;;
|
exit ;;
|
||||||
*:Darwin:*:*)
|
*:Darwin:*:*)
|
||||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||||
eval $set_cc_for_build
|
case $UNAME_PROCESSOR in
|
||||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
i386)
|
||||||
UNAME_PROCESSOR=powerpc
|
eval $set_cc_for_build
|
||||||
fi
|
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
grep IS_64BIT_ARCH >/dev/null
|
||||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
then
|
||||||
grep IS_64BIT_ARCH >/dev/null
|
UNAME_PROCESSOR="x86_64"
|
||||||
then
|
fi
|
||||||
case $UNAME_PROCESSOR in
|
fi ;;
|
||||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
esac
|
||||||
esac
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
elif test "$UNAME_PROCESSOR" = i386 ; then
|
|
||||||
# Avoid executing cc on OS X 10.9, as it ships with a stub
|
|
||||||
# that puts up a graphical alert prompting to install
|
|
||||||
# developer tools. Any system running Mac OS X 10.7 or
|
|
||||||
# later (Darwin 11 and later) is required to have a 64-bit
|
|
||||||
# processor. This is not true of the ARM version of Darwin
|
|
||||||
# that Apple uses in portable devices.
|
|
||||||
UNAME_PROCESSOR=x86_64
|
|
||||||
fi
|
|
||||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||||
@@ -1294,10 +1230,7 @@ EOF
|
|||||||
*:QNX:*:4*)
|
*:QNX:*:4*)
|
||||||
echo i386-pc-qnx
|
echo i386-pc-qnx
|
||||||
exit ;;
|
exit ;;
|
||||||
NEO-?:NONSTOP_KERNEL:*:*)
|
NSE-?:NONSTOP_KERNEL:*:*)
|
||||||
echo neo-tandem-nsk${UNAME_RELEASE}
|
|
||||||
exit ;;
|
|
||||||
NSE-*:NONSTOP_KERNEL:*:*)
|
|
||||||
echo nse-tandem-nsk${UNAME_RELEASE}
|
echo nse-tandem-nsk${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
NSR-?:NONSTOP_KERNEL:*:*)
|
NSR-?:NONSTOP_KERNEL:*:*)
|
||||||
@@ -1342,13 +1275,13 @@ EOF
|
|||||||
echo pdp10-unknown-its
|
echo pdp10-unknown-its
|
||||||
exit ;;
|
exit ;;
|
||||||
SEI:*:*:SEIUX)
|
SEI:*:*:SEIUX)
|
||||||
echo mips-sei-seiux${UNAME_RELEASE}
|
echo mips-sei-seiux${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
*:DragonFly:*:*)
|
*:DragonFly:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||||
exit ;;
|
exit ;;
|
||||||
*:*VMS:*:*)
|
*:*VMS:*:*)
|
||||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||||
case "${UNAME_MACHINE}" in
|
case "${UNAME_MACHINE}" in
|
||||||
A*) echo alpha-dec-vms ; exit ;;
|
A*) echo alpha-dec-vms ; exit ;;
|
||||||
I*) echo ia64-dec-vms ; exit ;;
|
I*) echo ia64-dec-vms ; exit ;;
|
||||||
@@ -1366,11 +1299,11 @@ EOF
|
|||||||
i*86:AROS:*:*)
|
i*86:AROS:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-aros
|
echo ${UNAME_MACHINE}-pc-aros
|
||||||
exit ;;
|
exit ;;
|
||||||
x86_64:VMkernel:*:*)
|
|
||||||
echo ${UNAME_MACHINE}-unknown-esx
|
|
||||||
exit ;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||||
|
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
|
||||||
|
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
cat >$dummy.c <<EOF
|
cat >$dummy.c <<EOF
|
||||||
#ifdef _SEQUENT_
|
#ifdef _SEQUENT_
|
||||||
@@ -1388,11 +1321,11 @@ main ()
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
printf ("m68k-sony-newsos%s\n",
|
printf ("m68k-sony-newsos%s\n",
|
||||||
#ifdef NEWSOS4
|
#ifdef NEWSOS4
|
||||||
"4"
|
"4"
|
||||||
#else
|
#else
|
||||||
""
|
""
|
||||||
#endif
|
#endif
|
||||||
); exit (0);
|
); exit (0);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
288
autoconf/config.sub
vendored
288
autoconf/config.sub
vendored
@@ -1,31 +1,38 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
|
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
|
# Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2014-01-01'
|
timestamp='2009-11-20'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is (in principle) common to ALL GNU software.
|
||||||
# under the terms of the GNU General Public License as published by
|
# The presence of a machine in this file suggests that SOME GNU software
|
||||||
# the Free Software Foundation; either version 3 of the License, or
|
# can handle that machine. It does not imply ALL GNU software can.
|
||||||
|
#
|
||||||
|
# This file 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.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# This program is distributed in the hope that it will be useful, but
|
# This program is distributed in the hope that it will be useful,
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
|
# 02110-1301, USA.
|
||||||
#
|
#
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
# configuration script generated by Autoconf, you may include it under
|
# configuration script generated by Autoconf, you may include it under
|
||||||
# the same distribution terms that you use for the rest of that
|
# the same distribution terms that you use for the rest of that program.
|
||||||
# program. This Exception is an additional permission under section 7
|
|
||||||
# of the GNU General Public License, version 3 ("GPLv3").
|
|
||||||
|
|
||||||
|
|
||||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||||
|
# diff and a properly formatted GNU ChangeLog entry.
|
||||||
#
|
#
|
||||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||||
# Supply the specified configuration type as an argument.
|
# Supply the specified configuration type as an argument.
|
||||||
@@ -68,7 +75,8 @@ Report bugs and patches to <config-patches@gnu.org>."
|
|||||||
version="\
|
version="\
|
||||||
GNU config.sub ($timestamp)
|
GNU config.sub ($timestamp)
|
||||||
|
|
||||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
|
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||||
@@ -115,18 +123,13 @@ esac
|
|||||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||||
case $maybe_os in
|
case $maybe_os in
|
||||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
|
||||||
kopensolaris*-gnu* | \
|
kopensolaris*-gnu* | \
|
||||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||||
os=-$maybe_os
|
os=-$maybe_os
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||||
;;
|
;;
|
||||||
android-linux)
|
|
||||||
os=-linux-android
|
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||||
if [ $basic_machine != $1 ]
|
if [ $basic_machine != $1 ]
|
||||||
@@ -149,12 +152,12 @@ case $os in
|
|||||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
-apple | -axis | -knuth | -cray | -microblaze)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
-bluegene*)
|
-bluegene*)
|
||||||
os=-cnk
|
os=-cnk
|
||||||
;;
|
;;
|
||||||
-sim | -cisco | -oki | -wec | -winbond)
|
-sim | -cisco | -oki | -wec | -winbond)
|
||||||
os=
|
os=
|
||||||
@@ -170,10 +173,10 @@ case $os in
|
|||||||
os=-chorusos
|
os=-chorusos
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
-chorusrdb)
|
-chorusrdb)
|
||||||
os=-chorusrdb
|
os=-chorusrdb
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
-hiux*)
|
-hiux*)
|
||||||
os=-hiuxwe2
|
os=-hiuxwe2
|
||||||
;;
|
;;
|
||||||
@@ -218,12 +221,6 @@ case $os in
|
|||||||
-isc*)
|
-isc*)
|
||||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
;;
|
;;
|
||||||
-lynx*178)
|
|
||||||
os=-lynxos178
|
|
||||||
;;
|
|
||||||
-lynx*5)
|
|
||||||
os=-lynxos5
|
|
||||||
;;
|
|
||||||
-lynx*)
|
-lynx*)
|
||||||
os=-lynxos
|
os=-lynxos
|
||||||
;;
|
;;
|
||||||
@@ -248,28 +245,20 @@ case $basic_machine in
|
|||||||
# Some are omitted here because they have special meanings below.
|
# Some are omitted here because they have special meanings below.
|
||||||
1750a | 580 \
|
1750a | 580 \
|
||||||
| a29k \
|
| a29k \
|
||||||
| aarch64 | aarch64_be \
|
|
||||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||||
| am33_2.0 \
|
| am33_2.0 \
|
||||||
| arc | arceb \
|
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
|
||||||
| avr | avr32 \
|
|
||||||
| be32 | be64 \
|
|
||||||
| bfin \
|
| bfin \
|
||||||
| c4x | c8051 | clipper \
|
| c4x | clipper \
|
||||||
| d10v | d30v | dlx | dsp16xx \
|
| d10v | d30v | dlx | dsp16xx \
|
||||||
| epiphany \
|
|
||||||
| fido | fr30 | frv \
|
| fido | fr30 | frv \
|
||||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||||
| hexagon \
|
|
||||||
| i370 | i860 | i960 | ia64 \
|
| i370 | i860 | i960 | ia64 \
|
||||||
| ip2k | iq2000 \
|
| ip2k | iq2000 \
|
||||||
| k1om \
|
|
||||||
| le32 | le64 \
|
|
||||||
| lm32 \
|
| lm32 \
|
||||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
| maxq | mb | microblaze | mcore | mep | metag \
|
||||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||||
| mips16 \
|
| mips16 \
|
||||||
| mips64 | mips64el \
|
| mips64 | mips64el \
|
||||||
@@ -287,45 +276,34 @@ case $basic_machine in
|
|||||||
| mipsisa64r2 | mipsisa64r2el \
|
| mipsisa64r2 | mipsisa64r2el \
|
||||||
| mipsisa64sb1 | mipsisa64sb1el \
|
| mipsisa64sb1 | mipsisa64sb1el \
|
||||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||||
| mipsr5900 | mipsr5900el \
|
|
||||||
| mipstx39 | mipstx39el \
|
| mipstx39 | mipstx39el \
|
||||||
| mn10200 | mn10300 \
|
| mn10200 | mn10300 \
|
||||||
| moxie \
|
| moxie \
|
||||||
| mt \
|
| mt \
|
||||||
| msp430 \
|
| msp430 \
|
||||||
| nds32 | nds32le | nds32be \
|
| nios | nios2 \
|
||||||
| nios | nios2 | nios2eb | nios2el \
|
|
||||||
| ns16k | ns32k \
|
| ns16k | ns32k \
|
||||||
| open8 \
|
| or32 \
|
||||||
| or1k | or32 \
|
|
||||||
| pdp10 | pdp11 | pj | pjl \
|
| pdp10 | pdp11 | pj | pjl \
|
||||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||||
| pyramid \
|
| pyramid \
|
||||||
| rl78 | rx \
|
| rx \
|
||||||
| score \
|
| score \
|
||||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||||
| sh64 | sh64le \
|
| sh64 | sh64le \
|
||||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||||
| spu \
|
| spu | strongarm \
|
||||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
| tahoe | thumb | tic4x | tic80 | tron \
|
||||||
| ubicom32 \
|
| ubicom32 \
|
||||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
| v850 | v850e \
|
||||||
| we32k \
|
| we32k \
|
||||||
| x86 | xc16x | xstormy16 | xtensa \
|
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||||
| z8k | z80)
|
| z8k | z80)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
;;
|
;;
|
||||||
c54x)
|
m6811 | m68hc11 | m6812 | m68hc12 | picochip)
|
||||||
basic_machine=tic54x-unknown
|
# Motorola 68HC11/12.
|
||||||
;;
|
|
||||||
c55x)
|
|
||||||
basic_machine=tic55x-unknown
|
|
||||||
;;
|
|
||||||
c6x)
|
|
||||||
basic_machine=tic6x-unknown
|
|
||||||
;;
|
|
||||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
os=-none
|
os=-none
|
||||||
;;
|
;;
|
||||||
@@ -335,21 +313,6 @@ case $basic_machine in
|
|||||||
basic_machine=mt-unknown
|
basic_machine=mt-unknown
|
||||||
;;
|
;;
|
||||||
|
|
||||||
strongarm | thumb | xscale)
|
|
||||||
basic_machine=arm-unknown
|
|
||||||
;;
|
|
||||||
xgate)
|
|
||||||
basic_machine=$basic_machine-unknown
|
|
||||||
os=-none
|
|
||||||
;;
|
|
||||||
xscaleeb)
|
|
||||||
basic_machine=armeb-unknown
|
|
||||||
;;
|
|
||||||
|
|
||||||
xscaleel)
|
|
||||||
basic_machine=armel-unknown
|
|
||||||
;;
|
|
||||||
|
|
||||||
# We use `pc' rather than `unknown'
|
# We use `pc' rather than `unknown'
|
||||||
# because (1) that's what they normally are, and
|
# because (1) that's what they normally are, and
|
||||||
# (2) the word "unknown" tends to confuse beginning users.
|
# (2) the word "unknown" tends to confuse beginning users.
|
||||||
@@ -364,31 +327,25 @@ case $basic_machine in
|
|||||||
# Recognize the basic CPU types with company name.
|
# Recognize the basic CPU types with company name.
|
||||||
580-* \
|
580-* \
|
||||||
| a29k-* \
|
| a29k-* \
|
||||||
| aarch64-* | aarch64_be-* \
|
|
||||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| avr-* | avr32-* \
|
| avr-* | avr32-* \
|
||||||
| be32-* | be64-* \
|
|
||||||
| bfin-* | bs2000-* \
|
| bfin-* | bs2000-* \
|
||||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
| clipper-* | craynv-* | cydra-* \
|
||||||
| d10v-* | d30v-* | dlx-* \
|
| d10v-* | d30v-* | dlx-* \
|
||||||
| elxsi-* \
|
| elxsi-* \
|
||||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||||
| h8300-* | h8500-* \
|
| h8300-* | h8500-* \
|
||||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||||
| hexagon-* \
|
|
||||||
| i*86-* | i860-* | i960-* | ia64-* \
|
| i*86-* | i860-* | i960-* | ia64-* \
|
||||||
| ip2k-* | iq2000-* \
|
| ip2k-* | iq2000-* \
|
||||||
| k1om-* \
|
|
||||||
| le32-* | le64-* \
|
|
||||||
| lm32-* \
|
| lm32-* \
|
||||||
| m32c-* | m32r-* | m32rle-* \
|
| m32c-* | m32r-* | m32rle-* \
|
||||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
|
||||||
| microblaze-* | microblazeel-* \
|
|
||||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||||
| mips16-* \
|
| mips16-* \
|
||||||
| mips64-* | mips64el-* \
|
| mips64-* | mips64el-* \
|
||||||
@@ -406,34 +363,29 @@ case $basic_machine in
|
|||||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||||
| mipsr5900-* | mipsr5900el-* \
|
|
||||||
| mipstx39-* | mipstx39el-* \
|
| mipstx39-* | mipstx39el-* \
|
||||||
| mmix-* \
|
| mmix-* \
|
||||||
| mt-* \
|
| mt-* \
|
||||||
| msp430-* \
|
| msp430-* \
|
||||||
| nds32-* | nds32le-* | nds32be-* \
|
| nios-* | nios2-* \
|
||||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
|
||||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||||
| open8-* \
|
|
||||||
| orion-* \
|
| orion-* \
|
||||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||||
| pyramid-* \
|
| pyramid-* \
|
||||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
| romp-* | rs6000-* | rx-* \
|
||||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||||
| sparclite-* \
|
| sparclite-* \
|
||||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||||
| tahoe-* \
|
| tahoe-* | thumb-* \
|
||||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||||
| tile*-* \
|
|
||||||
| tron-* \
|
| tron-* \
|
||||||
| ubicom32-* \
|
| ubicom32-* \
|
||||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
| v850-* | v850e-* | vax-* \
|
||||||
| vax-* \
|
|
||||||
| we32k-* \
|
| we32k-* \
|
||||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||||
| xstormy16-* | xtensa*-* \
|
| xstormy16-* | xtensa*-* \
|
||||||
| ymp-* \
|
| ymp-* \
|
||||||
| z8k-* | z80-*)
|
| z8k-* | z80-*)
|
||||||
@@ -458,7 +410,7 @@ case $basic_machine in
|
|||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
;;
|
;;
|
||||||
abacus)
|
abacus)
|
||||||
basic_machine=abacus-unknown
|
basic_machine=abacus-unknown
|
||||||
;;
|
;;
|
||||||
adobe68k)
|
adobe68k)
|
||||||
@@ -528,20 +480,11 @@ case $basic_machine in
|
|||||||
basic_machine=powerpc-ibm
|
basic_machine=powerpc-ibm
|
||||||
os=-cnk
|
os=-cnk
|
||||||
;;
|
;;
|
||||||
c54x-*)
|
|
||||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
|
||||||
;;
|
|
||||||
c55x-*)
|
|
||||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
|
||||||
;;
|
|
||||||
c6x-*)
|
|
||||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
|
||||||
;;
|
|
||||||
c90)
|
c90)
|
||||||
basic_machine=c90-cray
|
basic_machine=c90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
cegcc)
|
cegcc)
|
||||||
basic_machine=arm-unknown
|
basic_machine=arm-unknown
|
||||||
os=-cegcc
|
os=-cegcc
|
||||||
;;
|
;;
|
||||||
@@ -573,7 +516,7 @@ case $basic_machine in
|
|||||||
basic_machine=craynv-cray
|
basic_machine=craynv-cray
|
||||||
os=-unicosmp
|
os=-unicosmp
|
||||||
;;
|
;;
|
||||||
cr16 | cr16-*)
|
cr16)
|
||||||
basic_machine=cr16-unknown
|
basic_machine=cr16-unknown
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
@@ -731,6 +674,7 @@ case $basic_machine in
|
|||||||
i370-ibm* | ibm*)
|
i370-ibm* | ibm*)
|
||||||
basic_machine=i370-ibm
|
basic_machine=i370-ibm
|
||||||
;;
|
;;
|
||||||
|
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||||
i*86v32)
|
i*86v32)
|
||||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||||
os=-sysv32
|
os=-sysv32
|
||||||
@@ -788,15 +732,11 @@ case $basic_machine in
|
|||||||
basic_machine=ns32k-utek
|
basic_machine=ns32k-utek
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
microblaze*)
|
microblaze)
|
||||||
basic_machine=microblaze-xilinx
|
basic_machine=microblaze-xilinx
|
||||||
;;
|
;;
|
||||||
mingw64)
|
|
||||||
basic_machine=x86_64-pc
|
|
||||||
os=-mingw64
|
|
||||||
;;
|
|
||||||
mingw32)
|
mingw32)
|
||||||
basic_machine=i686-pc
|
basic_machine=i386-pc
|
||||||
os=-mingw32
|
os=-mingw32
|
||||||
;;
|
;;
|
||||||
mingw32ce)
|
mingw32ce)
|
||||||
@@ -831,18 +771,10 @@ case $basic_machine in
|
|||||||
ms1-*)
|
ms1-*)
|
||||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||||
;;
|
;;
|
||||||
msys)
|
|
||||||
basic_machine=i686-pc
|
|
||||||
os=-msys
|
|
||||||
;;
|
|
||||||
mvs)
|
mvs)
|
||||||
basic_machine=i370-ibm
|
basic_machine=i370-ibm
|
||||||
os=-mvs
|
os=-mvs
|
||||||
;;
|
;;
|
||||||
nacl)
|
|
||||||
basic_machine=le32-unknown
|
|
||||||
os=-nacl
|
|
||||||
;;
|
|
||||||
ncr3000)
|
ncr3000)
|
||||||
basic_machine=i486-ncr
|
basic_machine=i486-ncr
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
@@ -907,12 +839,6 @@ case $basic_machine in
|
|||||||
np1)
|
np1)
|
||||||
basic_machine=np1-gould
|
basic_machine=np1-gould
|
||||||
;;
|
;;
|
||||||
neo-tandem)
|
|
||||||
basic_machine=neo-tandem
|
|
||||||
;;
|
|
||||||
nse-tandem)
|
|
||||||
basic_machine=nse-tandem
|
|
||||||
;;
|
|
||||||
nsr-tandem)
|
nsr-tandem)
|
||||||
basic_machine=nsr-tandem
|
basic_machine=nsr-tandem
|
||||||
;;
|
;;
|
||||||
@@ -995,10 +921,9 @@ case $basic_machine in
|
|||||||
;;
|
;;
|
||||||
power) basic_machine=power-ibm
|
power) basic_machine=power-ibm
|
||||||
;;
|
;;
|
||||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
ppc) basic_machine=powerpc-unknown
|
||||||
;;
|
;;
|
||||||
ppc-* | ppcbe-*)
|
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
|
||||||
;;
|
;;
|
||||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||||
basic_machine=powerpcle-unknown
|
basic_machine=powerpcle-unknown
|
||||||
@@ -1023,11 +948,7 @@ case $basic_machine in
|
|||||||
basic_machine=i586-unknown
|
basic_machine=i586-unknown
|
||||||
os=-pw32
|
os=-pw32
|
||||||
;;
|
;;
|
||||||
rdos | rdos64)
|
rdos)
|
||||||
basic_machine=x86_64-pc
|
|
||||||
os=-rdos
|
|
||||||
;;
|
|
||||||
rdos32)
|
|
||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-rdos
|
os=-rdos
|
||||||
;;
|
;;
|
||||||
@@ -1096,9 +1017,6 @@ case $basic_machine in
|
|||||||
basic_machine=i860-stratus
|
basic_machine=i860-stratus
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
strongarm-* | thumb-*)
|
|
||||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
|
||||||
;;
|
|
||||||
sun2)
|
sun2)
|
||||||
basic_machine=m68000-sun
|
basic_machine=m68000-sun
|
||||||
;;
|
;;
|
||||||
@@ -1155,8 +1073,20 @@ case $basic_machine in
|
|||||||
basic_machine=t90-cray
|
basic_machine=t90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
tic54x | c54x*)
|
||||||
|
basic_machine=tic54x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tic55x | c55x*)
|
||||||
|
basic_machine=tic55x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tic6x | c6x*)
|
||||||
|
basic_machine=tic6x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
tile*)
|
tile*)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=tile-unknown
|
||||||
os=-linux-gnu
|
os=-linux-gnu
|
||||||
;;
|
;;
|
||||||
tx39)
|
tx39)
|
||||||
@@ -1226,9 +1156,6 @@ case $basic_machine in
|
|||||||
xps | xps100)
|
xps | xps100)
|
||||||
basic_machine=xps100-honeywell
|
basic_machine=xps100-honeywell
|
||||||
;;
|
;;
|
||||||
xscale-* | xscalee[bl]-*)
|
|
||||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
|
||||||
;;
|
|
||||||
ymp)
|
ymp)
|
||||||
basic_machine=ymp-cray
|
basic_machine=ymp-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
@@ -1326,11 +1253,11 @@ esac
|
|||||||
if [ x"$os" != x"" ]
|
if [ x"$os" != x"" ]
|
||||||
then
|
then
|
||||||
case $os in
|
case $os in
|
||||||
# First match some system type aliases
|
# First match some system type aliases
|
||||||
# that might get confused with valid system types.
|
# that might get confused with valid system types.
|
||||||
# -solaris* is a basic system type, with this one exception.
|
# -solaris* is a basic system type, with this one exception.
|
||||||
-auroraux)
|
-auroraux)
|
||||||
os=-auroraux
|
os=-auroraux
|
||||||
;;
|
;;
|
||||||
-solaris1 | -solaris1.*)
|
-solaris1 | -solaris1.*)
|
||||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||||
@@ -1354,21 +1281,20 @@ case $os in
|
|||||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||||
| -sym* | -kopensolaris* | -plan9* \
|
| -sym* | -kopensolaris* \
|
||||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||||
| -aos* | -aros* \
|
| -aos* | -aros* \
|
||||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||||
| -bitrig* | -openbsd* | -solidbsd* \
|
| -openbsd* | -solidbsd* \
|
||||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
|
||||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||||
@@ -1415,7 +1341,7 @@ case $os in
|
|||||||
-opened*)
|
-opened*)
|
||||||
os=-openedition
|
os=-openedition
|
||||||
;;
|
;;
|
||||||
-os400*)
|
-os400*)
|
||||||
os=-os400
|
os=-os400
|
||||||
;;
|
;;
|
||||||
-wince*)
|
-wince*)
|
||||||
@@ -1464,7 +1390,7 @@ case $os in
|
|||||||
-sinix*)
|
-sinix*)
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
-tpf*)
|
-tpf*)
|
||||||
os=-tpf
|
os=-tpf
|
||||||
;;
|
;;
|
||||||
-triton*)
|
-triton*)
|
||||||
@@ -1500,14 +1426,15 @@ case $os in
|
|||||||
-aros*)
|
-aros*)
|
||||||
os=-aros
|
os=-aros
|
||||||
;;
|
;;
|
||||||
|
-kaos*)
|
||||||
|
os=-kaos
|
||||||
|
;;
|
||||||
-zvmoe)
|
-zvmoe)
|
||||||
os=-zvmoe
|
os=-zvmoe
|
||||||
;;
|
;;
|
||||||
-dicos*)
|
-dicos*)
|
||||||
os=-dicos
|
os=-dicos
|
||||||
;;
|
;;
|
||||||
-nacl*)
|
|
||||||
;;
|
|
||||||
-none)
|
-none)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -1530,10 +1457,10 @@ else
|
|||||||
# system, and we'll never get to this point.
|
# system, and we'll never get to this point.
|
||||||
|
|
||||||
case $basic_machine in
|
case $basic_machine in
|
||||||
score-*)
|
score-*)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
spu-*)
|
spu-*)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
*-acorn)
|
*-acorn)
|
||||||
@@ -1545,23 +1472,8 @@ case $basic_machine in
|
|||||||
arm*-semi)
|
arm*-semi)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
c4x-* | tic4x-*)
|
c4x-* | tic4x-*)
|
||||||
os=-coff
|
os=-coff
|
||||||
;;
|
|
||||||
c8051-*)
|
|
||||||
os=-elf
|
|
||||||
;;
|
|
||||||
hexagon-*)
|
|
||||||
os=-elf
|
|
||||||
;;
|
|
||||||
tic54x-*)
|
|
||||||
os=-coff
|
|
||||||
;;
|
|
||||||
tic55x-*)
|
|
||||||
os=-coff
|
|
||||||
;;
|
|
||||||
tic6x-*)
|
|
||||||
os=-coff
|
|
||||||
;;
|
;;
|
||||||
# This must come before the *-dec entry.
|
# This must come before the *-dec entry.
|
||||||
pdp10-*)
|
pdp10-*)
|
||||||
@@ -1581,11 +1493,14 @@ case $basic_machine in
|
|||||||
;;
|
;;
|
||||||
m68000-sun)
|
m68000-sun)
|
||||||
os=-sunos3
|
os=-sunos3
|
||||||
|
# This also exists in the configure program, but was not the
|
||||||
|
# default.
|
||||||
|
# os=-sunos4
|
||||||
;;
|
;;
|
||||||
m68*-cisco)
|
m68*-cisco)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
mep-*)
|
mep-*)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
mips*-cisco)
|
mips*-cisco)
|
||||||
@@ -1594,9 +1509,6 @@ case $basic_machine in
|
|||||||
mips*-*)
|
mips*-*)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
or1k-*)
|
|
||||||
os=-elf
|
|
||||||
;;
|
|
||||||
or32-*)
|
or32-*)
|
||||||
os=-coff
|
os=-coff
|
||||||
;;
|
;;
|
||||||
@@ -1615,7 +1527,7 @@ case $basic_machine in
|
|||||||
*-ibm)
|
*-ibm)
|
||||||
os=-aix
|
os=-aix
|
||||||
;;
|
;;
|
||||||
*-knuth)
|
*-knuth)
|
||||||
os=-mmixware
|
os=-mmixware
|
||||||
;;
|
;;
|
||||||
*-wec)
|
*-wec)
|
||||||
|
|||||||
@@ -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:
|
|
||||||
6
conf/.gitignore
vendored
6
conf/.gitignore
vendored
@@ -1,6 +0,0 @@
|
|||||||
command_profile_template.profile
|
|
||||||
example.conf
|
|
||||||
lvmlocal.conf
|
|
||||||
metadata_profile_template.profile
|
|
||||||
configure.h
|
|
||||||
lvm-version.h
|
|
||||||
@@ -1,58 +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@
|
|
||||||
|
|
||||||
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)/lvmdbusd.profile
|
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
|
||||||
|
|
||||||
.PHONY: install_conf install_localconf install_profiles
|
|
||||||
|
|
||||||
generate:
|
|
||||||
(cat $(top_srcdir)/conf/example.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --withcomments --ignorelocal --withspaces) > example.conf.in
|
|
||||||
(cat $(top_srcdir)/conf/lvmlocal.conf.base && LD_LIBRARY_PATH=$(top_builddir)/libdm:$(LD_LIBRARY_PATH) $(top_builddir)/tools/lvm dumpconfig --type default --unconfigured --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)
|
|
||||||
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_PROFILE_DIR)
|
|
||||||
$(INSTALL_DATA) $(PROFILES) $(DESTDIR)$(DEFAULT_PROFILE_DIR)/
|
|
||||||
|
|
||||||
install_lvm2: install_conf install_localconf install_profiles
|
|
||||||
|
|
||||||
install: install_lvm2
|
|
||||||
|
|
||||||
DISTCLEAN_TARGETS += $(CONFSRC) $(CONFLOCAL) $(PROFILE_TEMPLATES)
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 settins for "smq" policy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# This is an example configuration file for the LVM2 system.
|
|
||||||
# It contains the default settings that would be used if there was no
|
|
||||||
# @DEFAULT_SYS_DIR@/lvm.conf file.
|
|
||||||
#
|
|
||||||
# Refer to 'man lvm.conf' for further information including the file layout.
|
|
||||||
#
|
|
||||||
# Refer to 'man lvm.conf' for information about how settings configured in
|
|
||||||
# this file are combined with built-in values and command line options to
|
|
||||||
# arrive at the final values used by LVM.
|
|
||||||
#
|
|
||||||
# Refer to 'man lvmconfig' for information about displaying the built-in
|
|
||||||
# and configured values used by LVM.
|
|
||||||
#
|
|
||||||
# If a default value is set in this file (not commented out), then a
|
|
||||||
# new version of LVM using this file will continue using that value,
|
|
||||||
# even if the new version of LVM changes the built-in default value.
|
|
||||||
#
|
|
||||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
|
|
||||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
|
|
||||||
#
|
|
||||||
# N.B. Take care that each setting only appears once if uncommenting
|
|
||||||
# example settings in this file.
|
|
||||||
|
|
||||||
2104
conf/example.conf.in
2104
conf/example.conf.in
File diff suppressed because it is too large
Load Diff
@@ -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"
|
|
||||||
}
|
|
||||||
@@ -1,19 +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.
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
allocation {
|
|
||||||
thin_pool_chunk_size_policy = "generic"
|
|
||||||
thin_pool_zero = 1
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
allocation {
|
|
||||||
thin_pool_chunk_size_policy = "performance"
|
|
||||||
thin_pool_zero = 0
|
|
||||||
}
|
|
||||||
1392
configure.in
1392
configure.in
File diff suppressed because it is too large
Load Diff
@@ -1,122 +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];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -9,13 +9,17 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
.PHONY: dmeventd clvmd cmirrord lvmetad lvmpolld lvmlockd
|
ifeq ("@BUILD_LVMETAD@", "yes")
|
||||||
|
SUBDIRS += lvmetad
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: dmeventd clvmd cmirrord lvmetad
|
||||||
|
|
||||||
ifneq ("@CLVMD@", "none")
|
ifneq ("@CLVMD@", "none")
|
||||||
SUBDIRS += clvmd
|
SUBDIRS += clvmd
|
||||||
@@ -32,24 +36,8 @@ daemons.cflow: dmeventd.cflow
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@BUILD_LVMETAD@", "yes")
|
|
||||||
SUBDIRS += lvmetad
|
|
||||||
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)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd
|
SUBDIRS = clvmd cmirrord dmeventd lvmetad
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|||||||
1
daemons/clvmd/.gitignore
vendored
1
daemons/clvmd/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
clvmd
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
@@ -36,6 +36,10 @@ SOURCES = \
|
|||||||
lvm-functions.c \
|
lvm-functions.c \
|
||||||
refresh_clvmd.c
|
refresh_clvmd.c
|
||||||
|
|
||||||
|
ifeq ("@DEBUG@", "yes")
|
||||||
|
DEFS += -DDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||||
SOURCES += clvmd-cman.c
|
SOURCES += clvmd-cman.c
|
||||||
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
|
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
|
||||||
@@ -83,8 +87,8 @@ include $(top_builddir)/make.tmpl
|
|||||||
LVMLIBS += -ldevmapper
|
LVMLIBS += -ldevmapper
|
||||||
LIBS += $(PTHREAD_LIBS)
|
LIBS += $(PTHREAD_LIBS)
|
||||||
|
|
||||||
CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS)
|
DEFS += -D_REENTRANT
|
||||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
|
||||||
INSTALL_TARGETS = \
|
INSTALL_TARGETS = \
|
||||||
install_clvmd
|
install_clvmd
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Definitions for CLVMD server and clients */
|
/* Definitions for CLVMD server and clients */
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
#define _CLVM_H
|
#define _CLVM_H
|
||||||
|
|
||||||
#include "configure.h"
|
#include "configure.h"
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
struct clvm_header {
|
struct clvm_header {
|
||||||
uint8_t cmd; /* See below */
|
uint8_t cmd; /* See below */
|
||||||
@@ -50,7 +49,7 @@ struct clvm_header {
|
|||||||
#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
|
#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
|
||||||
|
|
||||||
/* Name of the local socket to communicate between lvm and clvmd */
|
/* Name of the local socket to communicate between lvm and clvmd */
|
||||||
#define CLVMD_SOCKNAME DEFAULT_RUN_DIR "/clvmd.sock"
|
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
|
||||||
|
|
||||||
/* Internal commands & replies */
|
/* Internal commands & replies */
|
||||||
#define CLVMD_CMD_REPLY 1
|
#define CLVMD_CMD_REPLY 1
|
||||||
@@ -76,10 +75,8 @@ struct clvm_header {
|
|||||||
#define CLVMD_CMD_SYNC_NAMES 45
|
#define CLVMD_CMD_SYNC_NAMES 45
|
||||||
|
|
||||||
/* Used internally by some callers, but not part of the protocol.*/
|
/* Used internally by some callers, but not part of the protocol.*/
|
||||||
#ifndef NODE_ALL
|
#define NODE_ALL "*"
|
||||||
# define NODE_ALL "*"
|
#define NODE_LOCAL "."
|
||||||
# define NODE_LOCAL "."
|
#define NODE_REMOTE "^"
|
||||||
# define NODE_REMOTE "^"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -110,12 +110,12 @@ static void _cluster_init_completed(void)
|
|||||||
clvmd_cluster_init_completed();
|
clvmd_cluster_init_completed();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_main_cluster_fd(void)
|
static int _get_main_cluster_fd()
|
||||||
{
|
{
|
||||||
return cman_get_fd(c_handle);
|
return cman_get_fd(c_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_num_nodes(void)
|
static int _get_num_nodes()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int nnodes = 0;
|
int nnodes = 0;
|
||||||
@@ -243,8 +243,9 @@ static void _add_up_node(const char *csid)
|
|||||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cluster_closedown(void)
|
static void _cluster_closedown()
|
||||||
{
|
{
|
||||||
|
destroy_lvhash();
|
||||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||||
cman_finish(c_handle);
|
cman_finish(c_handle);
|
||||||
}
|
}
|
||||||
@@ -282,7 +283,7 @@ static void count_clvmds_running(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a list of active cluster members */
|
/* Get a list of active cluster members */
|
||||||
static void get_members(void)
|
static void get_members()
|
||||||
{
|
{
|
||||||
int retnodes;
|
int retnodes;
|
||||||
int status;
|
int status;
|
||||||
@@ -380,7 +381,7 @@ static int nodeid_from_csid(const char *csid)
|
|||||||
return nodeid;
|
return nodeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _is_quorate(void)
|
static int _is_quorate()
|
||||||
{
|
{
|
||||||
return cman_is_quorate(c_handle);
|
return cman_is_quorate(c_handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -78,6 +78,9 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
|||||||
unsigned char lock_cmd;
|
unsigned char lock_cmd;
|
||||||
unsigned char lock_flags;
|
unsigned char lock_flags;
|
||||||
|
|
||||||
|
/* Reset test mode before we start */
|
||||||
|
init_test(0);
|
||||||
|
|
||||||
/* Do the command */
|
/* Do the command */
|
||||||
switch (msg->cmd) {
|
switch (msg->cmd) {
|
||||||
/* Just a test message */
|
/* Just a test message */
|
||||||
@@ -109,6 +112,8 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
|||||||
lockname = &args[2];
|
lockname = &args[2];
|
||||||
/* Check to see if the VG is in use by LVM1 */
|
/* Check to see if the VG is in use by LVM1 */
|
||||||
status = do_check_lvm1(lockname);
|
status = do_check_lvm1(lockname);
|
||||||
|
if (lock_flags & LCK_TEST_MODE)
|
||||||
|
init_test(1);
|
||||||
do_lock_vg(lock_cmd, lock_flags, lockname);
|
do_lock_vg(lock_cmd, lock_flags, lockname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -117,6 +122,8 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
|||||||
lock_cmd = args[0];
|
lock_cmd = args[0];
|
||||||
lock_flags = args[1];
|
lock_flags = args[1];
|
||||||
lockname = &args[2];
|
lockname = &args[2];
|
||||||
|
if (lock_flags & LCK_TEST_MODE)
|
||||||
|
init_test(1);
|
||||||
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
/* Replace EIO with something less scary */
|
/* Replace EIO with something less scary */
|
||||||
if (status == EIO) {
|
if (status == EIO) {
|
||||||
@@ -176,58 +183,65 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lock_vg(struct local_client *client)
|
static int lock_vg(struct local_client *client)
|
||||||
{
|
{
|
||||||
struct dm_hash_table *lock_hash;
|
struct dm_hash_table *lock_hash;
|
||||||
struct clvm_header *header =
|
struct clvm_header *header =
|
||||||
(struct clvm_header *) client->bits.localsock.cmd;
|
(struct clvm_header *) client->bits.localsock.cmd;
|
||||||
unsigned char lock_cmd;
|
unsigned char lock_cmd;
|
||||||
int lock_mode;
|
int lock_mode;
|
||||||
char *args = header->node + strlen(header->node) + 1;
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
int lkid;
|
int lkid;
|
||||||
int status;
|
int status = 0;
|
||||||
char *lockname;
|
char *lockname;
|
||||||
|
|
||||||
/*
|
/* Keep a track of VG locks in our own hash table. In current
|
||||||
* Keep a track of VG locks in our own hash table. In current
|
practice there should only ever be more than two VGs locked
|
||||||
* practice there should only ever be more than two VGs locked
|
if a user tries to merge lots of them at once */
|
||||||
* if a user tries to merge lots of them at once
|
if (client->bits.localsock.private) {
|
||||||
*/
|
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
|
||||||
if (!client->bits.localsock.private) {
|
}
|
||||||
if (!(lock_hash = dm_hash_create(3)))
|
else {
|
||||||
return ENOMEM;
|
lock_hash = dm_hash_create(3);
|
||||||
client->bits.localsock.private = (void *) lock_hash;
|
if (!lock_hash)
|
||||||
} else
|
return ENOMEM;
|
||||||
lock_hash = (struct dm_hash_table *) client->bits.localsock.private;
|
client->bits.localsock.private = (void *)lock_hash;
|
||||||
|
}
|
||||||
|
|
||||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||||
lock_mode = ((int) lock_cmd & LCK_TYPE_MASK);
|
lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
|
||||||
/* lock_flags = args[1]; */
|
/* lock_flags = args[1]; */
|
||||||
lockname = &args[2];
|
lockname = &args[2];
|
||||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||||
|
|
||||||
if (lock_mode == LCK_UNLOCK) {
|
if (lock_mode == LCK_UNLOCK) {
|
||||||
if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname)))
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
if ((status = sync_unlock(lockname, lkid)))
|
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
|
||||||
status = errno;
|
if (lkid == 0)
|
||||||
else
|
return EINVAL;
|
||||||
dm_hash_remove(lock_hash, lockname);
|
|
||||||
} else {
|
|
||||||
/* Read locks need to be PR; other modes get passed through */
|
|
||||||
if (lock_mode == LCK_READ)
|
|
||||||
lock_mode = LCK_PREAD;
|
|
||||||
|
|
||||||
if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid)))
|
status = sync_unlock(lockname, lkid);
|
||||||
status = errno;
|
if (status)
|
||||||
else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid))
|
status = errno;
|
||||||
return ENOMEM;
|
else
|
||||||
}
|
dm_hash_remove(lock_hash, lockname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Read locks need to be PR; other modes get passed through */
|
||||||
|
if (lock_mode == LCK_READ)
|
||||||
|
lock_mode = LCK_PREAD;
|
||||||
|
status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid);
|
||||||
|
if (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
if (!dm_hash_insert(lock_hash, lockname, (void *)(long)lkid))
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -245,6 +259,7 @@ int do_pre_command(struct local_client *client)
|
|||||||
int status = 0;
|
int status = 0;
|
||||||
char *lockname;
|
char *lockname;
|
||||||
|
|
||||||
|
init_test(0);
|
||||||
switch (header->cmd) {
|
switch (header->cmd) {
|
||||||
case CLVMD_CMD_TEST:
|
case CLVMD_CMD_TEST:
|
||||||
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
|
status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
|
||||||
@@ -263,6 +278,8 @@ int do_pre_command(struct local_client *client)
|
|||||||
lock_cmd = args[0];
|
lock_cmd = args[0];
|
||||||
lock_flags = args[1];
|
lock_flags = args[1];
|
||||||
lockname = &args[2];
|
lockname = &args[2];
|
||||||
|
if (lock_flags & LCK_TEST_MODE)
|
||||||
|
init_test(1);
|
||||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -294,16 +311,20 @@ int do_post_command(struct local_client *client)
|
|||||||
char *args = header->node + strlen(header->node) + 1;
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
char *lockname;
|
char *lockname;
|
||||||
|
|
||||||
|
init_test(0);
|
||||||
switch (header->cmd) {
|
switch (header->cmd) {
|
||||||
case CLVMD_CMD_TEST:
|
case CLVMD_CMD_TEST:
|
||||||
status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
status =
|
||||||
client->bits.localsock.private = NULL;
|
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||||
|
client->bits.localsock.private = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_LV:
|
case CLVMD_CMD_LOCK_LV:
|
||||||
lock_cmd = args[0];
|
lock_cmd = args[0];
|
||||||
lock_flags = args[1];
|
lock_flags = args[1];
|
||||||
lockname = &args[2];
|
lockname = &args[2];
|
||||||
|
if (lock_flags & LCK_TEST_MODE)
|
||||||
|
init_test(1);
|
||||||
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -323,7 +344,6 @@ void cmd_client_cleanup(struct local_client *client)
|
|||||||
int lkid;
|
int lkid;
|
||||||
char *lockname;
|
char *lockname;
|
||||||
|
|
||||||
DEBUGLOG("Client thread cleanup (%p)\n", client);
|
|
||||||
if (!client->bits.localsock.private)
|
if (!client->bits.localsock.private)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -332,14 +352,15 @@ void cmd_client_cleanup(struct local_client *client)
|
|||||||
dm_hash_iterate(v, lock_hash) {
|
dm_hash_iterate(v, lock_hash) {
|
||||||
lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
||||||
lockname = dm_hash_get_key(lock_hash, v);
|
lockname = dm_hash_get_key(lock_hash, v);
|
||||||
DEBUGLOG("Cleanup (%p): Unlocking lock %s %x\n", client, lockname, lkid);
|
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
|
||||||
(void) sync_unlock(lockname, lkid);
|
(void) sync_unlock(lockname, lkid);
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_hash_destroy(lock_hash);
|
dm_hash_destroy(lock_hash);
|
||||||
client->bits.localsock.private = NULL;
|
client->bits.localsock.private = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int restart_clvmd(void)
|
static int restart_clvmd(void)
|
||||||
{
|
{
|
||||||
const char **argv;
|
const char **argv;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -18,10 +18,16 @@
|
|||||||
#ifndef _LVM_CLVMD_COMMON_H
|
#ifndef _LVM_CLVMD_COMMON_H
|
||||||
#define _LVM_CLVMD_COMMON_H
|
#define _LVM_CLVMD_COMMON_H
|
||||||
|
|
||||||
#define _REENTRANT
|
#include "configure.h"
|
||||||
|
|
||||||
#include "tool.h"
|
#define _GNU_SOURCE
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
#include "lvm-logging.h"
|
#include "lvm-logging.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -89,7 +89,7 @@ quorum_callbacks_t quorum_callbacks = {
|
|||||||
|
|
||||||
struct node_info
|
struct node_info
|
||||||
{
|
{
|
||||||
enum {NODE_DOWN, NODE_CLVMD} state;
|
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||||
int nodeid;
|
int nodeid;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -255,6 +255,26 @@ static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
|||||||
ninfo->state = NODE_DOWN;
|
ninfo->state = NODE_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<member_list_entries; i++) {
|
||||||
|
if (member_list[i].nodeid == 0) continue;
|
||||||
|
ninfo = dm_hash_lookup_binary(node_hash,
|
||||||
|
(char *)&member_list[i].nodeid,
|
||||||
|
COROSYNC_CSID_LEN);
|
||||||
|
if (!ninfo) {
|
||||||
|
ninfo = malloc(sizeof(struct node_info));
|
||||||
|
if (!ninfo) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ninfo->nodeid = member_list[i].nodeid;
|
||||||
|
dm_hash_insert_binary(node_hash,
|
||||||
|
(char *)&ninfo->nodeid,
|
||||||
|
COROSYNC_CSID_LEN, ninfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ninfo->state = NODE_CLVMD;
|
||||||
|
}
|
||||||
|
|
||||||
num_nodes = member_list_entries;
|
num_nodes = member_list_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,6 +365,9 @@ static int _init_cluster(void)
|
|||||||
|
|
||||||
static void _cluster_closedown(void)
|
static void _cluster_closedown(void)
|
||||||
{
|
{
|
||||||
|
DEBUGLOG("cluster_closedown\n");
|
||||||
|
destroy_lvhash();
|
||||||
|
|
||||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||||
cpg_finalize(cpg_handle);
|
cpg_finalize(cpg_handle);
|
||||||
quorum_finalize(quorum_handle);
|
quorum_finalize(quorum_handle);
|
||||||
@@ -385,7 +408,7 @@ static int _name_from_csid(const char *csid, char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _get_num_nodes(void)
|
static int _get_num_nodes()
|
||||||
{
|
{
|
||||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||||
return num_nodes;
|
return num_nodes;
|
||||||
@@ -417,6 +440,7 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
|||||||
{
|
{
|
||||||
struct dm_hash_node *hn;
|
struct dm_hash_node *hn;
|
||||||
struct node_info *ninfo;
|
struct node_info *ninfo;
|
||||||
|
int somedown = 0;
|
||||||
|
|
||||||
dm_hash_iterate(hn, node_hash)
|
dm_hash_iterate(hn, node_hash)
|
||||||
{
|
{
|
||||||
@@ -428,10 +452,12 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
|||||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||||
ninfo->state);
|
ninfo->state);
|
||||||
|
|
||||||
if (ninfo->state == NODE_CLVMD)
|
if (ninfo->state != NODE_DOWN)
|
||||||
callback(master_client, csid, 1);
|
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||||
|
if (ninfo->state != NODE_CLVMD)
|
||||||
|
somedown = -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return somedown;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Real locking */
|
/* Real locking */
|
||||||
@@ -502,7 +528,7 @@ static int _unlock_resource(const char *resource, int lockid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _is_quorate(void)
|
static int _is_quorate()
|
||||||
{
|
{
|
||||||
int quorate;
|
int quorate;
|
||||||
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -197,7 +197,9 @@ static int add_internal_client(int fd, fd_callback_t callback)
|
|||||||
|
|
||||||
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
|
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
|
||||||
|
|
||||||
if (!(client = dm_zalloc(sizeof(*client)))) {
|
client = calloc(1, sizeof(struct local_client));
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
DEBUGLOG("malloc failed\n");
|
DEBUGLOG("malloc failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -243,7 +245,7 @@ static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
|||||||
struct node_info *ninfo;
|
struct node_info *ninfo;
|
||||||
|
|
||||||
DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
|
DEBUGLOG("confchg callback. %" PRIsize_t " joined, "
|
||||||
FMTsize_t " left, %" PRIsize_t " members\n",
|
"%" PRIsize_t " left, %" PRIsize_t " members\n",
|
||||||
joined_list_entries, left_list_entries, member_list_entries);
|
joined_list_entries, left_list_entries, member_list_entries);
|
||||||
|
|
||||||
for (i=0; i<joined_list_entries; i++) {
|
for (i=0; i<joined_list_entries; i++) {
|
||||||
@@ -365,6 +367,9 @@ static int _init_cluster(void)
|
|||||||
|
|
||||||
static void _cluster_closedown(void)
|
static void _cluster_closedown(void)
|
||||||
{
|
{
|
||||||
|
DEBUGLOG("cluster_closedown\n");
|
||||||
|
destroy_lvhash();
|
||||||
|
|
||||||
saLckFinalize(lck_handle);
|
saLckFinalize(lck_handle);
|
||||||
cpg_finalize(cpg_handle);
|
cpg_finalize(cpg_handle);
|
||||||
}
|
}
|
||||||
@@ -684,6 +689,6 @@ struct cluster_ops *init_openais_cluster(void)
|
|||||||
{
|
{
|
||||||
if (!_init_cluster())
|
if (!_init_cluster())
|
||||||
return &_cluster_openais_ops;
|
return &_cluster_openais_ops;
|
||||||
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2013 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
#include "clvmd-common.h"
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "clvm.h"
|
#include "clvm.h"
|
||||||
#include "clvmd-comms.h"
|
#include "clvmd-comms.h"
|
||||||
|
#include "lvm-functions.h"
|
||||||
#include "clvmd.h"
|
#include "clvmd.h"
|
||||||
|
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@@ -31,14 +32,10 @@ static int listen_fd = -1;
|
|||||||
static struct dm_hash_table *_locks;
|
static struct dm_hash_table *_locks;
|
||||||
static int _lockid;
|
static int _lockid;
|
||||||
|
|
||||||
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
/* Using one common condition for all locks for simplicity */
|
|
||||||
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
|
|
||||||
struct lock {
|
struct lock {
|
||||||
struct dm_list list;
|
|
||||||
int lockid;
|
int lockid;
|
||||||
int mode;
|
int mode;
|
||||||
|
int excl;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void close_comms(void)
|
static void close_comms(void)
|
||||||
@@ -108,7 +105,6 @@ static int _init_cluster(void)
|
|||||||
r = init_comms();
|
r = init_comms();
|
||||||
if (r) {
|
if (r) {
|
||||||
dm_hash_destroy(_locks);
|
dm_hash_destroy(_locks);
|
||||||
_locks = NULL;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,13 +116,11 @@ static void _cluster_closedown(void)
|
|||||||
{
|
{
|
||||||
close_comms();
|
close_comms();
|
||||||
|
|
||||||
/* If there is any awaited resource, kill it softly */
|
DEBUGLOG("cluster_closedown\n");
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
destroy_lvhash();
|
||||||
dm_hash_destroy(_locks);
|
dm_hash_destroy(_locks);
|
||||||
_locks = NULL;
|
_locks = NULL;
|
||||||
_lockid = 0;
|
_lockid = 0;
|
||||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _get_our_csid(char *csid)
|
static void _get_our_csid(char *csid)
|
||||||
@@ -166,115 +160,64 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
|||||||
|
|
||||||
int _lock_file(const char *file, uint32_t flags);
|
int _lock_file(const char *file, uint32_t flags);
|
||||||
|
|
||||||
static const char *_get_mode(int mode)
|
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
{
|
/* Using one common condition for all locks for simplicity */
|
||||||
switch (mode) {
|
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
|
||||||
case LCK_NULL: return "NULL";
|
|
||||||
case LCK_READ: return "READ";
|
|
||||||
case LCK_PREAD: return "PREAD";
|
|
||||||
case LCK_WRITE: return "WRITE";
|
|
||||||
case LCK_EXCL: return "EXCLUSIVE";
|
|
||||||
case LCK_UNLOCK: return "UNLOCK";
|
|
||||||
default: return "????";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Real locking */
|
/* Real locking */
|
||||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||||
{
|
{
|
||||||
/* DLM table of allowed transition states */
|
struct lock *lck;
|
||||||
static const int _dlm_table[6][6] = {
|
|
||||||
/* Mode NL CR CW PR PW EX */
|
|
||||||
/* NL */ { 1, 1, 1, 1, 1, 1},
|
|
||||||
/* CR */ { 1, 1, 1, 1, 1, 0},
|
|
||||||
/* CW */ { 1, 1, 1, 0, 0, 0},
|
|
||||||
/* PR */ { 1, 1, 0, 1, 0, 0},
|
|
||||||
/* PW */ { 1, 1, 0, 0, 0, 0},
|
|
||||||
/* EX */ { 1, 0, 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lock *lck = NULL, *lckt;
|
DEBUGLOG("Locking resource %s, flags=%d, mode=%d\n",
|
||||||
struct dm_list *head;
|
resource, flags, mode);
|
||||||
|
|
||||||
DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n",
|
|
||||||
resource, flags,
|
|
||||||
(flags & LCKF_NOQUEUE) ? "NOQUEUE" : "",
|
|
||||||
((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) ==
|
|
||||||
(LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "",
|
|
||||||
(flags & LCKF_CONVERT) ? "CONVERT" : "",
|
|
||||||
_get_mode(mode), mode);
|
|
||||||
|
|
||||||
mode &= LCK_TYPE_MASK;
|
mode &= LCK_TYPE_MASK;
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
pthread_mutex_lock(&_lock_mutex);
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (!(head = dm_hash_lookup(_locks, resource))) {
|
if (!(lck = dm_hash_lookup(_locks, resource))) {
|
||||||
if (flags & LCKF_CONVERT) {
|
|
||||||
/* In real DLM, lock is identified only by lockid, resource is not used */
|
|
||||||
DEBUGLOG("Unlocked resource %s cannot be converted\n", resource);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
/* Add new locked resource */
|
/* Add new locked resource */
|
||||||
if (!(head = dm_malloc(sizeof(struct dm_list))) ||
|
if (!(lck = dm_zalloc(sizeof(struct lock))) ||
|
||||||
!dm_hash_insert(_locks, resource, head)) {
|
!dm_hash_insert(_locks, resource, lck))
|
||||||
dm_free(head);
|
goto bad;
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_list_init(head);
|
lck->lockid = ++_lockid;
|
||||||
} else /* Update/convert locked resource */
|
goto out;
|
||||||
dm_list_iterate_items(lck, head) {
|
|
||||||
/* Check is all locks are compatible with requested lock */
|
|
||||||
if (flags & LCKF_CONVERT) {
|
|
||||||
if (lck->lockid != *lockid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode));
|
|
||||||
dm_list_iterate_items(lckt, head) {
|
|
||||||
if ((lckt->lockid != *lockid) &&
|
|
||||||
!_dlm_table[mode][lckt->mode]) {
|
|
||||||
if (!(flags & LCKF_NOQUEUE) &&
|
|
||||||
/* TODO: Real dlm uses here conversion queues */
|
|
||||||
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
|
|
||||||
_locks) /* End of the game? */
|
|
||||||
goto retry;
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lck->mode = mode; /* Lock is now converted */
|
|
||||||
goto out;
|
|
||||||
} else if (!_dlm_table[mode][lck->mode]) {
|
|
||||||
DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode));
|
|
||||||
if (!(flags & LCKF_NOQUEUE) &&
|
|
||||||
!pthread_cond_wait(&_lock_cond, &_lock_mutex) &&
|
|
||||||
_locks) { /* End of the game? */
|
|
||||||
DEBUGLOG("Resource %s retrying lock in mode:%s...\n",
|
|
||||||
resource, _get_mode(mode));
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & LCKF_CONVERT)) {
|
|
||||||
if (!(lck = dm_malloc(sizeof(struct lock))))
|
|
||||||
goto_bad;
|
|
||||||
|
|
||||||
*lockid = lck->lockid = ++_lockid;
|
|
||||||
lck->mode = mode;
|
|
||||||
dm_list_add(head, &lck->list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update/convert lock */
|
||||||
|
if (flags == LCKF_CONVERT) {
|
||||||
|
if (lck->excl)
|
||||||
|
mode = LCK_EXCL;
|
||||||
|
} else if ((lck->mode == LCK_WRITE) || (lck->mode == LCK_EXCL)) {
|
||||||
|
DEBUGLOG("Resource %s already %s locked (%d)...\n", resource,
|
||||||
|
(lck->mode == LCK_WRITE) ? "write" : "exclusively", lck->lockid);
|
||||||
|
goto maybe_retry;
|
||||||
|
} else if (lck->mode > mode) {
|
||||||
|
DEBUGLOG("Resource %s already locked and %s lock requested...\n",
|
||||||
|
resource,
|
||||||
|
(mode == LCK_READ) ? "READ" :
|
||||||
|
(mode == LCK_WRITE) ? "WRITE" : "EXCLUSIVE");
|
||||||
|
goto maybe_retry;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
|
*lockid = lck->lockid;
|
||||||
|
lck->mode = mode;
|
||||||
|
lck->excl |= (mode == LCK_EXCL);
|
||||||
|
DEBUGLOG("Locked resource %s, lockid=%d, mode=%d\n", resource, lck->lockid, mode);
|
||||||
|
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
pthread_mutex_unlock(&_lock_mutex);
|
||||||
DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n",
|
|
||||||
resource, lck->lockid, _get_mode(lck->mode));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
maybe_retry:
|
||||||
|
if (!(flags & LCK_NONBLOCK)) {
|
||||||
|
pthread_cond_wait(&_lock_cond, &_lock_mutex);
|
||||||
|
DEBUGLOG("Resource %s RETRYING lock...\n", resource);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
bad:
|
bad:
|
||||||
pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */
|
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
pthread_mutex_unlock(&_lock_mutex);
|
||||||
DEBUGLOG("Failed to lock resource %s\n", resource);
|
DEBUGLOG("Failed to lock resource %s\n", resource);
|
||||||
|
|
||||||
@@ -284,44 +227,35 @@ bad:
|
|||||||
static int _unlock_resource(const char *resource, int lockid)
|
static int _unlock_resource(const char *resource, int lockid)
|
||||||
{
|
{
|
||||||
struct lock *lck;
|
struct lock *lck;
|
||||||
struct dm_list *head;
|
|
||||||
int r = 1;
|
|
||||||
|
|
||||||
if (lockid < 0) {
|
if (lockid < 0) {
|
||||||
DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
|
DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
|
||||||
resource, lockid);
|
resource, lockid);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
|
DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
|
||||||
pthread_mutex_lock(&_lock_mutex);
|
pthread_mutex_lock(&_lock_mutex);
|
||||||
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
|
||||||
|
|
||||||
if (!(head = dm_hash_lookup(_locks, resource))) {
|
if (!(lck = dm_hash_lookup(_locks, resource))) {
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
pthread_mutex_unlock(&_lock_mutex);
|
||||||
DEBUGLOG("Resource %s is not locked.\n", resource);
|
DEBUGLOG("Resource %s, lockid=%d is not locked.\n", resource, lockid);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_list_iterate_items(lck, head)
|
if (lck->lockid != lockid) {
|
||||||
if (lck->lockid == lockid) {
|
pthread_mutex_unlock(&_lock_mutex);
|
||||||
dm_list_del(&lck->list);
|
DEBUGLOG("Resource %s has wrong lockid %d, expected %d.\n",
|
||||||
dm_free(lck);
|
resource, lck->lockid, lockid);
|
||||||
r = 0;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid);
|
|
||||||
out:
|
|
||||||
if (dm_list_empty(head)) {
|
|
||||||
//DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid);
|
|
||||||
dm_hash_remove(_locks, resource);
|
|
||||||
dm_free(head);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dm_hash_remove(_locks, resource);
|
||||||
|
pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
|
||||||
pthread_mutex_unlock(&_lock_mutex);
|
pthread_mutex_unlock(&_lock_mutex);
|
||||||
|
dm_free(lck);
|
||||||
|
|
||||||
return r;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _is_quorate(void)
|
static int _is_quorate(void)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CLVMD_H
|
#ifndef _CLVMD_H
|
||||||
@@ -53,12 +53,13 @@ struct localsock_bits {
|
|||||||
int finished; /* Flag to tell subthread to exit */
|
int finished; /* Flag to tell subthread to exit */
|
||||||
int all_success; /* Set to 0 if any node (or the pre_command)
|
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||||
failed */
|
failed */
|
||||||
int cleanup_needed; /* helper for cleanup_zombie */
|
|
||||||
struct local_client *pipe_client;
|
struct local_client *pipe_client;
|
||||||
pthread_t threadid;
|
pthread_t threadid;
|
||||||
enum { PRE_COMMAND, POST_COMMAND } state;
|
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
||||||
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
|
|
||||||
|
pthread_mutex_t reply_mutex; /* Protect reply structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Entries for PIPE clients */
|
/* Entries for PIPE clients */
|
||||||
|
|||||||
@@ -10,13 +10,14 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "clvmd-common.h"
|
#include "clvmd-common.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "lvm-types.h"
|
||||||
#include "clvm.h"
|
#include "clvm.h"
|
||||||
#include "clvmd-comms.h"
|
#include "clvmd-comms.h"
|
||||||
#include "clvmd.h"
|
#include "clvmd.h"
|
||||||
@@ -130,15 +131,14 @@ static const char *decode_flags(unsigned char flags)
|
|||||||
static char buf[128];
|
static char buf[128];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s%s)", flags,
|
len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s)", flags,
|
||||||
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
|
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "",
|
||||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
|
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "",
|
||||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
|
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "",
|
||||||
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
|
flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "",
|
||||||
flags & LCK_TEST_MODE ? "TEST|" : "",
|
flags & LCK_TEST_MODE ? "TEST|" : "",
|
||||||
flags & LCK_CONVERT_MODE ? "CONVERT|" : "",
|
flags & LCK_CONVERT ? "CONVERT|" : "",
|
||||||
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "",
|
flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "");
|
||||||
flags & LCK_REVERT_MODE ? "REVERT|" : "");
|
|
||||||
|
|
||||||
if (len > 1)
|
if (len > 1)
|
||||||
buf[len - 2] = ' ';
|
buf[len - 2] = ' ';
|
||||||
@@ -180,19 +180,8 @@ static int insert_info(const char *resource, struct lv_info *lvi)
|
|||||||
|
|
||||||
static void remove_info(const char *resource)
|
static void remove_info(const char *resource)
|
||||||
{
|
{
|
||||||
int num_open;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&lv_hash_lock);
|
pthread_mutex_lock(&lv_hash_lock);
|
||||||
dm_hash_remove(lv_hash, resource);
|
dm_hash_remove(lv_hash, resource);
|
||||||
|
|
||||||
/* When last lock is remove, validate there are not left opened devices */
|
|
||||||
if (!dm_hash_get_first(lv_hash)) {
|
|
||||||
if (critical_section())
|
|
||||||
log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section.");
|
|
||||||
if ((num_open = dev_cache_check_for_open_devices()))
|
|
||||||
log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&lv_hash_lock);
|
pthread_mutex_unlock(&lv_hash_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +224,7 @@ void destroy_lvhash(void)
|
|||||||
if ((status = sync_unlock(resource, lvi->lock_id)))
|
if ((status = sync_unlock(resource, lvi->lock_id)))
|
||||||
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
|
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
|
||||||
status, strerror(errno));
|
status, strerror(errno));
|
||||||
dm_free(lvi);
|
free(lvi);
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_hash_destroy(lv_hash);
|
dm_hash_destroy(lv_hash);
|
||||||
@@ -251,6 +240,9 @@ static int hold_lock(char *resource, int mode, int flags)
|
|||||||
int saved_errno;
|
int saved_errno;
|
||||||
struct lv_info *lvi;
|
struct lv_info *lvi;
|
||||||
|
|
||||||
|
if (test_mode())
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Mask off invalid options */
|
/* Mask off invalid options */
|
||||||
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
|
flags &= LCKF_NOQUEUE | LCKF_CONVERT;
|
||||||
|
|
||||||
@@ -264,7 +256,7 @@ static int hold_lock(char *resource, int mode, int flags)
|
|||||||
}
|
}
|
||||||
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
|
if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) {
|
||||||
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
|
DEBUGLOG("hold_lock, lock already held LCK_EXCL, "
|
||||||
"ignoring LCK_WRITE request\n");
|
"ignoring LCK_WRITE request");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,26 +268,29 @@ static int hold_lock(char *resource, int mode, int flags)
|
|||||||
}
|
}
|
||||||
if (lvi) {
|
if (lvi) {
|
||||||
/* Already exists - convert it */
|
/* Already exists - convert it */
|
||||||
status = sync_lock(resource, mode, flags, &lvi->lock_id);
|
status =
|
||||||
|
sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
if (!status)
|
if (!status)
|
||||||
lvi->lock_mode = mode;
|
lvi->lock_mode = mode;
|
||||||
else
|
|
||||||
|
if (status) {
|
||||||
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
}
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
} else {
|
} else {
|
||||||
if (!(lvi = dm_malloc(sizeof(struct lv_info)))) {
|
lvi = malloc(sizeof(struct lv_info));
|
||||||
|
if (!lvi) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lvi->lock_mode = mode;
|
lvi->lock_mode = mode;
|
||||||
lvi->lock_id = 0;
|
|
||||||
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
|
status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
if (status) {
|
if (status) {
|
||||||
dm_free(lvi);
|
free(lvi);
|
||||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
} else
|
} else
|
||||||
@@ -316,6 +311,9 @@ static int hold_unlock(char *resource)
|
|||||||
int status;
|
int status;
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
|
|
||||||
|
if (test_mode())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(lvi = lookup_info(resource))) {
|
if (!(lvi = lookup_info(resource))) {
|
||||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -325,7 +323,7 @@ static int hold_unlock(char *resource)
|
|||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
if (!status) {
|
if (!status) {
|
||||||
remove_info(resource);
|
remove_info(resource);
|
||||||
dm_free(lvi);
|
free(lvi);
|
||||||
} else {
|
} else {
|
||||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
@@ -358,7 +356,7 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Does the config file want us to activate this LV ? */
|
/* Does the config file want us to activate this LV ? */
|
||||||
if (!lv_activation_filter(cmd, resource, &activate_lv, NULL))
|
if (!lv_activation_filter(cmd, resource, &activate_lv))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
if (!activate_lv)
|
if (!activate_lv)
|
||||||
@@ -375,8 +373,8 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
|
|||||||
* Use lock conversion only if requested, to prevent implicit conversion
|
* Use lock conversion only if requested, to prevent implicit conversion
|
||||||
* of exclusive lock to shared one during activation.
|
* of exclusive lock to shared one during activation.
|
||||||
*/
|
*/
|
||||||
if (!test_mode() && command & LCK_CLUSTER_VG) {
|
if (command & LCK_CLUSTER_VG) {
|
||||||
status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? LCKF_CONVERT:0));
|
status = hold_lock(resource, mode, LCKF_NOQUEUE | (lock_flags & LCK_CONVERT ? LCKF_CONVERT:0));
|
||||||
if (status) {
|
if (status) {
|
||||||
/* Return an LVM-sensible error for this.
|
/* Return an LVM-sensible error for this.
|
||||||
* Forcing EIO makes the upper level return this text
|
* Forcing EIO makes the upper level return this text
|
||||||
@@ -396,20 +394,20 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
|
|||||||
|
|
||||||
if (lvi.suspended) {
|
if (lvi.suspended) {
|
||||||
critical_section_inc(cmd, "resuming");
|
critical_section_inc(cmd, "resuming");
|
||||||
if (!lv_resume(cmd, resource, 0, NULL)) {
|
if (!lv_resume(cmd, resource, 0)) {
|
||||||
critical_section_dec(cmd, "resumed");
|
critical_section_dec(cmd, "resumed");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now activate it */
|
/* Now activate it */
|
||||||
if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
|
if (!lv_activate(cmd, resource, exclusive))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!test_mode() && (oldmode == -1 || oldmode != mode))
|
if (oldmode == -1 || oldmode != mode)
|
||||||
(void)hold_unlock(resource);
|
(void)hold_unlock(resource);
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
@@ -429,7 +427,7 @@ static int do_resume_lv(char *resource, unsigned char command, unsigned char loc
|
|||||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||||
revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
|
revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0;
|
||||||
|
|
||||||
if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert, NULL))
|
if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -452,7 +450,7 @@ static int do_suspend_lv(char *resource, unsigned char command, unsigned char lo
|
|||||||
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
exclusive = (oldmode == LCK_EXCL) ? 1 : 0;
|
||||||
|
|
||||||
/* Always call lv_suspend to read commited and precommited data */
|
/* Always call lv_suspend to read commited and precommited data */
|
||||||
if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive, NULL, NULL))
|
if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -470,10 +468,10 @@ static int do_deactivate_lv(char *resource, unsigned char command, unsigned char
|
|||||||
return 0; /* We don't need to do anything */
|
return 0; /* We don't need to do anything */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_deactivate(cmd, resource, NULL))
|
if (!lv_deactivate(cmd, resource))
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
if (!test_mode() && command & LCK_CLUSTER_VG) {
|
if (command & LCK_CLUSTER_VG) {
|
||||||
status = hold_unlock(resource);
|
status = hold_unlock(resource);
|
||||||
if (status)
|
if (status)
|
||||||
return errno;
|
return errno;
|
||||||
@@ -485,19 +483,18 @@ static int do_deactivate_lv(char *resource, unsigned char command, unsigned char
|
|||||||
const char *do_lock_query(char *resource)
|
const char *do_lock_query(char *resource)
|
||||||
{
|
{
|
||||||
int mode;
|
int mode;
|
||||||
const char *type;
|
const char *type = NULL;
|
||||||
|
|
||||||
mode = get_current_lock(resource);
|
mode = get_current_lock(resource);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case LCK_NULL: type = "NL"; break;
|
case LCK_NULL: type = "NL"; break;
|
||||||
case LCK_READ: type = "CR"; break;
|
case LCK_READ: type = "CR"; break;
|
||||||
case LCK_PREAD:type = "PR"; break;
|
case LCK_PREAD:type = "PR"; break;
|
||||||
case LCK_WRITE:type = "PW"; break;
|
case LCK_WRITE:type = "PW"; break;
|
||||||
case LCK_EXCL: type = "EX"; break;
|
case LCK_EXCL: type = "EX"; break;
|
||||||
default: type = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "--");
|
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "?");
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -511,7 +508,7 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
|
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n",
|
||||||
resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
|
resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section());
|
||||||
|
|
||||||
if (!cmd->initialized.config || config_files_changed(cmd)) {
|
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||||
/* Reinitialise various settings inc. logging, filters */
|
/* Reinitialise various settings inc. logging, filters */
|
||||||
if (do_refresh_cache()) {
|
if (do_refresh_cache()) {
|
||||||
log_error("Updated config file invalid. Aborting.");
|
log_error("Updated config file invalid. Aborting.");
|
||||||
@@ -520,8 +517,6 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&lvm_lock);
|
pthread_mutex_lock(&lvm_lock);
|
||||||
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
|
|
||||||
|
|
||||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||||
init_mirror_in_sync(1);
|
init_mirror_in_sync(1);
|
||||||
|
|
||||||
@@ -574,7 +569,6 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
|
|
||||||
/* clean the pool for another command */
|
/* clean the pool for another command */
|
||||||
dm_pool_empty(cmd->mem);
|
dm_pool_empty(cmd->mem);
|
||||||
init_test(0);
|
|
||||||
pthread_mutex_unlock(&lvm_lock);
|
pthread_mutex_unlock(&lvm_lock);
|
||||||
|
|
||||||
DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
|
DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section());
|
||||||
@@ -594,8 +588,7 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||||
|
|
||||||
if (!(lock_flags & LCK_TEST_MODE) &&
|
if (hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
|
||||||
hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT))
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -613,8 +606,9 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
|||||||
(command & LCK_CLUSTER_VG)) {
|
(command & LCK_CLUSTER_VG)) {
|
||||||
int oldmode;
|
int oldmode;
|
||||||
|
|
||||||
DEBUGLOG("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
DEBUGLOG
|
||||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||||
|
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||||
|
|
||||||
/* If the lock state is PW then restore it to what it was */
|
/* If the lock state is PW then restore it to what it was */
|
||||||
oldmode = get_current_lock(resource);
|
oldmode = get_current_lock(resource);
|
||||||
@@ -627,13 +621,11 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
|||||||
if (!status)
|
if (!status)
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
||||||
if (!(lock_flags & LCK_TEST_MODE)) {
|
if (lvi.exists) {
|
||||||
if (lvi.exists) {
|
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
|
||||||
if (hold_lock(resource, LCK_READ, LCKF_CONVERT))
|
|
||||||
return errno;
|
|
||||||
} else if (hold_unlock(resource))
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
} else if (hold_unlock(resource))
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -663,8 +655,7 @@ int do_refresh_cache(void)
|
|||||||
|
|
||||||
init_full_scan_done(0);
|
init_full_scan_done(0);
|
||||||
init_ignore_suspended_devices(1);
|
init_ignore_suspended_devices(1);
|
||||||
lvmcache_force_next_label_scan();
|
lvmcache_label_scan(cmd, 2);
|
||||||
lvmcache_label_scan(cmd);
|
|
||||||
dm_pool_empty(cmd->mem);
|
dm_pool_empty(cmd->mem);
|
||||||
|
|
||||||
pthread_mutex_unlock(&lvm_lock);
|
pthread_mutex_unlock(&lvm_lock);
|
||||||
@@ -698,8 +689,6 @@ void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&lvm_lock);
|
pthread_mutex_lock(&lvm_lock);
|
||||||
init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0);
|
|
||||||
|
|
||||||
switch (lock_cmd) {
|
switch (lock_cmd) {
|
||||||
case LCK_VG_COMMIT:
|
case LCK_VG_COMMIT:
|
||||||
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
|
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
|
||||||
@@ -714,8 +703,6 @@ void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
|
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
|
||||||
lvmcache_drop_metadata(vgname, 0);
|
lvmcache_drop_metadata(vgname, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_test(0);
|
|
||||||
pthread_mutex_unlock(&lvm_lock);
|
pthread_mutex_unlock(&lvm_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,7 +714,7 @@ void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
|||||||
static int get_initial_state(struct dm_hash_table *excl_uuid)
|
static int get_initial_state(struct dm_hash_table *excl_uuid)
|
||||||
{
|
{
|
||||||
int lock_mode;
|
int lock_mode;
|
||||||
char lv[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */
|
char lv[64], vg[64], flags[25], vg_flags[25];
|
||||||
char uuid[65];
|
char uuid[65];
|
||||||
char line[255];
|
char line[255];
|
||||||
char *lvs_cmd;
|
char *lvs_cmd;
|
||||||
@@ -816,7 +803,7 @@ static void check_config(void)
|
|||||||
{
|
{
|
||||||
int locking_type;
|
int locking_type;
|
||||||
|
|
||||||
locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL);
|
locking_type = find_config_tree_int(cmd, global_locking_type_CFG);
|
||||||
|
|
||||||
if (locking_type == 3) /* compiled-in cluster support */
|
if (locking_type == 3) /* compiled-in cluster support */
|
||||||
return;
|
return;
|
||||||
@@ -824,7 +811,7 @@ static void check_config(void)
|
|||||||
if (locking_type == 2) { /* External library, check name */
|
if (locking_type == 2) { /* External library, check name */
|
||||||
const char *libname;
|
const char *libname;
|
||||||
|
|
||||||
libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL);
|
libname = find_config_tree_str(cmd, global_locking_library_CFG);
|
||||||
if (libname && strstr(libname, "liblvm2clusterlock.so"))
|
if (libname && strstr(libname, "liblvm2clusterlock.so"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -844,7 +831,7 @@ void lvm_do_backup(const char *vgname)
|
|||||||
|
|
||||||
pthread_mutex_lock(&lvm_lock);
|
pthread_mutex_lock(&lvm_lock);
|
||||||
|
|
||||||
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, WARN_PV_READ, &consistent);
|
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 1, &consistent);
|
||||||
|
|
||||||
if (vg && consistent)
|
if (vg && consistent)
|
||||||
check_current_backup(vg);
|
check_current_backup(vg);
|
||||||
@@ -901,12 +888,8 @@ int init_clvm(struct dm_hash_table *excl_uuid)
|
|||||||
if (!get_initial_state(excl_uuid))
|
if (!get_initial_state(excl_uuid))
|
||||||
log_error("Cannot load initial lock states.");
|
log_error("Cannot load initial lock states.");
|
||||||
|
|
||||||
if (!udev_init_library_context())
|
if (!(cmd = create_toolcontext(1, NULL, 0, 1))) {
|
||||||
stack;
|
|
||||||
|
|
||||||
if (!(cmd = create_toolcontext(1, NULL, 0, 1, 1, 1))) {
|
|
||||||
log_error("Failed to allocate command context");
|
log_error("Failed to allocate command context");
|
||||||
udev_fin_library_context();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,7 +916,6 @@ void destroy_lvm(void)
|
|||||||
if (cmd) {
|
if (cmd) {
|
||||||
memlock_dec_daemon(cmd);
|
memlock_dec_daemon(cmd);
|
||||||
destroy_toolcontext(cmd);
|
destroy_toolcontext(cmd);
|
||||||
udev_fin_library_context();
|
|
||||||
cmd = NULL;
|
|
||||||
}
|
}
|
||||||
|
cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Functions in lvm-functions.c */
|
/* Functions in lvm-functions.c */
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* FIXME Remove duplicated functions from this file. */
|
/* FIXME Remove duplicated functions from this file. */
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
daemons/cmirrord/.gitignore
vendored
1
daemons/cmirrord/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
cmirrord
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
@@ -28,8 +28,7 @@ include $(top_builddir)/make.tmpl
|
|||||||
|
|
||||||
LIBS += -ldevmapper
|
LIBS += -ldevmapper
|
||||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
||||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS)
|
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS)
|
||||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS)
|
|
||||||
|
|
||||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "link_mon.h"
|
#include "link_mon.h"
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -33,49 +32,14 @@ static void daemonize(void);
|
|||||||
static void init_all(void);
|
static void init_all(void);
|
||||||
static void cleanup_all(void);
|
static void cleanup_all(void);
|
||||||
|
|
||||||
static void usage (FILE *dest)
|
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
|
||||||
{
|
{
|
||||||
fprintf (dest, "Usage: cmirrord [options]\n"
|
daemonize();
|
||||||
" -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();
|
init_all();
|
||||||
|
|
||||||
/* Parent can now exit, we're ready to handle requests */
|
/* Parent can now exit, we're ready to handle requests */
|
||||||
if (!foreground_mode)
|
kill(getppid(), SIGTERM);
|
||||||
kill(getppid(), SIGTERM);
|
|
||||||
|
|
||||||
LOG_PRINT("Starting cmirrord:");
|
LOG_PRINT("Starting cmirrord:");
|
||||||
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
||||||
@@ -238,23 +202,7 @@ static void daemonize(void)
|
|||||||
(dup2(devnull, 2) < 0)) /* reopen stderr */
|
(dup2(devnull, 2) < 0)) /* reopen stderr */
|
||||||
exit(EXIT_FAILURE);
|
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);
|
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);
|
(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
|
||||||
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
|
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
|
||||||
@@ -273,6 +221,16 @@ static void init_all(void)
|
|||||||
signal(SIGUSR2, &sig_handler);
|
signal(SIGUSR2, &sig_handler);
|
||||||
sigemptyset(&signal_mask);
|
sigemptyset(&signal_mask);
|
||||||
signal_received = 0;
|
signal_received = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_all
|
||||||
|
*
|
||||||
|
* Initialize modules. Exit on failure.
|
||||||
|
*/
|
||||||
|
static void init_all(void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
if ((r = init_local()) ||
|
if ((r = init_local()) ||
|
||||||
(r = init_cluster())) {
|
(r = init_cluster())) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "cluster.h"
|
#include "cluster.h"
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#if CMIRROR_HAS_CHECKPOINT
|
#if CMIRROR_HAS_CHECKPOINT
|
||||||
#include <openais/saAis.h>
|
#include <openais/saAis.h>
|
||||||
#include <openais/saCkpt.h>
|
#include <openais/saCkpt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Open AIS error codes */
|
/* Open AIS error codes */
|
||||||
#define str_ais_error(x) \
|
#define str_ais_error(x) \
|
||||||
@@ -56,40 +57,6 @@
|
|||||||
((x) == SA_AIS_ERR_TOO_BIG) ? "SA_AIS_ERR_TOO_BIG" : \
|
((x) == SA_AIS_ERR_TOO_BIG) ? "SA_AIS_ERR_TOO_BIG" : \
|
||||||
((x) == SA_AIS_ERR_NO_SECTIONS) ? "SA_AIS_ERR_NO_SECTIONS" : \
|
((x) == SA_AIS_ERR_NO_SECTIONS) ? "SA_AIS_ERR_NO_SECTIONS" : \
|
||||||
"ais_error_unknown"
|
"ais_error_unknown"
|
||||||
#else
|
|
||||||
#define str_ais_error(x) \
|
|
||||||
((x) == CS_OK) ? "CS_OK" : \
|
|
||||||
((x) == CS_ERR_LIBRARY) ? "CS_ERR_LIBRARY" : \
|
|
||||||
((x) == CS_ERR_VERSION) ? "CS_ERR_VERSION" : \
|
|
||||||
((x) == CS_ERR_INIT) ? "CS_ERR_INIT" : \
|
|
||||||
((x) == CS_ERR_TIMEOUT) ? "CS_ERR_TIMEOUT" : \
|
|
||||||
((x) == CS_ERR_TRY_AGAIN) ? "CS_ERR_TRY_AGAIN" : \
|
|
||||||
((x) == CS_ERR_INVALID_PARAM) ? "CS_ERR_INVALID_PARAM" : \
|
|
||||||
((x) == CS_ERR_NO_MEMORY) ? "CS_ERR_NO_MEMORY" : \
|
|
||||||
((x) == CS_ERR_BAD_HANDLE) ? "CS_ERR_BAD_HANDLE" : \
|
|
||||||
((x) == CS_ERR_BUSY) ? "CS_ERR_BUSY" : \
|
|
||||||
((x) == CS_ERR_ACCESS) ? "CS_ERR_ACCESS" : \
|
|
||||||
((x) == CS_ERR_NOT_EXIST) ? "CS_ERR_NOT_EXIST" : \
|
|
||||||
((x) == CS_ERR_NAME_TOO_LONG) ? "CS_ERR_NAME_TOO_LONG" : \
|
|
||||||
((x) == CS_ERR_EXIST) ? "CS_ERR_EXIST" : \
|
|
||||||
((x) == CS_ERR_NO_SPACE) ? "CS_ERR_NO_SPACE" : \
|
|
||||||
((x) == CS_ERR_INTERRUPT) ? "CS_ERR_INTERRUPT" : \
|
|
||||||
((x) == CS_ERR_NAME_NOT_FOUND) ? "CS_ERR_NAME_NOT_FOUND" : \
|
|
||||||
((x) == CS_ERR_NO_RESOURCES) ? "CS_ERR_NO_RESOURCES" : \
|
|
||||||
((x) == CS_ERR_NOT_SUPPORTED) ? "CS_ERR_NOT_SUPPORTED" : \
|
|
||||||
((x) == CS_ERR_BAD_OPERATION) ? "CS_ERR_BAD_OPERATION" : \
|
|
||||||
((x) == CS_ERR_FAILED_OPERATION) ? "CS_ERR_FAILED_OPERATION" : \
|
|
||||||
((x) == CS_ERR_MESSAGE_ERROR) ? "CS_ERR_MESSAGE_ERROR" : \
|
|
||||||
((x) == CS_ERR_QUEUE_FULL) ? "CS_ERR_QUEUE_FULL" : \
|
|
||||||
((x) == CS_ERR_QUEUE_NOT_AVAILABLE) ? "CS_ERR_QUEUE_NOT_AVAILABLE" : \
|
|
||||||
((x) == CS_ERR_BAD_FLAGS) ? "CS_ERR_BAD_FLAGS" : \
|
|
||||||
((x) == CS_ERR_TOO_BIG) ? "CS_ERR_TOO_BIG" : \
|
|
||||||
((x) == CS_ERR_NO_SECTIONS) ? "CS_ERR_NO_SECTIONS" : \
|
|
||||||
((x) == CS_ERR_CONTEXT_NOT_FOUND) ? "CS_ERR_CONTEXT_NOT_FOUND" : \
|
|
||||||
((x) == CS_ERR_TOO_MANY_GROUPS) ? "CS_ERR_TOO_MANY_GROUPS" : \
|
|
||||||
((x) == CS_ERR_SECURITY) ? "CS_ERR_SECURITY" : \
|
|
||||||
"cs_error_unknown"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _RQ_TYPE(x) \
|
#define _RQ_TYPE(x) \
|
||||||
((x) == DM_ULOG_CHECKPOINT_READY) ? "DM_ULOG_CHECKPOINT_READY": \
|
((x) == DM_ULOG_CHECKPOINT_READY) ? "DM_ULOG_CHECKPOINT_READY": \
|
||||||
@@ -104,11 +71,10 @@ static SaVersionT version = { 'B', 1, 1 };
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUGGING_HISTORY 100
|
#define DEBUGGING_HISTORY 100
|
||||||
#define DEBUGGING_BUFLEN 128
|
|
||||||
#define LOG_SPRINT(cc, f, arg...) do { \
|
#define LOG_SPRINT(cc, f, arg...) do { \
|
||||||
cc->idx++; \
|
cc->idx++; \
|
||||||
cc->idx = cc->idx % DEBUGGING_HISTORY; \
|
cc->idx = cc->idx % DEBUGGING_HISTORY; \
|
||||||
snprintf(cc->debugging[cc->idx], DEBUGGING_BUFLEN, f, ## arg); \
|
sprintf(cc->debugging[cc->idx], f, ## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int log_resp_rec = 0;
|
static int log_resp_rec = 0;
|
||||||
@@ -151,7 +117,7 @@ struct clog_cpg {
|
|||||||
uint32_t checkpoint_requesters[MAX_CHECKPOINT_REQUESTERS];
|
uint32_t checkpoint_requesters[MAX_CHECKPOINT_REQUESTERS];
|
||||||
struct checkpoint_data *checkpoint_list;
|
struct checkpoint_data *checkpoint_list;
|
||||||
int idx;
|
int idx;
|
||||||
char debugging[DEBUGGING_HISTORY][DEBUGGING_BUFLEN];
|
char debugging[DEBUGGING_HISTORY][128];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dm_list clog_cpg_list;
|
static struct dm_list clog_cpg_list;
|
||||||
@@ -837,11 +803,6 @@ static int import_checkpoint(struct clog_cpg *entry, int no_read,
|
|||||||
{
|
{
|
||||||
int bitmap_size;
|
int bitmap_size;
|
||||||
|
|
||||||
if (no_read) {
|
|
||||||
LOG_DBG("Checkpoint for this log already received");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitmap_size = (rq->u_rq.data_size - RECOVERING_REGION_SECTION_SIZE) / 2;
|
bitmap_size = (rq->u_rq.data_size - RECOVERING_REGION_SECTION_SIZE) / 2;
|
||||||
if (bitmap_size < 0) {
|
if (bitmap_size < 0) {
|
||||||
LOG_ERROR("Checkpoint has invalid payload size.");
|
LOG_ERROR("Checkpoint has invalid payload size.");
|
||||||
@@ -985,16 +946,8 @@ static int do_cluster_work(void *data __attribute__((unused)))
|
|||||||
|
|
||||||
dm_list_iterate_items_safe(entry, tmp, &clog_cpg_list) {
|
dm_list_iterate_items_safe(entry, tmp, &clog_cpg_list) {
|
||||||
r = cpg_dispatch(entry->handle, CS_DISPATCH_ALL);
|
r = cpg_dispatch(entry->handle, CS_DISPATCH_ALL);
|
||||||
if (r != CS_OK) {
|
if (r != CS_OK)
|
||||||
if ((r == CS_ERR_BAD_HANDLE) &&
|
LOG_ERROR("cpg_dispatch failed: %d", r);
|
||||||
((entry->state == INVALID) ||
|
|
||||||
(entry->state == LEAVING)))
|
|
||||||
/* It's ok if we've left the cluster */
|
|
||||||
r = CS_OK;
|
|
||||||
else
|
|
||||||
LOG_ERROR("cpg_dispatch failed: %s",
|
|
||||||
str_ais_error(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry->free_me) {
|
if (entry->free_me) {
|
||||||
free(entry);
|
free(entry);
|
||||||
@@ -1067,7 +1020,7 @@ static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gna
|
|||||||
int i_am_server;
|
int i_am_server;
|
||||||
int response = 0;
|
int response = 0;
|
||||||
struct clog_request *rq = msg;
|
struct clog_request *rq = msg;
|
||||||
struct clog_request *tmp_rq, *tmp_rq2;
|
struct clog_request *tmp_rq;
|
||||||
struct clog_cpg *match;
|
struct clog_cpg *match;
|
||||||
|
|
||||||
match = find_clog_cpg(handle);
|
match = find_clog_cpg(handle);
|
||||||
@@ -1198,17 +1151,18 @@ static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gna
|
|||||||
|
|
||||||
if (match->state == INVALID) {
|
if (match->state == INVALID) {
|
||||||
LOG_DBG("Log not valid yet, storing request");
|
LOG_DBG("Log not valid yet, storing request");
|
||||||
if (!(tmp_rq2 = malloc(DM_ULOG_REQUEST_SIZE))) {
|
tmp_rq = malloc(DM_ULOG_REQUEST_SIZE);
|
||||||
|
if (!tmp_rq) {
|
||||||
LOG_ERROR("cpg_message_callback: Unable to"
|
LOG_ERROR("cpg_message_callback: Unable to"
|
||||||
" allocate transfer structs");
|
" allocate transfer structs");
|
||||||
r = -ENOMEM; /* FIXME: Better error #? */
|
r = -ENOMEM; /* FIXME: Better error #? */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(tmp_rq2, rq, sizeof(*rq) + rq->u_rq.data_size);
|
memcpy(tmp_rq, rq, sizeof(*rq) + rq->u_rq.data_size);
|
||||||
tmp_rq2->pit_server = match->lowest_id;
|
tmp_rq->pit_server = match->lowest_id;
|
||||||
dm_list_init(&tmp_rq2->u.list);
|
dm_list_init(&tmp_rq->u.list);
|
||||||
dm_list_add(&match->startup_list, &tmp_rq2->u.list);
|
dm_list_add(&match->startup_list, &tmp_rq->u.list);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,9 +1249,7 @@ static void cpg_join_callback(struct clog_cpg *match,
|
|||||||
uint32_t my_pid = (uint32_t)getpid();
|
uint32_t my_pid = (uint32_t)getpid();
|
||||||
uint32_t lowest = match->lowest_id;
|
uint32_t lowest = match->lowest_id;
|
||||||
struct clog_request *rq;
|
struct clog_request *rq;
|
||||||
char dbuf[64] = { 0 };
|
char dbuf[32] = { 0 };
|
||||||
char *dbuf_p = dbuf;
|
|
||||||
size_t dbuf_rem = sizeof dbuf;
|
|
||||||
|
|
||||||
/* Assign my_cluster_id */
|
/* Assign my_cluster_id */
|
||||||
if ((my_cluster_id == 0xDEAD) && (joined->pid == my_pid))
|
if ((my_cluster_id == 0xDEAD) && (joined->pid == my_pid))
|
||||||
@@ -1313,17 +1265,9 @@ static void cpg_join_callback(struct clog_cpg *match,
|
|||||||
if (joined->nodeid == my_cluster_id)
|
if (joined->nodeid == my_cluster_id)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < member_list_entries - 1; i++) {
|
for (i = 0; i < member_list_entries - 1; i++)
|
||||||
int written = snprintf(dbuf_p, dbuf_rem, "%u-", member_list[i].nodeid);
|
sprintf(dbuf+strlen(dbuf), "%u-", member_list[i].nodeid);
|
||||||
if (written < 0) continue; /* impossible */
|
sprintf(dbuf+strlen(dbuf), "(%u)", joined->nodeid);
|
||||||
if ((unsigned)written >= dbuf_rem) {
|
|
||||||
dbuf_rem = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dbuf_rem -= written;
|
|
||||||
dbuf_p += written;
|
|
||||||
}
|
|
||||||
snprintf(dbuf_p, dbuf_rem, "(%u)", joined->nodeid);
|
|
||||||
LOG_COND(log_checkpoint, "[%s] Joining node, %u needs checkpoint [%s]",
|
LOG_COND(log_checkpoint, "[%s] Joining node, %u needs checkpoint [%s]",
|
||||||
SHORT_UUID(match->name.value), joined->nodeid, dbuf);
|
SHORT_UUID(match->name.value), joined->nodeid, dbuf);
|
||||||
|
|
||||||
@@ -1440,7 +1384,7 @@ static void cpg_leave_callback(struct clog_cpg *match,
|
|||||||
free(rq);
|
free(rq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0, j = 0; (int) i < match->checkpoints_needed; i++, j++) {
|
for (i = 0, j = 0; i < match->checkpoints_needed; i++, j++) {
|
||||||
match->checkpoint_requesters[j] = match->checkpoint_requesters[i];
|
match->checkpoint_requesters[j] = match->checkpoint_requesters[i];
|
||||||
if (match->checkpoint_requesters[i] == left->nodeid) {
|
if (match->checkpoint_requesters[i] == left->nodeid) {
|
||||||
LOG_ERROR("[%s] Removing pending ckpt from needed list (%u is leaving)",
|
LOG_ERROR("[%s] Removing pending ckpt from needed list (%u is leaving)",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef _LVM_CLOG_CLUSTER_H
|
#ifndef _LVM_CLOG_CLUSTER_H
|
||||||
#define _LVM_CLOG_CLUSTER_H
|
#define _LVM_CLOG_CLUSTER_H
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef _LVM_CLOG_COMMON_H
|
#ifndef _LVM_CLOG_COMMON_H
|
||||||
#define _LVM_CLOG_COMMON_H
|
#define _LVM_CLOG_COMMON_H
|
||||||
|
|||||||
@@ -126,14 +126,13 @@ static int v5_endian_to_network(struct clog_request *rq)
|
|||||||
|
|
||||||
u_rq->error = xlate32(u_rq->error);
|
u_rq->error = xlate32(u_rq->error);
|
||||||
u_rq->seq = xlate32(u_rq->seq);
|
u_rq->seq = xlate32(u_rq->seq);
|
||||||
|
u_rq->request_type = xlate32(u_rq->request_type);
|
||||||
|
u_rq->data_size = xlate64(u_rq->data_size);
|
||||||
|
|
||||||
rq->originator = xlate32(rq->originator);
|
rq->originator = xlate32(rq->originator);
|
||||||
|
|
||||||
v5_data_endian_switch(rq, 1);
|
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;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ static int v5_endian_from_network(struct clog_request *rq)
|
|||||||
u_rq->error = xlate32(u_rq->error);
|
u_rq->error = xlate32(u_rq->error);
|
||||||
u_rq->seq = xlate32(u_rq->seq);
|
u_rq->seq = xlate32(u_rq->seq);
|
||||||
u_rq->request_type = xlate32(u_rq->request_type);
|
u_rq->request_type = xlate32(u_rq->request_type);
|
||||||
u_rq->data_size = xlate32(u_rq->data_size);
|
u_rq->data_size = xlate64(u_rq->data_size);
|
||||||
|
|
||||||
rq->originator = xlate32(rq->originator);
|
rq->originator = xlate32(rq->originator);
|
||||||
|
|
||||||
@@ -183,11 +182,12 @@ int clog_request_from_network(void *data, size_t data_len)
|
|||||||
{
|
{
|
||||||
uint64_t *vp = data;
|
uint64_t *vp = data;
|
||||||
uint64_t version = xlate64(vp[0]);
|
uint64_t version = xlate64(vp[0]);
|
||||||
|
uint64_t unconverted_version = vp[1];
|
||||||
struct clog_request *rq = data;
|
struct clog_request *rq = data;
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 5: /* Upstream */
|
case 5: /* Upstream */
|
||||||
if (version == vp[0])
|
if (version == unconverted_version)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case 4: /* RHEL 5.[45] */
|
case 4: /* RHEL 5.[45] */
|
||||||
|
|||||||
@@ -7,12 +7,11 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -33,13 +32,12 @@
|
|||||||
#define LOG_OFFSET 2
|
#define LOG_OFFSET 2
|
||||||
|
|
||||||
#define RESYNC_HISTORY 50
|
#define RESYNC_HISTORY 50
|
||||||
#define RESYNC_BUFLEN 128
|
|
||||||
//static char resync_history[RESYNC_HISTORY][128];
|
//static char resync_history[RESYNC_HISTORY][128];
|
||||||
//static int idx = 0;
|
//static int idx = 0;
|
||||||
#define LOG_SPRINT(_lc, f, arg...) do { \
|
#define LOG_SPRINT(_lc, f, arg...) do { \
|
||||||
lc->idx++; \
|
lc->idx++; \
|
||||||
lc->idx = lc->idx % RESYNC_HISTORY; \
|
lc->idx = lc->idx % RESYNC_HISTORY; \
|
||||||
snprintf(lc->resync_history[lc->idx], RESYNC_BUFLEN, f, ## arg); \
|
sprintf(lc->resync_history[lc->idx], f, ## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
struct log_header {
|
struct log_header {
|
||||||
@@ -90,7 +88,7 @@ struct log_c {
|
|||||||
size_t disk_size; /* size of disk_buffer in bytes */
|
size_t disk_size; /* size of disk_buffer in bytes */
|
||||||
void *disk_buffer; /* aligned memory for O_DIRECT */
|
void *disk_buffer; /* aligned memory for O_DIRECT */
|
||||||
int idx;
|
int idx;
|
||||||
char resync_history[RESYNC_HISTORY][RESYNC_BUFLEN];
|
char resync_history[RESYNC_HISTORY][128];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mark_entry {
|
struct mark_entry {
|
||||||
@@ -574,12 +572,6 @@ static int clog_ctr(struct dm_ulog_request *rq)
|
|||||||
for (argc = 0, p = rq->data; (p = strstr(p, " ")); p++, argc++)
|
for (argc = 0, p = rq->data; (p = strstr(p, " ")); p++, argc++)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
if (!argc) {
|
|
||||||
LOG_ERROR("Received constructor request with bad data %s",
|
|
||||||
rq->data);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv = malloc(argc * sizeof(char *));
|
argv = malloc(argc * sizeof(char *));
|
||||||
if (!argv)
|
if (!argv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -1452,7 +1444,7 @@ static int disk_status_info(struct log_c *lc, struct dm_ulog_request *rq)
|
|||||||
char *data = (char *)rq->data;
|
char *data = (char *)rq->data;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (fstat(lc->disk_fd, &statbuf)) {
|
if(fstat(lc->disk_fd, &statbuf)) {
|
||||||
rq->error = -errno;
|
rq->error = -errno;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@@ -1515,7 +1507,7 @@ static int disk_status_table(struct log_c *lc, struct dm_ulog_request *rq)
|
|||||||
char *data = (char *)rq->data;
|
char *data = (char *)rq->data;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (fstat(lc->disk_fd, &statbuf)) {
|
if(fstat(lc->disk_fd, &statbuf)) {
|
||||||
rq->error = -errno;
|
rq->error = -errno;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef _LVM_CLOG_FUNCTIONS_H
|
#ifndef _LVM_CLOG_FUNCTIONS_H
|
||||||
#define _LVM_CLOG_FUNCTIONS_H
|
#define _LVM_CLOG_FUNCTIONS_H
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "link_mon.h"
|
#include "link_mon.h"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef _LVM_CLOG_LINK_MON_H
|
#ifndef _LVM_CLOG_LINK_MON_H
|
||||||
#define _LVM_CLOG_LINK_MON_H
|
#define _LVM_CLOG_LINK_MON_H
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef _LVM_CLOG_LOCAL_H
|
#ifndef _LVM_CLOG_LOCAL_H
|
||||||
#define _LVM_CLOG_LOCAL_H
|
#define _LVM_CLOG_LOCAL_H
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LVM_CLOG_LOGGING_H
|
#ifndef _LVM_CLOG_LOGGING_H
|
||||||
@@ -63,7 +63,7 @@ extern int log_resend_requests;
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
||||||
#else /* DEBUG */
|
#else /* DEBUG */
|
||||||
#define LOG_DBG(f, arg...) do {} while (0)
|
#define LOG_DBG(f, arg...)
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
#define LOG_COND(__X, f, arg...) do {\
|
#define LOG_COND(__X, f, arg...) do {\
|
||||||
|
|||||||
1
daemons/dmeventd/.gitignore
vendored
1
daemons/dmeventd/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
dmeventd
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# 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,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
@@ -59,10 +59,8 @@ device-mapper: $(TARGETS)
|
|||||||
LIBS += -ldevmapper
|
LIBS += -ldevmapper
|
||||||
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
|
LVMLIBS += -ldevmapper-event $(PTHREAD_LIBS)
|
||||||
|
|
||||||
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
|
||||||
|
|
||||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
|
$(CC) $(CFLAGS) $(LDFLAGS) $(ELDFLAGS) -L. -o $@ dmeventd.o \
|
||||||
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
$(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
|
||||||
|
|
||||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DMEVENTD_DOT_H__
|
#ifndef __DMEVENTD_DOT_H__
|
||||||
@@ -34,7 +34,6 @@ enum dm_event_command {
|
|||||||
DM_EVENT_CMD_HELLO,
|
DM_EVENT_CMD_HELLO,
|
||||||
DM_EVENT_CMD_DIE,
|
DM_EVENT_CMD_DIE,
|
||||||
DM_EVENT_CMD_GET_STATUS,
|
DM_EVENT_CMD_GET_STATUS,
|
||||||
DM_EVENT_CMD_GET_PARAMETERS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Message passed between client and daemon. */
|
/* Message passed between client and daemon. */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of the device-mapper userspace tools.
|
* This file is part of the device-mapper userspace tools.
|
||||||
*
|
*
|
||||||
@@ -9,25 +9,27 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dm-logging.h"
|
|
||||||
#include "dmlib.h"
|
#include "dmlib.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
|
//#include "libmultilog.h"
|
||||||
#include "dmeventd.h"
|
#include "dmeventd.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||||
#include <pthread.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
static int _debug_level = 0;
|
|
||||||
static int _use_syslog = 0;
|
|
||||||
static int _sequence_nr = 0;
|
static int _sequence_nr = 0;
|
||||||
|
|
||||||
struct dm_event_handler {
|
struct dm_event_handler {
|
||||||
@@ -55,7 +57,7 @@ static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
|
|||||||
|
|
||||||
struct dm_event_handler *dm_event_handler_create(void)
|
struct dm_event_handler *dm_event_handler_create(void)
|
||||||
{
|
{
|
||||||
struct dm_event_handler *dmevh;
|
struct dm_event_handler *dmevh = NULL;
|
||||||
|
|
||||||
if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
|
if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
|
||||||
log_error("Failed to allocate event handler.");
|
log_error("Failed to allocate event handler.");
|
||||||
@@ -80,7 +82,8 @@ int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const cha
|
|||||||
|
|
||||||
dm_free(dmevh->dmeventd_path);
|
dm_free(dmevh->dmeventd_path);
|
||||||
|
|
||||||
if (!(dmevh->dmeventd_path = dm_strdup(dmeventd_path)))
|
dmevh->dmeventd_path = dm_strdup(dmeventd_path);
|
||||||
|
if (!dmevh->dmeventd_path)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -90,10 +93,10 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
|
|||||||
{
|
{
|
||||||
if (!path) /* noop */
|
if (!path) /* noop */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dm_free(dmevh->dso);
|
dm_free(dmevh->dso);
|
||||||
|
|
||||||
if (!(dmevh->dso = dm_strdup(path)))
|
dmevh->dso = dm_strdup(path);
|
||||||
|
if (!dmevh->dso)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -106,9 +109,9 @@ int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *de
|
|||||||
|
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
if (!(dmevh->dev_name = dm_strdup(dev_name)))
|
dmevh->dev_name = dm_strdup(dev_name);
|
||||||
|
if (!dmevh->dev_name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,9 +122,9 @@ int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
|
|||||||
|
|
||||||
_dm_event_handler_clear_dev_info(dmevh);
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
if (!(dmevh->uuid = dm_strdup(uuid)))
|
dmevh->uuid = dm_strdup(uuid);
|
||||||
|
if (!dmevh->uuid)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +201,7 @@ static int _check_message_id(struct dm_event_daemon_message *msg)
|
|||||||
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
|
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
|
||||||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
|
(pid != getpid()) || (seq_nr != _sequence_nr)) {
|
||||||
log_error("Ignoring out-of-sequence reply from dmeventd. "
|
log_error("Ignoring out-of-sequence reply from dmeventd. "
|
||||||
"Expected %d:%d but received %s.", getpid(),
|
"Expected %d:%d but received %s", getpid(),
|
||||||
_sequence_nr, msg->data);
|
_sequence_nr, msg->data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -221,6 +224,7 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
|||||||
unsigned bytes = 0;
|
unsigned bytes = 0;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
struct timeval tval = { 0, 0 };
|
||||||
size_t size = 2 * sizeof(uint32_t); /* status + size */
|
size_t size = 2 * sizeof(uint32_t); /* status + size */
|
||||||
uint32_t *header = alloca(size);
|
uint32_t *header = alloca(size);
|
||||||
char *buf = (char *)header;
|
char *buf = (char *)header;
|
||||||
@@ -228,12 +232,13 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
|||||||
while (bytes < size) {
|
while (bytes < size) {
|
||||||
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
|
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
|
||||||
/* Watch daemon read FIFO for input. */
|
/* Watch daemon read FIFO for input. */
|
||||||
struct timeval tval = { .tv_sec = 1 };
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fifos->server, &fds);
|
FD_SET(fifos->server, &fds);
|
||||||
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
tval.tv_sec = 1;
|
||||||
|
ret = select(fifos->server + 1, &fds, NULL, NULL,
|
||||||
|
&tval);
|
||||||
if (ret < 0 && errno != EINTR) {
|
if (ret < 0 && errno != EINTR) {
|
||||||
log_error("Unable to read from event server.");
|
log_error("Unable to read from event server");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((ret == 0) && (i > 4) && !bytes) {
|
if ((ret == 0) && (i > 4) && !bytes) {
|
||||||
@@ -278,13 +283,15 @@ static int _daemon_read(struct dm_event_fifos *fifos,
|
|||||||
static int _daemon_write(struct dm_event_fifos *fifos,
|
static int _daemon_write(struct dm_event_fifos *fifos,
|
||||||
struct dm_event_daemon_message *msg)
|
struct dm_event_daemon_message *msg)
|
||||||
{
|
{
|
||||||
int ret;
|
unsigned bytes = 0;
|
||||||
|
int ret = 0;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
size_t bytes = 0;
|
|
||||||
size_t size = 2 * sizeof(uint32_t) + msg->size;
|
size_t size = 2 * sizeof(uint32_t) + msg->size;
|
||||||
uint32_t *header = alloca(size);
|
uint32_t *header = alloca(size);
|
||||||
char *buf = (char *)header;
|
char *buf = (char *)header;
|
||||||
char drainbuf[128];
|
char drainbuf[128];
|
||||||
|
struct timeval tval = { 0, 0 };
|
||||||
|
|
||||||
header[0] = htonl(msg->cmd);
|
header[0] = htonl(msg->cmd);
|
||||||
header[1] = htonl(msg->size);
|
header[1] = htonl(msg->size);
|
||||||
@@ -292,25 +299,17 @@ static int _daemon_write(struct dm_event_fifos *fifos,
|
|||||||
|
|
||||||
/* drain the answer fifo */
|
/* drain the answer fifo */
|
||||||
while (1) {
|
while (1) {
|
||||||
struct timeval tval = { .tv_usec = 100 };
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fifos->server, &fds);
|
FD_SET(fifos->server, &fds);
|
||||||
|
tval.tv_usec = 100;
|
||||||
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
||||||
if (ret < 0) {
|
if ((ret < 0) && (errno != EINTR)) {
|
||||||
if (errno == EINTR)
|
log_error("Unable to talk to event daemon");
|
||||||
continue;
|
|
||||||
log_error("Unable to talk to event daemon.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
break;
|
break;
|
||||||
ret = read(fifos->server, drainbuf, sizeof(drainbuf));
|
ret = read(fifos->server, drainbuf, 127);
|
||||||
if (ret < 0) {
|
|
||||||
if ((errno == EINTR) || (errno == EAGAIN))
|
|
||||||
continue;
|
|
||||||
log_error("Unable to talk to event daemon.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bytes < size) {
|
while (bytes < size) {
|
||||||
@@ -320,7 +319,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
|
|||||||
FD_SET(fifos->client, &fds);
|
FD_SET(fifos->client, &fds);
|
||||||
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
|
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
|
||||||
if ((ret < 0) && (errno != EINTR)) {
|
if ((ret < 0) && (errno != EINTR)) {
|
||||||
log_error("Unable to talk to event daemon.");
|
log_error("Unable to talk to event daemon");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} while (ret < 1);
|
} while (ret < 1);
|
||||||
@@ -330,7 +329,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
|
|||||||
if ((errno == EINTR) || (errno == EAGAIN))
|
if ((errno == EINTR) || (errno == EAGAIN))
|
||||||
continue;
|
continue;
|
||||||
else {
|
else {
|
||||||
log_error("Unable to talk to event daemon.");
|
log_error("Unable to talk to event daemon");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,6 +345,9 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
|||||||
const char *dso_name, const char *dev_name,
|
const char *dso_name, const char *dev_name,
|
||||||
enum dm_event_mask evmask, uint32_t timeout)
|
enum dm_event_mask evmask, uint32_t timeout)
|
||||||
{
|
{
|
||||||
|
const char *dso = dso_name ? dso_name : "-";
|
||||||
|
const char *dev = dev_name ? dev_name : "-";
|
||||||
|
const char *fmt = "%d:%d %s %s %u %" PRIu32;
|
||||||
int msg_size;
|
int msg_size;
|
||||||
memset(msg, 0, sizeof(*msg));
|
memset(msg, 0, sizeof(*msg));
|
||||||
|
|
||||||
@@ -353,17 +355,14 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
|||||||
* Set command and pack the arguments
|
* Set command and pack the arguments
|
||||||
* into ASCII message string.
|
* into ASCII message string.
|
||||||
*/
|
*/
|
||||||
if ((msg_size =
|
msg->cmd = cmd;
|
||||||
((cmd == DM_EVENT_CMD_HELLO) ?
|
if (cmd == DM_EVENT_CMD_HELLO)
|
||||||
dm_asprintf(&(msg->data), "%d:%d HELLO", getpid(), _sequence_nr) :
|
fmt = "%d:%d HELLO";
|
||||||
dm_asprintf(&(msg->data), "%d:%d %s %s %u %" PRIu32,
|
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
|
||||||
getpid(), _sequence_nr,
|
dso, dev, evmask, timeout)) < 0) {
|
||||||
dso_name ? : "-", dev_name ? : "-", evmask, timeout)))
|
log_error("_daemon_talk: message allocation failed");
|
||||||
< 0) {
|
|
||||||
log_error("_daemon_talk: message allocation failed.");
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
msg->cmd = cmd;
|
|
||||||
msg->size = msg_size;
|
msg->size = msg_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -373,13 +372,14 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
|||||||
if (!_daemon_write(fifos, msg)) {
|
if (!_daemon_write(fifos, msg)) {
|
||||||
stack;
|
stack;
|
||||||
dm_free(msg->data);
|
dm_free(msg->data);
|
||||||
msg->data = NULL;
|
msg->data = 0;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
dm_free(msg->data);
|
dm_free(msg->data);
|
||||||
msg->data = NULL;
|
msg->data = 0;
|
||||||
|
|
||||||
if (!_daemon_read(fifos, msg)) {
|
if (!_daemon_read(fifos, msg)) {
|
||||||
stack;
|
stack;
|
||||||
@@ -412,55 +412,28 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
|||||||
char default_dmeventd_path[] = DMEVENTD_PATH;
|
char default_dmeventd_path[] = DMEVENTD_PATH;
|
||||||
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
||||||
|
|
||||||
/*
|
if (stat(fifos->client_path, &statbuf))
|
||||||
* FIXME Explicitly verify the code's requirement that client_path is secure:
|
goto start_server;
|
||||||
* - 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 (!S_ISFIFO(statbuf.st_mode)) {
|
||||||
if ((lstat(fifos->client_path, &statbuf) < 0)) {
|
log_error("%s is not a fifo.", fifos->client_path);
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anyone listening? If not, errno will be ENXIO */
|
/* Anyone listening? If not, errno will be ENXIO */
|
||||||
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
||||||
if (fifos->client >= 0) {
|
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 */
|
/* server is running and listening */
|
||||||
if (close(fifos->client))
|
if (close(fifos->client))
|
||||||
log_sys_debug("close", fifos->client_path);
|
log_sys_error("close", fifos->client_path);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (errno != ENXIO && errno != ENOENT) {
|
} else if (errno != ENXIO) {
|
||||||
/* problem */
|
/* problem */
|
||||||
log_sys_error("open", fifos->client_path);
|
log_sys_error("open", fifos->client_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_server:
|
start_server:
|
||||||
/* server is not running */
|
/* server is not running */
|
||||||
|
|
||||||
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
|
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
|
||||||
@@ -475,11 +448,11 @@ start_server:
|
|||||||
|
|
||||||
else if (!pid) {
|
else if (!pid) {
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
log_error("Unable to exec dmeventd: %s.", strerror(errno));
|
log_error("Unable to exec dmeventd: %s", strerror(errno));
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
if (waitpid(pid, &status, 0) < 0)
|
if (waitpid(pid, &status, 0) < 0)
|
||||||
log_error("Unable to start dmeventd: %s.",
|
log_error("Unable to start dmeventd: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
else if (WEXITSTATUS(status))
|
else if (WEXITSTATUS(status))
|
||||||
log_error("Unable to start dmeventd.");
|
log_error("Unable to start dmeventd.");
|
||||||
@@ -495,6 +468,10 @@ int init_fifos(struct dm_event_fifos *fifos)
|
|||||||
/* FIXME? Is fifo the most suitable method? Why not share
|
/* FIXME? Is fifo the most suitable method? Why not share
|
||||||
comms/daemon code with something else e.g. multipath? */
|
comms/daemon code with something else e.g. multipath? */
|
||||||
|
|
||||||
|
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||||
|
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||||
|
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||||
|
|
||||||
/* Open the fifo used to read from the daemon. */
|
/* Open the fifo used to read from the daemon. */
|
||||||
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
|
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
|
||||||
log_sys_error("open", fifos->server_path);
|
log_sys_error("open", fifos->server_path);
|
||||||
@@ -504,27 +481,32 @@ int init_fifos(struct dm_event_fifos *fifos)
|
|||||||
/* Lock out anyone else trying to do communication with the daemon. */
|
/* Lock out anyone else trying to do communication with the daemon. */
|
||||||
if (flock(fifos->server, LOCK_EX) < 0) {
|
if (flock(fifos->server, LOCK_EX) < 0) {
|
||||||
log_sys_error("flock", fifos->server_path);
|
log_sys_error("flock", fifos->server_path);
|
||||||
goto bad;
|
if (close(fifos->server))
|
||||||
|
log_sys_error("close", fifos->server_path);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
||||||
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
|
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
|
||||||
log_sys_error("open", fifos->client_path);
|
log_sys_error("open", fifos->client_path);
|
||||||
goto bad;
|
if (close(fifos->server))
|
||||||
|
log_sys_error("close", fifos->server_path);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
|
||||||
if (close(fifos->server))
|
|
||||||
log_sys_debug("close", fifos->server_path);
|
|
||||||
fifos->server = -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize client. */
|
/* Initialize client. */
|
||||||
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
|
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||||
{
|
{
|
||||||
|
/* init fifos */
|
||||||
|
memset(fifos, 0, sizeof(*fifos));
|
||||||
|
|
||||||
|
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||||
|
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||||
|
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||||
|
|
||||||
if (!_start_daemon(dmeventd_path, fifos))
|
if (!_start_daemon(dmeventd_path, fifos))
|
||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
@@ -533,16 +515,13 @@ static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
|
|||||||
|
|
||||||
void fini_fifos(struct dm_event_fifos *fifos)
|
void fini_fifos(struct dm_event_fifos *fifos)
|
||||||
{
|
{
|
||||||
if (fifos->client >= 0 && close(fifos->client))
|
if (flock(fifos->server, LOCK_UN))
|
||||||
log_sys_debug("close", fifos->client_path);
|
log_error("flock unlock %s", fifos->server_path);
|
||||||
|
|
||||||
if (fifos->server >= 0) {
|
if (close(fifos->client))
|
||||||
if (flock(fifos->server, LOCK_UN))
|
log_sys_error("close", fifos->client_path);
|
||||||
log_sys_debug("flock unlock", fifos->server_path);
|
if (close(fifos->server))
|
||||||
|
log_sys_error("close", fifos->server_path);
|
||||||
if (close(fifos->server))
|
|
||||||
log_sys_debug("close", fifos->server_path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get uuid of a device */
|
/* Get uuid of a device */
|
||||||
@@ -552,7 +531,7 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
|||||||
struct dm_info info;
|
struct dm_info info;
|
||||||
|
|
||||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
|
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
|
||||||
log_error("_get_device_info: dm_task creation for info failed.");
|
log_error("_get_device_info: dm_task creation for info failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,19 +549,19 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
|||||||
|
|
||||||
/* FIXME Add name or uuid or devno to messages */
|
/* FIXME Add name or uuid or devno to messages */
|
||||||
if (!dm_task_run(dmt)) {
|
if (!dm_task_run(dmt)) {
|
||||||
log_error("_get_device_info: dm_task_run() failed.");
|
log_error("_get_device_info: dm_task_run() failed");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dm_task_get_info(dmt, &info)) {
|
if (!dm_task_get_info(dmt, &info)) {
|
||||||
log_error("_get_device_info: failed to get info for device.");
|
log_error("_get_device_info: failed to get info for device");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.exists) {
|
if (!info.exists) {
|
||||||
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found.",
|
log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
|
||||||
dmevh->uuid ? : "",
|
dmevh->uuid ? : "",
|
||||||
(!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
|
(!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->uuid && !dmevh->dev_name && dmevh->major > 0) ? 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->major > 0) ? ":" : "",
|
||||||
@@ -592,6 +571,7 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return dmt;
|
return dmt;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
@@ -605,17 +585,11 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
|
|||||||
enum dm_event_mask evmask, uint32_t timeout)
|
enum dm_event_mask evmask, uint32_t timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct dm_event_fifos fifos = {
|
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)) {
|
if (!_init_client(dmeventd_path, &fifos)) {
|
||||||
ret = -ESRCH;
|
stack;
|
||||||
goto_out;
|
return -ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
|
||||||
@@ -625,7 +599,7 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
|
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
|
||||||
out:
|
|
||||||
/* what is the opposite of init? */
|
/* what is the opposite of init? */
|
||||||
fini_fifos(&fifos);
|
fini_fifos(&fifos);
|
||||||
|
|
||||||
@@ -638,23 +612,18 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
|
|||||||
int ret = 1, err;
|
int ret = 1, err;
|
||||||
const char *uuid;
|
const char *uuid;
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
struct dm_event_daemon_message msg = { 0 };
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
if (!(dmt = _get_device_info(dmevh)))
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
return_0;
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uuid = dm_task_get_uuid(dmt);
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") &&
|
|
||||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
|
|
||||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
|
|
||||||
!strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
|
|
||||||
log_warn("WARNING: %s: dmeventd plugins are deprecated.", dmevh->dso);
|
|
||||||
|
|
||||||
|
|
||||||
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||||
log_error("%s: event registration failed: %s.",
|
log_error("%s: event registration failed: %s",
|
||||||
dm_task_get_name(dmt),
|
dm_task_get_name(dmt),
|
||||||
msg.data ? msg.data : strerror(-err));
|
msg.data ? msg.data : strerror(-err));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -672,16 +641,18 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
|
|||||||
int ret = 1, err;
|
int ret = 1, err;
|
||||||
const char *uuid;
|
const char *uuid;
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
struct dm_event_daemon_message msg = { 0 };
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
if (!(dmt = _get_device_info(dmevh)))
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
return_0;
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uuid = dm_task_get_uuid(dmt);
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
|
||||||
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||||
log_error("%s: event deregistration failed: %s.",
|
log_error("%s: event deregistration failed: %s",
|
||||||
dm_task_get_name(dmt),
|
dm_task_get_name(dmt),
|
||||||
msg.data ? msg.data : strerror(-err));
|
msg.data ? msg.data : strerror(-err));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -716,18 +687,20 @@ static char *_fetch_string(char **src, const int delimiter)
|
|||||||
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||||
char **uuid, enum dm_event_mask *evmask)
|
char **uuid, enum dm_event_mask *evmask)
|
||||||
{
|
{
|
||||||
char *id;
|
char *id = NULL;
|
||||||
char *p = msg->data;
|
char *p = msg->data;
|
||||||
|
|
||||||
if ((id = _fetch_string(&p, ' ')) &&
|
if ((id = _fetch_string(&p, ' ')) &&
|
||||||
(*dso_name = _fetch_string(&p, ' ')) &&
|
(*dso_name = _fetch_string(&p, ' ')) &&
|
||||||
(*uuid = _fetch_string(&p, ' '))) {
|
(*uuid = _fetch_string(&p, ' '))) {
|
||||||
*evmask = atoi(p);
|
*evmask = atoi(p);
|
||||||
|
|
||||||
dm_free(id);
|
dm_free(id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dm_free(id);
|
if (id)
|
||||||
|
dm_free(id);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,7 +727,6 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
|
|
||||||
uuid = dm_task_get_uuid(dmt);
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
/* FIXME Distinguish errors connecting to daemon */
|
|
||||||
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
|
if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
|
||||||
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
|
DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
|
||||||
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
|
&msg, dmevh->dso, uuid, dmevh->mask, 0)) {
|
||||||
@@ -778,8 +750,8 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
dmevh->uuid = dm_strdup(reply_uuid);
|
||||||
if (!(dmevh->uuid = dm_strdup(reply_uuid))) {
|
if (!dmevh->uuid) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -798,7 +770,8 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
dm_free(reply_uuid);
|
dm_free(reply_uuid);
|
||||||
reply_uuid = NULL;
|
reply_uuid = NULL;
|
||||||
|
|
||||||
if (!(dmevh->dev_name = dm_strdup(dm_task_get_name(dmt)))) {
|
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
|
||||||
|
if (!dmevh->dev_name) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -838,7 +811,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
|||||||
|
|
||||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||||
char *p;
|
char *p;
|
||||||
struct dm_event_daemon_message msg = { 0 };
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
|
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -855,99 +828,6 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
|||||||
return 1;
|
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 */
|
#if 0 /* left out for now */
|
||||||
|
|
||||||
static char *_skip_string(char *src, const int delimiter)
|
static char *_skip_string(char *src, const int delimiter)
|
||||||
@@ -960,7 +840,7 @@ static char *_skip_string(char *src, const int delimiter)
|
|||||||
|
|
||||||
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
||||||
{
|
{
|
||||||
struct dm_event_daemon_message msg = { 0 };
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
if (!device_exists(device_path))
|
if (!device_exists(device_path))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -972,24 +852,22 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
|||||||
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct dm_event_daemon_message msg = { 0 };
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
if (!device_exists(device_path))
|
if (!device_exists(device_path))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
|
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
|
||||||
0, 0))) {
|
0, 0))) {
|
||||||
char *p = _skip_string(msg.data, ' ');
|
char *p = _skip_string(msg.data, ' ');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
log_error("Malformed reply from dmeventd '%s'.",
|
log_error("malformed reply from dmeventd '%s'\n",
|
||||||
msg.data);
|
msg.data);
|
||||||
dm_free(msg.data);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
*timeout = atoi(p);
|
*timeout = atoi(p);
|
||||||
}
|
}
|
||||||
dm_free(msg.data);
|
if (msg.data)
|
||||||
|
dm_free(msg.data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of the device-mapper userspace tools.
|
* This file is part of the device-mapper userspace tools.
|
||||||
*
|
*
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -46,9 +46,8 @@ enum dm_event_mask {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
|
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
|
||||||
#define DM_EVENT_PROTOCOL_VERSION 2
|
#define DM_EVENT_PROTOCOL_VERSION 1
|
||||||
|
|
||||||
struct dm_task;
|
|
||||||
struct dm_event_handler;
|
struct dm_event_handler;
|
||||||
|
|
||||||
struct dm_event_handler *dm_event_handler_create(void);
|
struct dm_event_handler *dm_event_handler_create(void);
|
||||||
@@ -105,25 +104,6 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
|
|||||||
int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||||
int dm_event_unregister_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
|
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
|
||||||
detailed descriptions. */
|
detailed descriptions. */
|
||||||
// FIXME misuse of bitmask as enum
|
// FIXME misuse of bitmask as enum
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2010-2014 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
@@ -24,7 +24,7 @@ LIB_VERSION = $(LIB_VERSION_LVM)
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS)
|
LIBS += @LVM2CMD_LIB@ -ldevmapper $(PTHREAD_LIBS) $(DAEMON_LIBS)
|
||||||
|
|
||||||
install_lvm2: install_lib_shared
|
install_lvm2: install_lib_shared
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,15 +9,19 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "log.h"
|
||||||
#include "libdevmapper-event.h"
|
|
||||||
#include "lvm2cmd.h"
|
#include "lvm2cmd.h"
|
||||||
|
#include "dmeventd_lvm.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
extern int dmeventd_debug;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* register_device() is called first and performs initialisation.
|
* register_device() is called first and performs initialisation.
|
||||||
@@ -32,19 +36,48 @@ static int _register_count = 0;
|
|||||||
static struct dm_pool *_mem_pool = NULL;
|
static struct dm_pool *_mem_pool = NULL;
|
||||||
static void *_lvm_handle = NULL;
|
static void *_lvm_handle = NULL;
|
||||||
|
|
||||||
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.
|
* Currently only one event can be processed at a time.
|
||||||
*/
|
*/
|
||||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME Do not pass things directly to syslog, rather use the existing logging
|
||||||
|
* facilities to sort logging ... however that mechanism needs to be somehow
|
||||||
|
* configurable and we don't have that option yet
|
||||||
|
*/
|
||||||
|
static void _temporary_log_fn(int level,
|
||||||
|
const char *file __attribute__((unused)),
|
||||||
|
int line __attribute__((unused)),
|
||||||
|
int dm_errno __attribute__((unused)),
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
level &= ~(_LOG_STDERR | _LOG_ONCE);
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case _LOG_DEBUG:
|
||||||
|
if (dmeventd_debug >= 3)
|
||||||
|
syslog(LOG_DEBUG, "%s", message);
|
||||||
|
break;
|
||||||
|
case _LOG_INFO:
|
||||||
|
if (dmeventd_debug >= 2)
|
||||||
|
syslog(LOG_INFO, "%s", message);
|
||||||
|
break;
|
||||||
|
case _LOG_NOTICE:
|
||||||
|
if (dmeventd_debug >= 1)
|
||||||
|
syslog(LOG_NOTICE, "%s", message);
|
||||||
|
break;
|
||||||
|
case _LOG_WARN:
|
||||||
|
syslog(LOG_WARNING, "%s", message);
|
||||||
|
break;
|
||||||
|
case _LOG_ERR:
|
||||||
|
syslog(LOG_ERR, "%s", message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_CRIT, "%s", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dmeventd_lvm2_lock(void)
|
void dmeventd_lvm2_lock(void)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&_event_mutex);
|
pthread_mutex_lock(&_event_mutex);
|
||||||
@@ -61,26 +94,23 @@ int dmeventd_lvm2_init(void)
|
|||||||
|
|
||||||
pthread_mutex_lock(&_register_mutex);
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need some space for allocations. 1024 should be more
|
||||||
|
* than enough for what we need (device mapper name splitting)
|
||||||
|
*/
|
||||||
|
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (!_lvm_handle) {
|
if (!_lvm_handle) {
|
||||||
lvm2_log_fn(_lvm2_print_log);
|
lvm2_log_fn(_temporary_log_fn);
|
||||||
|
if (!(_lvm_handle = lvm2_init())) {
|
||||||
if (!(_lvm_handle = lvm2_init()))
|
dm_pool_destroy(_mem_pool);
|
||||||
goto out;
|
_mem_pool = NULL;
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
lvm2_disable_dmeventd_monitoring(_lvm_handle);
|
lvm2_disable_dmeventd_monitoring(_lvm_handle);
|
||||||
/* FIXME Temporary: move to dmeventd core */
|
/* FIXME Temporary: move to dmeventd core */
|
||||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||||
log_debug("lvm plugin initilized.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_register_count++;
|
_register_count++;
|
||||||
@@ -96,13 +126,11 @@ void dmeventd_lvm2_exit(void)
|
|||||||
pthread_mutex_lock(&_register_mutex);
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
if (!--_register_count) {
|
if (!--_register_count) {
|
||||||
log_debug("lvm plugin shuting down.");
|
|
||||||
lvm2_run(_lvm_handle, "_memlock_dec");
|
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||||
dm_pool_destroy(_mem_pool);
|
dm_pool_destroy(_mem_pool);
|
||||||
_mem_pool = NULL;
|
_mem_pool = NULL;
|
||||||
lvm2_exit(_lvm_handle);
|
lvm2_exit(_lvm_handle);
|
||||||
_lvm_handle = NULL;
|
_lvm_handle = NULL;
|
||||||
log_debug("lvm plugin exited.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&_register_mutex);
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
@@ -115,48 +143,32 @@ struct dm_pool *dmeventd_lvm2_pool(void)
|
|||||||
|
|
||||||
int dmeventd_lvm2_run(const char *cmdline)
|
int dmeventd_lvm2_run(const char *cmdline)
|
||||||
{
|
{
|
||||||
return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
|
return lvm2_run(_lvm_handle, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
||||||
const char *cmd, const char *device)
|
const char *cmd, const char *device)
|
||||||
{
|
{
|
||||||
static char _internal_prefix[] = "_dmeventd_";
|
|
||||||
char *vg = NULL, *lv = NULL, *layer;
|
char *vg = NULL, *lv = NULL, *layer;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
|
if (!dm_split_lvm_name(mem, device, &vg, &lv, &layer)) {
|
||||||
log_error("Unable to determine VG name from %s.",
|
syslog(LOG_ERR, "Unable to determine VG name from %s.\n",
|
||||||
device);
|
device);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strip off the mirror component designations */
|
/* strip off the mirror component designations */
|
||||||
if ((layer = strstr(lv, "_mimagetmp")) ||
|
layer = strstr(lv, "_mlog");
|
||||||
(layer = strstr(lv, "_mlog")))
|
if (layer)
|
||||||
*layer = '\0';
|
*layer = '\0';
|
||||||
|
|
||||||
if (!strncmp(cmd, _internal_prefix, sizeof(_internal_prefix) - 1)) {
|
|
||||||
dmeventd_lvm2_lock();
|
|
||||||
/* output of internal command passed via env var */
|
|
||||||
if (!dmeventd_lvm2_run(cmd))
|
|
||||||
cmd = NULL;
|
|
||||||
else if ((cmd = getenv(cmd)))
|
|
||||||
cmd = dm_pool_strdup(mem, cmd); /* copy with lock */
|
|
||||||
dmeventd_lvm2_unlock();
|
|
||||||
|
|
||||||
if (!cmd) {
|
|
||||||
log_error("Unable to find configured command.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
|
r = dm_snprintf(buffer, size, "%s %s/%s", cmd, vg, lv);
|
||||||
|
|
||||||
dm_pool_free(mem, vg);
|
dm_pool_free(mem, vg);
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("Unable to form LVM command. (too long).");
|
syslog(LOG_ERR, "Unable to form LVM command. (too long).\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -22,11 +22,11 @@
|
|||||||
* liblvm2cmd thread-safe so this can go away.
|
* liblvm2cmd thread-safe so this can go away.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
|
||||||
#ifndef _DMEVENTD_LVMWRAP_H
|
#ifndef _DMEVENTD_LVMWRAP_H
|
||||||
#define _DMEVENTD_LVMWRAP_H
|
#define _DMEVENTD_LVMWRAP_H
|
||||||
|
|
||||||
struct dm_pool;
|
|
||||||
|
|
||||||
int dmeventd_lvm2_init(void);
|
int dmeventd_lvm2_init(void);
|
||||||
void dmeventd_lvm2_exit(void);
|
void dmeventd_lvm2_exit(void);
|
||||||
int dmeventd_lvm2_run(const char *cmdline);
|
int dmeventd_lvm2_run(const char *cmdline);
|
||||||
@@ -39,36 +39,4 @@ struct dm_pool *dmeventd_lvm2_pool(void);
|
|||||||
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
||||||
const char *cmd, const char *device);
|
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 */
|
#endif /* _DMEVENTD_LVMWRAP_H */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
# Copyright (C) 2004-2005, 2008-2014 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2005, 2008-2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_mirror.c
|
SOURCES = dmeventd_mirror.c
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2005-2012 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,31 +9,28 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
#include "errors.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
#include "dmeventd_lvm.h"
|
#include "dmeventd_lvm.h"
|
||||||
#include "activate.h" /* For TARGET_NAME* */
|
#include "defaults.h"
|
||||||
|
|
||||||
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
|
/* FIXME Missing openlog? */
|
||||||
|
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||||
/* FIXME Reformat to 80 char lines. */
|
/* FIXME Reformat to 80 char lines. */
|
||||||
|
|
||||||
#define ME_IGNORE 0
|
#define ME_IGNORE 0
|
||||||
#define ME_INSYNC 1
|
#define ME_INSYNC 1
|
||||||
#define ME_FAILURE 2
|
#define ME_FAILURE 2
|
||||||
|
|
||||||
struct dso_state {
|
static int _process_status_code(const char status_code, const char *dev_name,
|
||||||
struct dm_pool *mem;
|
const char *dev_type, int r)
|
||||||
char cmd_lvscan[512];
|
|
||||||
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
|
* A => Alive - No failures
|
||||||
@@ -43,180 +40,196 @@ static void _process_status_code(dm_status_mirror_health_t health,
|
|||||||
* R => Read - A read failure occurred, mirror data unaffected
|
* R => Read - A read failure occurred, mirror data unaffected
|
||||||
* U => Unclassified failure (bug)
|
* U => Unclassified failure (bug)
|
||||||
*/
|
*/
|
||||||
switch (health) {
|
if (status_code == 'F') {
|
||||||
case DM_STATUS_MIRROR_ALIVE:
|
syslog(LOG_ERR, "%s device %s flush failed.",
|
||||||
return;
|
dev_type, dev_name);
|
||||||
case DM_STATUS_MIRROR_FLUSH_FAILED:
|
r = ME_FAILURE;
|
||||||
log_error("%s device %u:%u flush failed.",
|
} else if (status_code == 'S')
|
||||||
dev_type, major, minor);
|
syslog(LOG_ERR, "%s device %s sync failed.",
|
||||||
*r = ME_FAILURE;
|
dev_type, dev_name);
|
||||||
break;
|
else if (status_code == 'R')
|
||||||
case DM_STATUS_MIRROR_SYNC_FAILED:
|
syslog(LOG_ERR, "%s device %s read failed.",
|
||||||
log_error("%s device %u:%u sync failed.",
|
dev_type, dev_name);
|
||||||
dev_type, major, minor);
|
else if (status_code != 'A') {
|
||||||
break;
|
syslog(LOG_ERR, "%s device %s has failed (%c).",
|
||||||
case DM_STATUS_MIRROR_READ_FAILED:
|
dev_type, dev_name, status_code);
|
||||||
log_error("%s device %u:%u read failed.",
|
r = ME_FAILURE;
|
||||||
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert,
|
static int _get_mirror_event(char *params)
|
||||||
const char *device)
|
|
||||||
{
|
{
|
||||||
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
|
int i, r = ME_INSYNC;
|
||||||
log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
|
char **args = NULL;
|
||||||
|
char *dev_status_str;
|
||||||
|
char *log_status_str;
|
||||||
|
char *sync_str;
|
||||||
|
char *p = NULL;
|
||||||
|
int log_argc, num_devs;
|
||||||
|
|
||||||
/* if repair goes OK, report success even if lvscan has failed */
|
/*
|
||||||
if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
|
* dm core parms: 0 409600 mirror
|
||||||
log_error("Repair of mirrored device %s failed.", device);
|
* Mirror core parms: 2 253:4 253:5 400/400
|
||||||
return 0;
|
* New-style failure params: 1 AA
|
||||||
}
|
* New-style log params: 3 cluster 253:3 A
|
||||||
|
* or 3 disk 253:3 A
|
||||||
|
* or 1 core
|
||||||
|
*/
|
||||||
|
|
||||||
log_info("Repair of mirrored device %s finished successfully.", device);
|
/* number of devices */
|
||||||
|
if (!dm_split_words(params, 1, 0, &p))
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
return 1;
|
if (!(num_devs = atoi(p)) ||
|
||||||
|
(num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0))
|
||||||
|
goto out_parse;
|
||||||
|
p += strlen(p) + 1;
|
||||||
|
|
||||||
|
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||||
|
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||||
|
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
/* FIXME: Code differs from lib/mirror/mirrored.c */
|
||||||
|
dev_status_str = args[2 + num_devs];
|
||||||
|
log_argc = atoi(args[3 + num_devs]);
|
||||||
|
log_status_str = args[3 + num_devs + log_argc];
|
||||||
|
sync_str = args[num_devs];
|
||||||
|
|
||||||
|
/* Check for bad mirror devices */
|
||||||
|
for (i = 0; i < num_devs; i++)
|
||||||
|
r = _process_status_code(dev_status_str[i], args[i],
|
||||||
|
i ? "Secondary mirror" : "Primary mirror", r);
|
||||||
|
|
||||||
|
/* Check for bad disk log device */
|
||||||
|
if (log_argc > 1)
|
||||||
|
r = _process_status_code(log_status_str[0],
|
||||||
|
args[2 + num_devs + log_argc],
|
||||||
|
"Log", r);
|
||||||
|
|
||||||
|
if (r == ME_FAILURE)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
p = strstr(sync_str, "/");
|
||||||
|
if (p) {
|
||||||
|
p[0] = '\0';
|
||||||
|
if (strcmp(sync_str, p+1))
|
||||||
|
r = ME_IGNORE;
|
||||||
|
p[0] = '/';
|
||||||
|
} else
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
out:
|
||||||
|
dm_free(args);
|
||||||
|
return r;
|
||||||
|
|
||||||
|
out_parse:
|
||||||
|
dm_free(args);
|
||||||
|
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||||
|
return ME_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _remove_failed_devices(const char *device)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||||
|
char cmd_str[CMD_SIZE];
|
||||||
|
|
||||||
|
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
|
||||||
|
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||||
|
"--repair --use-policies", device))
|
||||||
|
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||||
|
|
||||||
|
r = dmeventd_lvm2_run(cmd_str);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Repair of mirrored device %s %s.", device,
|
||||||
|
(r == ECMD_PROCESSED) ? "finished successfully" : "failed");
|
||||||
|
|
||||||
|
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_event(struct dm_task *dmt,
|
void process_event(struct dm_task *dmt,
|
||||||
enum dm_event_mask event __attribute__((unused)),
|
enum dm_event_mask event __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
|
||||||
void *next = NULL;
|
void *next = NULL;
|
||||||
uint64_t start, length;
|
uint64_t start, length;
|
||||||
char *target_type = NULL;
|
char *target_type = NULL;
|
||||||
char *params;
|
char *params;
|
||||||
const char *device = dm_task_get_name(dmt);
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
|
||||||
|
dmeventd_lvm2_lock();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
next = dm_get_next_target(dmt, next, &start, &length,
|
next = dm_get_next_target(dmt, next, &start, &length,
|
||||||
&target_type, ¶ms);
|
&target_type, ¶ms);
|
||||||
|
|
||||||
if (!target_type) {
|
if (!target_type) {
|
||||||
log_info("%s mapping lost.", device);
|
syslog(LOG_INFO, "%s mapping lost.", device);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(target_type, TARGET_NAME_MIRROR)) {
|
if (strcmp(target_type, "mirror")) {
|
||||||
log_info("%s has unmirrored portion.", device);
|
syslog(LOG_INFO, "%s has unmirrored portion.", device);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(_get_mirror_event(state, params)) {
|
switch(_get_mirror_event(params)) {
|
||||||
case ME_INSYNC:
|
case ME_INSYNC:
|
||||||
/* FIXME: all we really know is that this
|
/* FIXME: all we really know is that this
|
||||||
_part_ of the device is in sync
|
_part_ of the device is in sync
|
||||||
Also, this is not an error
|
Also, this is not an error
|
||||||
*/
|
*/
|
||||||
log_notice("%s is now in-sync.", device);
|
syslog(LOG_NOTICE, "%s is now in-sync.", device);
|
||||||
break;
|
break;
|
||||||
case ME_FAILURE:
|
case ME_FAILURE:
|
||||||
log_error("Device failure in %s.", device);
|
syslog(LOG_ERR, "Device failure in %s.", device);
|
||||||
if (!_remove_failed_devices(state->cmd_lvscan,
|
if (_remove_failed_devices(device))
|
||||||
state->cmd_lvconvert,
|
|
||||||
device))
|
|
||||||
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||||
log_error("Failed to remove faulty devices in %s.",
|
syslog(LOG_ERR, "Failed to remove faulty devices in %s.",
|
||||||
device);
|
device);
|
||||||
/* Should check before warning user that device is now linear
|
/* Should check before warning user that device is now linear
|
||||||
else
|
else
|
||||||
log_notice("%s is now a linear device.",
|
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||||
device);
|
device);
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case ME_IGNORE:
|
case ME_IGNORE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME Provide value then! */
|
/* FIXME Provide value then! */
|
||||||
log_warn("WARNING: %s received unknown event.", device);
|
syslog(LOG_INFO, "Unknown event received.");
|
||||||
}
|
}
|
||||||
} while (next);
|
} while (next);
|
||||||
|
|
||||||
|
dmeventd_lvm2_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int register_device(const char *device,
|
int register_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state;
|
if (!dmeventd_lvm2_init())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!dmeventd_lvm2_init_with_pool("mirror_state", state))
|
syslog(LOG_INFO, "Monitoring mirror device %s for events.", device);
|
||||||
goto_bad;
|
|
||||||
|
|
||||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
|
|
||||||
"lvscan --cache", device)) {
|
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
|
||||||
"lvconvert --repair --use-policies", device)) {
|
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
*user = state;
|
|
||||||
|
|
||||||
log_info("Monitoring mirror device %s for events.", device);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
|
||||||
log_error("Failed to monitor mirror %s.", device);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int unregister_device(const char *device,
|
int unregister_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
syslog(LOG_INFO, "No longer monitoring mirror device %s for events.",
|
||||||
|
device);
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
dmeventd_lvm2_exit();
|
||||||
log_info("No longer monitoring mirror device %s for events.",
|
|
||||||
device);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -9,14 +9,14 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_raid.c
|
SOURCES = dmeventd_raid.c
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,164 +9,164 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "defaults.h"
|
|
||||||
#include "dmeventd_lvm.h"
|
#include "lvm2cmd.h"
|
||||||
|
#include "errors.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
|
#include "dmeventd_lvm.h"
|
||||||
|
|
||||||
/* Hold enough elements for the mximum number of RAID images */
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
|
/* FIXME Missing openlog? */
|
||||||
|
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||||
struct dso_state {
|
|
||||||
struct dm_pool *mem;
|
|
||||||
char cmd_lvscan[512];
|
|
||||||
char cmd_lvconvert[512];
|
|
||||||
uint64_t raid_devs[RAID_DEVS_ELEMS];
|
|
||||||
int failed;
|
|
||||||
int warned;
|
|
||||||
};
|
|
||||||
|
|
||||||
DM_EVENT_LOG_FN("raid")
|
|
||||||
|
|
||||||
/* FIXME Reformat to 80 char lines. */
|
/* FIXME Reformat to 80 char lines. */
|
||||||
|
|
||||||
static int _process_raid_event(struct dso_state *state, char *params, const char *device)
|
/*
|
||||||
|
* run_repair is a close copy to
|
||||||
|
* plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
|
||||||
|
*/
|
||||||
|
static int run_repair(const char *device)
|
||||||
{
|
{
|
||||||
struct dm_status_raid *status;
|
int r;
|
||||||
const char *d;
|
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||||
int dead = 0, r = 1;
|
char cmd_str[CMD_SIZE];
|
||||||
uint32_t dev;
|
|
||||||
|
|
||||||
if (!dm_get_status_raid(state->mem, params, &status)) {
|
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
|
||||||
log_error("Failed to process status line for %s.", device);
|
"lvconvert --config devices{ignore_suspended_devices=1} "
|
||||||
return 0;
|
"--repair --use-policies", device))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
r = dmeventd_lvm2_run(cmd_str);
|
||||||
|
|
||||||
|
if (r != ECMD_PROCESSED)
|
||||||
|
syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
|
||||||
|
|
||||||
|
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _process_raid_event(char *params, const char *device)
|
||||||
|
{
|
||||||
|
int i, n, failure = 0;
|
||||||
|
char *p, *a[4];
|
||||||
|
char *raid_type;
|
||||||
|
char *num_devices;
|
||||||
|
char *health_chars;
|
||||||
|
char *resync_ratio;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RAID parms: <raid_type> <#raid_disks> \
|
||||||
|
* <health chars> <resync ratio>
|
||||||
|
*/
|
||||||
|
if (!dm_split_words(params, 4, 0, a)) {
|
||||||
|
syslog(LOG_ERR, "Failed to process status line for %s\n",
|
||||||
|
device);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
raid_type = a[0];
|
||||||
|
num_devices = a[1];
|
||||||
|
health_chars = a[2];
|
||||||
|
resync_ratio = a[3];
|
||||||
|
|
||||||
|
if (!(n = atoi(num_devices))) {
|
||||||
|
syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
|
||||||
|
device, num_devices);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = status->dev_health;
|
for (i = 0; i < n; i++) {
|
||||||
while ((d = strchr(d, 'D'))) {
|
switch (health_chars[i]) {
|
||||||
dev = (uint32_t)(d - status->dev_health);
|
case 'A':
|
||||||
|
/* Device is 'A'live and well */
|
||||||
if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64)))) {
|
case 'a':
|
||||||
state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64));
|
/* Device is 'a'live, but not yet in-sync */
|
||||||
log_warn("WARNING: Device #%u of %s array, %s, has failed.",
|
break;
|
||||||
dev, status->raid_type, device);
|
case 'D':
|
||||||
|
syslog(LOG_ERR,
|
||||||
|
"Device #%d of %s array, %s, has failed.",
|
||||||
|
i, raid_type, device);
|
||||||
|
failure++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unhandled character returned from kernel */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (failure)
|
||||||
d++;
|
return run_repair(device);
|
||||||
dead = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dead) {
|
p = strstr(resync_ratio, "/");
|
||||||
if (status->insync_regions < status->total_regions) {
|
if (!p) {
|
||||||
if (!state->warned) {
|
syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
|
||||||
state->warned = 1;
|
device, resync_ratio);
|
||||||
log_warn("WARNING: waiting for resynchronization to finish "
|
return -EINVAL;
|
||||||
"before initiating repair on RAID device %s.", device);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto out; /* Not yet done syncing with accessible devices */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->failed)
|
|
||||||
goto out; /* already reported */
|
|
||||||
|
|
||||||
state->failed = 1;
|
|
||||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
|
|
||||||
log_warn("WARNING: Re-scan of RAID device %s failed.", device);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
log_info("%s array, %s, is %s in-sync.",
|
|
||||||
status->raid_type, device,
|
|
||||||
(status->insync_regions == status->total_regions) ? "now" : "not");
|
|
||||||
}
|
}
|
||||||
out:
|
p[0] = '\0';
|
||||||
dm_pool_free(state->mem, status);
|
syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
|
||||||
|
raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
|
||||||
|
|
||||||
return r;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_event(struct dm_task *dmt,
|
void process_event(struct dm_task *dmt,
|
||||||
enum dm_event_mask event __attribute__((unused)),
|
enum dm_event_mask event __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
|
||||||
void *next = NULL;
|
void *next = NULL;
|
||||||
uint64_t start, length;
|
uint64_t start, length;
|
||||||
char *target_type = NULL;
|
char *target_type = NULL;
|
||||||
char *params;
|
char *params;
|
||||||
const char *device = dm_task_get_name(dmt);
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
|
||||||
|
dmeventd_lvm2_lock();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
next = dm_get_next_target(dmt, next, &start, &length,
|
next = dm_get_next_target(dmt, next, &start, &length,
|
||||||
&target_type, ¶ms);
|
&target_type, ¶ms);
|
||||||
|
|
||||||
if (!target_type) {
|
if (!target_type) {
|
||||||
log_info("%s mapping lost.", device);
|
syslog(LOG_INFO, "%s mapping lost.", device);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(target_type, "raid")) {
|
if (strcmp(target_type, "raid")) {
|
||||||
log_info("%s has non-raid portion.", device);
|
syslog(LOG_INFO, "%s has non-raid portion.", device);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_process_raid_event(state, params, device))
|
if (_process_raid_event(params, device))
|
||||||
log_error("Failed to process event for %s.",
|
syslog(LOG_ERR, "Failed to process event for %s",
|
||||||
device);
|
device);
|
||||||
} while (next);
|
} while (next);
|
||||||
|
|
||||||
|
dmeventd_lvm2_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int register_device(const char *device,
|
int register_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state;
|
if (!dmeventd_lvm2_init())
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!dmeventd_lvm2_init_with_pool("raid_state", state))
|
syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
|
||||||
goto_bad;
|
|
||||||
|
|
||||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan),
|
|
||||||
"lvscan --cache", device) ||
|
|
||||||
!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert),
|
|
||||||
"lvconvert --config devices{ignore_suspended_devices=1} "
|
|
||||||
"--repair --use-policies", device)) {
|
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
*user = state;
|
|
||||||
|
|
||||||
log_info("Monitoring RAID device %s for events.", device);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
|
||||||
log_error("Failed to monitor RAID %s.", device);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int unregister_device(const char *device,
|
int unregister_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **unused __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
|
||||||
|
device);
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
dmeventd_lvm2_exit();
|
||||||
log_info("No longer monitoring RAID device %s for events.",
|
|
||||||
device);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
# Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of the LVM2.
|
# This file is part of the LVM2.
|
||||||
#
|
#
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_snapshot.c
|
SOURCES = dmeventd_snapshot.c
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ LIB_VERSION = $(LIB_VERSION_LVM)
|
|||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
include $(top_builddir)/make.tmpl
|
||||||
|
|
||||||
LIBS += -ldevmapper-event-lvm2 -ldevmapper
|
LIBS += -ldevmapper-event-lvm2 -ldevmapper $(DAEMON_LIBS)
|
||||||
|
|
||||||
install_lvm2: install_dm_plugin
|
install_lvm2: install_dm_plugin
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2015 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2007-2011 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,36 +9,36 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
|
||||||
#include "libdevmapper-event.h"
|
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
#include "lvm2cmd.h"
|
||||||
|
#include "errors.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
#include "dmeventd_lvm.h"
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdarg.h>
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
#include <pthread.h>
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
/* First warning when snapshot is 80% full. */
|
/* First warning when snapshot is 80% full. */
|
||||||
#define WARNING_THRESH (DM_PERCENT_1 * 80)
|
#define WARNING_THRESH 80
|
||||||
/* Run a check every 5%. */
|
/* Run a check every 5%. */
|
||||||
#define CHECK_STEP (DM_PERCENT_1 * 5)
|
#define CHECK_STEP 5
|
||||||
/* Do not bother checking snapshots less than 50% full. */
|
/* Do not bother checking snapshots less than 50% full. */
|
||||||
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
|
#define CHECK_MINIMUM 50
|
||||||
|
|
||||||
#define UMOUNT_COMMAND "/bin/umount"
|
#define UMOUNT_COMMAND "/bin/umount"
|
||||||
|
|
||||||
struct dso_state {
|
struct dso_state {
|
||||||
struct dm_pool *mem;
|
struct dm_pool *mem;
|
||||||
dm_percent_t percent_check;
|
int percent_check;
|
||||||
uint64_t known_size;
|
uint64_t known_size;
|
||||||
char cmd_lvextend[512];
|
char cmd_str[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
DM_EVENT_LOG_FN("snap")
|
|
||||||
|
|
||||||
static int _run(const char *cmd, ...)
|
static int _run(const char *cmd, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -63,7 +63,7 @@ static int _run(const char *cmd, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
execvp(cmd, (char **)argv);
|
execvp(cmd, (char **)argv);
|
||||||
log_sys_error("exec", cmd);
|
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
|
||||||
exit(127);
|
exit(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,56 +82,18 @@ static int _run(const char *cmd, ...)
|
|||||||
|
|
||||||
static int _extend(const char *cmd)
|
static int _extend(const char *cmd)
|
||||||
{
|
{
|
||||||
log_debug("Extending snapshot via %s.", cmd);
|
return dmeventd_lvm2_run(cmd) == ECMD_PROCESSED;
|
||||||
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)
|
static void _umount(const char *device, int major, int minor)
|
||||||
{
|
{
|
||||||
FILE *mounts;
|
FILE *mounts;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
char *words[3];
|
char *words[3];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char procmounts[] = "/proc/mounts";
|
|
||||||
|
|
||||||
if (!(mounts = fopen(procmounts, "r"))) {
|
if (!(mounts = fopen("/proc/mounts", "r"))) {
|
||||||
log_sys_error("fopen", procmounts);
|
syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
|
||||||
log_error("Not umounting %s.", device);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,24 +111,23 @@ static void _umount(const char *device, int major, int minor)
|
|||||||
continue; /* can't stat, skip this one */
|
continue; /* can't stat, skip this one */
|
||||||
|
|
||||||
if (S_ISBLK(st.st_mode) &&
|
if (S_ISBLK(st.st_mode) &&
|
||||||
(int) major(st.st_rdev) == major &&
|
major(st.st_rdev) == major &&
|
||||||
(int) minor(st.st_rdev) == minor) {
|
minor(st.st_rdev) == minor) {
|
||||||
log_error("Unmounting invalid snapshot %s from %s.", device, words[1]);
|
syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.\n", device, words[1]);
|
||||||
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
|
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
|
||||||
log_error("Failed to umount snapshot %s from %s: %s.",
|
syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.\n",
|
||||||
device, words[1], strerror(errno));
|
device, words[1], strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fclose(mounts))
|
if (fclose(mounts))
|
||||||
log_sys_error("close", procmounts);
|
syslog(LOG_ERR, "Failed to close /proc/mounts.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_event(struct dm_task *dmt,
|
void process_event(struct dm_task *dmt,
|
||||||
enum dm_event_mask event __attribute__((unused)),
|
enum dm_event_mask event __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
|
||||||
void *next = NULL;
|
void *next = NULL;
|
||||||
uint64_t start, length;
|
uint64_t start, length;
|
||||||
char *target_type = NULL;
|
char *target_type = NULL;
|
||||||
@@ -174,47 +135,28 @@ void process_event(struct dm_task *dmt,
|
|||||||
struct dm_status_snapshot *status = NULL;
|
struct dm_status_snapshot *status = NULL;
|
||||||
const char *device = dm_task_get_name(dmt);
|
const char *device = dm_task_get_name(dmt);
|
||||||
int percent;
|
int percent;
|
||||||
struct dm_info info;
|
struct dso_state *state = *private;
|
||||||
|
|
||||||
/* No longer monitoring, waiting for remove */
|
/* No longer monitoring, waiting for remove */
|
||||||
if (!state->percent_check)
|
if (!state->percent_check)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dmeventd_lvm2_lock();
|
||||||
|
|
||||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||||
if (!target_type || strcmp(target_type, "snapshot")) {
|
if (!target_type)
|
||||||
log_error("Target %s is not snapshot.", target_type);
|
goto out;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dm_get_status_snapshot(state->mem, params, &status)) {
|
if (!dm_get_status_snapshot(state->mem, params, &status))
|
||||||
log_error("Cannot parse snapshot %s state: %s.", device, params);
|
goto out;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (status->invalid) {
|
||||||
* If the snapshot has been invalidated or we failed to parse
|
struct dm_info info;
|
||||||
* the status string. Report the full status string to syslog.
|
if (dm_task_get_info(dmt, &info)) {
|
||||||
*/
|
dmeventd_lvm2_unlock();
|
||||||
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);
|
_umount(device, info.major, info.minor);
|
||||||
#ifdef SNAPSHOT_REMOVE
|
return;
|
||||||
/* Maybe configurable ? */
|
} /* else; too bad, but this is best-effort thing... */
|
||||||
_remove(dm_task_get_uuid(dmt));
|
|
||||||
#endif
|
|
||||||
pthread_kill(pthread_self(), SIGALRM);
|
|
||||||
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);
|
|
||||||
pthread_kill(pthread_self(), SIGALRM);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Snapshot size had changed. Clear the threshold. */
|
/* Snapshot size had changed. Clear the threshold. */
|
||||||
@@ -223,50 +165,69 @@ void process_event(struct dm_task *dmt,
|
|||||||
state->known_size = status->total_sectors;
|
state->known_size = status->total_sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
percent = dm_make_percent(status->used_sectors, status->total_sectors);
|
/*
|
||||||
|
* If the snapshot has been invalidated or we failed to parse
|
||||||
|
* the status string. Report the full status string to syslog.
|
||||||
|
*/
|
||||||
|
if (status->invalid || !status->total_sectors) {
|
||||||
|
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||||
|
state->percent_check = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
percent = (int) (100 * status->used_sectors / status->total_sectors);
|
||||||
if (percent >= state->percent_check) {
|
if (percent >= state->percent_check) {
|
||||||
/* Usage has raised more than CHECK_STEP since the last
|
/* Usage has raised more than CHECK_STEP since the last
|
||||||
time. Run actions. */
|
time. Run actions. */
|
||||||
state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
state->percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||||
|
|
||||||
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||||
log_warn("WARNING: Snapshot %s is now %.2f%% full.",
|
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
|
||||||
device, dm_percent_to_float(percent));
|
|
||||||
|
|
||||||
/* Try to extend the snapshot, in accord with user-set policies */
|
/* Try to extend the snapshot, in accord with user-set policies */
|
||||||
if (!_extend(state->cmd_lvextend))
|
if (!_extend(state->cmd_str))
|
||||||
log_error("Failed to extend snapshot %s.", device);
|
syslog(LOG_ERR, "Failed to extend snapshot %s.\n", device);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dm_pool_free(state->mem, status);
|
if (status)
|
||||||
|
dm_pool_free(state->mem, status);
|
||||||
|
dmeventd_lvm2_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
int register_device(const char *device,
|
int register_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
|
struct dm_pool *statemem = NULL;
|
||||||
struct dso_state *state;
|
struct dso_state *state;
|
||||||
|
|
||||||
if (!dmeventd_lvm2_init_with_pool("snapshot_state", state))
|
if (!dmeventd_lvm2_init())
|
||||||
goto_bad;
|
goto out;
|
||||||
|
|
||||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend,
|
if (!(statemem = dm_pool_create("snapshot_state", 512)) ||
|
||||||
sizeof(state->cmd_lvextend),
|
!(state = dm_pool_zalloc(statemem, sizeof(*state))))
|
||||||
"lvextend --use-policies", device)) {
|
goto bad;
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
|
||||||
goto_bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!dmeventd_lvm2_command(statemem, state->cmd_str,
|
||||||
|
sizeof(state->cmd_str),
|
||||||
|
"lvextend --use-policies", device))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
state->mem = statemem;
|
||||||
state->percent_check = CHECK_MINIMUM;
|
state->percent_check = CHECK_MINIMUM;
|
||||||
*user = state;
|
*private = state;
|
||||||
|
|
||||||
log_info("Monitoring snapshot %s.", device);
|
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
bad:
|
||||||
log_error("Failed to monitor snapshot %s.", device);
|
if (statemem)
|
||||||
|
dm_pool_destroy(statemem);
|
||||||
|
dmeventd_lvm2_exit();
|
||||||
|
out:
|
||||||
|
syslog(LOG_ERR, "Failed to monitor snapshot %s.\n", device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -275,12 +236,13 @@ int unregister_device(const char *device,
|
|||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
struct dso_state *state = *private;
|
||||||
|
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
syslog(LOG_INFO, "No longer monitoring snapshot %s\n", device);
|
||||||
log_info("No longer monitoring snapshot %s.", device);
|
dm_pool_destroy(state->mem);
|
||||||
|
dmeventd_lvm2_exit();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2011-2014 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2011 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of LVM2.
|
# This file is part of LVM2.
|
||||||
#
|
#
|
||||||
@@ -9,14 +9,14 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
|
|
||||||
INCLUDES += -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||||
CLDFLAGS += -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2
|
||||||
|
|
||||||
SOURCES = dmeventd_thin.c
|
SOURCES = dmeventd_thin.c
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2017 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -9,387 +9,378 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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,
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h" /* using here lvm log */
|
#include "lib.h"
|
||||||
#include "dmeventd_lvm.h"
|
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
#include "errors.h"
|
||||||
#include "libdevmapper-event.h"
|
#include "libdevmapper-event.h"
|
||||||
|
#include "dmeventd_lvm.h"
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdarg.h>
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
#include <pthread.h>
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
/* TODO - move this mountinfo code into library to be reusable */
|
/* First warning when thin is 80% full. */
|
||||||
#ifdef __linux__
|
#define WARNING_THRESH 80
|
||||||
# include "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%. */
|
/* Run a check every 5%. */
|
||||||
#define CHECK_STEP (DM_PERCENT_1 * 5)
|
#define CHECK_STEP 5
|
||||||
/* Do not bother checking thin data or metadata is less than 50% full. */
|
/* Do not bother checking thins less than 50% full. */
|
||||||
#define CHECK_MINIMUM (DM_PERCENT_1 * 50)
|
#define CHECK_MINIMUM 50
|
||||||
|
|
||||||
#define UMOUNT_COMMAND "/bin/umount"
|
#define UMOUNT_COMMAND "/bin/umount"
|
||||||
|
|
||||||
#define MAX_FAILS (256) /* ~42 mins between cmd call retry with 10s delay */
|
|
||||||
|
|
||||||
#define THIN_DEBUG 0
|
#define THIN_DEBUG 0
|
||||||
|
|
||||||
struct dso_state {
|
struct dso_state {
|
||||||
struct dm_pool *mem;
|
struct dm_pool *mem;
|
||||||
int metadata_percent_check;
|
int metadata_percent_check;
|
||||||
int metadata_percent;
|
|
||||||
int metadata_warn_once;
|
|
||||||
int data_percent_check;
|
int data_percent_check;
|
||||||
int data_percent;
|
|
||||||
int data_warn_once;
|
|
||||||
uint64_t known_metadata_size;
|
uint64_t known_metadata_size;
|
||||||
uint64_t known_data_size;
|
uint64_t known_data_size;
|
||||||
unsigned fails;
|
|
||||||
unsigned max_fails;
|
|
||||||
int restore_sigset;
|
|
||||||
sigset_t old_sigset;
|
|
||||||
pid_t pid;
|
|
||||||
char **argv;
|
|
||||||
char cmd_str[1024];
|
char cmd_str[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
DM_EVENT_LOG_FN("thin")
|
|
||||||
|
|
||||||
#define UUID_PREFIX "LVM-"
|
/* TODO - move this mountinfo code into library to be reusable */
|
||||||
|
#ifdef linux
|
||||||
|
# include "kdev_t.h"
|
||||||
|
#else
|
||||||
|
# define MAJOR(x) major((x))
|
||||||
|
# define MINOR(x) minor((x))
|
||||||
|
# define MKDEV(x,y) makedev((x),(y))
|
||||||
|
#endif
|
||||||
|
|
||||||
static int _run_command(struct dso_state *state)
|
/* Get dependencies for device, and try to find matching device */
|
||||||
|
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
|
||||||
{
|
{
|
||||||
char val[3][36];
|
struct dm_task *dmt;
|
||||||
char *env[] = { val[0], val[1], val[2], NULL };
|
const struct dm_deps *deps;
|
||||||
int i;
|
struct dm_info info;
|
||||||
|
int major, minor;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
/* Mark for possible lvm2 command we are running from dmeventd
|
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
|
||||||
* lvm2 will not try to talk back to dmeventd while processing it */
|
|
||||||
(void) dm_snprintf(val[0], sizeof(val[0]), "LVM_RUN_BY_DMEVENTD=1");
|
|
||||||
|
|
||||||
if (state->data_percent) {
|
|
||||||
/* Prepare some known data to env vars for easy use */
|
|
||||||
(void) dm_snprintf(val[1], sizeof(val[1]), "DMEVENTD_THIN_POOL_DATA=%d",
|
|
||||||
state->data_percent / DM_PERCENT_1);
|
|
||||||
(void) dm_snprintf(val[2], sizeof(val[2]), "DMEVENTD_THIN_POOL_METADATA=%d",
|
|
||||||
state->metadata_percent / DM_PERCENT_1);
|
|
||||||
} else {
|
|
||||||
/* For an error event it's for a user to check status and decide */
|
|
||||||
env[1] = NULL;
|
|
||||||
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);
|
|
||||||
execve(state->argv[0], state->argv, env);
|
|
||||||
_exit(errno);
|
|
||||||
} else if (state->pid == -1) {
|
|
||||||
log_error("Can't fork command %s.", state->cmd_str);
|
|
||||||
state->fails = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
if (!dm_task_set_name(dmt, name))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!dm_task_no_open_count(dmt))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!dm_task_run(dmt))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!dm_task_get_info(dmt, &info))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!(deps = dm_task_get_deps(dmt)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!info.exists || deps->count != 1)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
major = (int) MAJOR(deps->device[0]);
|
||||||
|
minor = (int) MINOR(deps->device[0]);
|
||||||
|
if ((major != tp_major) || (minor != tp_minor))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*dev_minor = info.minor;
|
||||||
|
|
||||||
|
#if THIN_DEBUG
|
||||||
|
{
|
||||||
|
char dev_name[PATH_MAX];
|
||||||
|
if (dm_device_get_name(major, minor, 0, dev_name, sizeof(dev_name)))
|
||||||
|
syslog(LOG_DEBUG, "Found %s (%u:%u) depends on %s",
|
||||||
|
name, major, *dev_minor, dev_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
r = 1;
|
||||||
|
out:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _use_policy(struct dm_task *dmt, struct dso_state *state)
|
/* Get all active devices */
|
||||||
|
static int _find_all_devs(dm_bitset_t bs, int tp_major, int tp_minor)
|
||||||
|
{
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_names *names;
|
||||||
|
unsigned next = 0;
|
||||||
|
int minor, r = 1;
|
||||||
|
|
||||||
|
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dm_task_run(dmt)) {
|
||||||
|
r = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(names = dm_task_get_names(dmt))) {
|
||||||
|
r = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!names->dev)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
do {
|
||||||
|
names = (struct dm_names *)((char *) names + next);
|
||||||
|
if (_has_deps(names->name, tp_major, tp_minor, &minor))
|
||||||
|
dm_bit_set(bs, minor);
|
||||||
|
next = names->next;
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
out:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _extend(struct dso_state *state)
|
||||||
{
|
{
|
||||||
#if THIN_DEBUG
|
#if THIN_DEBUG
|
||||||
log_debug("dmeventd executes: %s.", state->cmd_str);
|
syslog(LOG_INFO, "dmeventd executes: %s.\n", state->cmd_str);
|
||||||
#endif
|
#endif
|
||||||
if (state->argv)
|
return (dmeventd_lvm2_run(state->cmd_str) == ECMD_PROCESSED);
|
||||||
return _run_command(state);
|
}
|
||||||
|
|
||||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
|
static int _run(const char *cmd, ...)
|
||||||
log_error("Failed command for %s.", dm_task_get_name(dmt));
|
{
|
||||||
state->fails = 1;
|
va_list ap;
|
||||||
return 0;
|
int argc = 1; /* for argv[0], i.e. cmd */
|
||||||
|
int i = 0;
|
||||||
|
const char **argv;
|
||||||
|
pid_t pid = fork();
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (pid == 0) { /* child */
|
||||||
|
va_start(ap, cmd);
|
||||||
|
while (va_arg(ap, const char *))
|
||||||
|
++argc;
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* + 1 for the terminating NULL */
|
||||||
|
argv = alloca(sizeof(const char *) * (argc + 1));
|
||||||
|
|
||||||
|
argv[0] = cmd;
|
||||||
|
va_start(ap, cmd);
|
||||||
|
while ((argv[++i] = va_arg(ap, const char *)));
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
execvp(cmd, (char **)argv);
|
||||||
|
syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
|
||||||
|
exit(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->fails = 0;
|
if (pid > 0) { /* parent */
|
||||||
|
if (waitpid(pid, &status, 0) != pid)
|
||||||
|
return 0; /* waitpid failed */
|
||||||
|
if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||||
|
return 0; /* the child failed */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid < 0)
|
||||||
|
return 0; /* fork failed */
|
||||||
|
|
||||||
|
return 1; /* all good */
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mountinfo_s {
|
||||||
|
struct dm_info info;
|
||||||
|
dm_bitset_t minors; /* Bitset for active thin pool minors */
|
||||||
|
const char *device;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _umount_device(char *buffer, unsigned major, unsigned minor,
|
||||||
|
char *target, void *cb_data)
|
||||||
|
{
|
||||||
|
struct mountinfo_s *data = cb_data;
|
||||||
|
|
||||||
|
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
|
||||||
|
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
|
||||||
|
data->device, target);
|
||||||
|
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
|
||||||
|
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
|
||||||
|
data->device, target, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if executed command has finished
|
/*
|
||||||
* Only 1 command may run */
|
* Find all thin pool users and try to umount them.
|
||||||
static int _wait_for_pid(struct dso_state *state)
|
* TODO: work with read-only thin pool support
|
||||||
|
*/
|
||||||
|
static void _umount(struct dm_task *dmt, const char *device)
|
||||||
{
|
{
|
||||||
int status = 0;
|
static const size_t MINORS = 4096;
|
||||||
|
struct mountinfo_s data = {
|
||||||
|
.device = device,
|
||||||
|
};
|
||||||
|
|
||||||
if (state->pid == -1)
|
if (!dm_task_get_info(dmt, &data.info))
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
if (!waitpid(state->pid, &status, WNOHANG))
|
dmeventd_lvm2_unlock();
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Wait for finish */
|
if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
|
||||||
if (WIFEXITED(status)) {
|
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
|
||||||
log_verbose("Child %d exited with status %d.",
|
goto out;
|
||||||
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;
|
if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
|
||||||
|
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
if (!dm_mountinfo_read(_umount_device, &data)) {
|
||||||
|
syslog(LOG_ERR, "Could not parse mountinfo file.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (data.minors)
|
||||||
|
dm_bitset_destroy(data.minors);
|
||||||
|
dmeventd_lvm2_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_event(struct dm_task *dmt,
|
void process_event(struct dm_task *dmt,
|
||||||
enum dm_event_mask event __attribute__((unused)),
|
enum dm_event_mask event __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
const char *device = dm_task_get_name(dmt);
|
const char *device = dm_task_get_name(dmt);
|
||||||
struct dso_state *state = *user;
|
int percent;
|
||||||
|
struct dso_state *state = *private;
|
||||||
struct dm_status_thin_pool *tps = NULL;
|
struct dm_status_thin_pool *tps = NULL;
|
||||||
void *next = NULL;
|
void *next = NULL;
|
||||||
uint64_t start, length;
|
uint64_t start, length;
|
||||||
char *target_type = NULL;
|
char *target_type = NULL;
|
||||||
char *params;
|
char *params;
|
||||||
int needs_policy = 0;
|
|
||||||
struct dm_task *new_dmt = NULL;
|
|
||||||
|
|
||||||
#if THIN_DEBUG
|
#if 0
|
||||||
log_debug("Watch for tp-data:%.2f%% tp-metadata:%.2f%%.",
|
/* No longer monitoring, waiting for remove */
|
||||||
dm_percent_to_float(state->data_percent_check),
|
if (!state->meta_percent_check && !state->data_percent_check)
|
||||||
dm_percent_to_float(state->metadata_percent_check));
|
|
||||||
#endif
|
|
||||||
if (!_wait_for_pid(state)) {
|
|
||||||
log_warn("WARNING: Skipping event, child %d is still running (%s).",
|
|
||||||
state->pid, state->cmd_str);
|
|
||||||
return;
|
return;
|
||||||
}
|
#endif
|
||||||
|
dmeventd_lvm2_lock();
|
||||||
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, ¶ms);
|
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||||
|
|
||||||
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
|
if (!target_type || (strcmp(target_type, "thin-pool") != 0)) {
|
||||||
log_error("Invalid target type.");
|
syslog(LOG_ERR, "Invalid target type.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
|
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
|
||||||
log_error("Failed to parse status.");
|
syslog(LOG_ERR, "Failed to parse status.\n");
|
||||||
|
_umount(dmt, device);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if THIN_DEBUG
|
#if THIN_DEBUG
|
||||||
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
|
syslog(LOG_INFO, "%p: Got status %" PRIu64 " / %" PRIu64
|
||||||
FMTu64 "/" FMTu64 ".",
|
" %" PRIu64 " / %" PRIu64 ".\n", state,
|
||||||
tps->used_metadata_blocks, tps->total_metadata_blocks,
|
tps->used_metadata_blocks, tps->total_metadata_blocks,
|
||||||
tps->used_data_blocks, tps->total_data_blocks);
|
tps->used_data_blocks, tps->total_data_blocks);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Thin pool size had changed. Clear the threshold. */
|
/* Thin pool size had changed. Clear the threshold. */
|
||||||
if (state->known_metadata_size != tps->total_metadata_blocks) {
|
if (state->known_metadata_size != tps->total_metadata_blocks) {
|
||||||
state->metadata_percent_check = CHECK_MINIMUM;
|
state->metadata_percent_check = CHECK_MINIMUM;
|
||||||
state->known_metadata_size = tps->total_metadata_blocks;
|
state->known_metadata_size = tps->total_metadata_blocks;
|
||||||
state->fails = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->known_data_size != tps->total_data_blocks) {
|
if (state->known_data_size != tps->total_data_blocks) {
|
||||||
state->data_percent_check = CHECK_MINIMUM;
|
state->data_percent_check = CHECK_MINIMUM;
|
||||||
state->known_data_size = tps->total_data_blocks;
|
state->known_data_size = tps->total_data_blocks;
|
||||||
state->fails = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
percent = 100 * tps->used_metadata_blocks / tps->total_metadata_blocks;
|
||||||
* Trigger action when threshold boundary is exceeded.
|
if (percent >= state->metadata_percent_check) {
|
||||||
* Report 80% threshold warning when it's used above 80%.
|
/*
|
||||||
* Only 100% is exception as it cannot be surpased so policy
|
* Usage has raised more than CHECK_STEP since the last
|
||||||
* action is called for: >50%, >55% ... >95%, 100%
|
* time. Run actions.
|
||||||
*/
|
*/
|
||||||
state->metadata_percent = dm_make_percent(tps->used_metadata_blocks, tps->total_metadata_blocks);
|
state->metadata_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||||
if (state->metadata_percent <= WARNING_THRESH)
|
|
||||||
state->metadata_warn_once = 0; /* Dropped bellow threshold, reset warn once */
|
|
||||||
else if (!state->metadata_warn_once++) /* Warn once when raised above threshold */
|
|
||||||
log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
|
|
||||||
device, dm_percent_to_float(state->metadata_percent));
|
|
||||||
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);
|
/* FIXME: extension of metadata needs to be written! */
|
||||||
if (state->data_percent <= WARNING_THRESH)
|
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||||
state->data_warn_once = 0;
|
syslog(LOG_WARNING, "Thin metadata %s is now %i%% full.\n",
|
||||||
else if (!state->data_warn_once++)
|
device, percent);
|
||||||
log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
|
/* Try to extend the metadata, in accord with user-set policies */
|
||||||
device, dm_percent_to_float(state->data_percent));
|
if (!_extend(state)) {
|
||||||
if (state->data_percent > CHECK_MINIMUM) {
|
syslog(LOG_ERR, "Failed to extend thin metadata %s.\n",
|
||||||
/* Run action when usage raised more than CHECK_STEP since the last time */
|
device);
|
||||||
if (state->data_percent > state->data_percent_check)
|
_umount(dmt, device);
|
||||||
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);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (state->max_fails < MAX_FAILS)
|
/* FIXME: hmm READ-ONLY switch should happen in error path */
|
||||||
state->max_fails <<= 1;
|
}
|
||||||
state->fails = needs_policy = 1; /* Retry failing command */
|
|
||||||
} else
|
|
||||||
state->max_fails = 1; /* Reset on success */
|
|
||||||
|
|
||||||
if (needs_policy)
|
percent = 100 * tps->used_data_blocks / tps->total_data_blocks;
|
||||||
_use_policy(dmt, state);
|
if (percent >= state->data_percent_check) {
|
||||||
|
/*
|
||||||
|
* Usage has raised more than CHECK_STEP since
|
||||||
|
* the last time. Run actions.
|
||||||
|
*/
|
||||||
|
state->data_percent_check = (percent / CHECK_STEP) * CHECK_STEP + CHECK_STEP;
|
||||||
|
|
||||||
|
if (percent >= WARNING_THRESH) /* Print a warning to syslog. */
|
||||||
|
syslog(LOG_WARNING, "Thin %s is now %i%% full.\n", device, percent);
|
||||||
|
/* Try to extend the thin data, in accord with user-set policies */
|
||||||
|
if (!_extend(state)) {
|
||||||
|
syslog(LOG_ERR, "Failed to extend thin %s.\n", device);
|
||||||
|
state->data_percent_check = 0;
|
||||||
|
_umount(dmt, device);
|
||||||
|
}
|
||||||
|
/* FIXME: hmm READ-ONLY switch should happen in error path */
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
if (tps)
|
if (tps)
|
||||||
dm_pool_free(state->mem, tps);
|
dm_pool_free(state->mem, tps);
|
||||||
|
|
||||||
if (new_dmt)
|
dmeventd_lvm2_unlock();
|
||||||
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,
|
int register_device(const char *device,
|
||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
|
struct dm_pool *statemem = NULL;
|
||||||
struct dso_state *state;
|
struct dso_state *state;
|
||||||
int maxcmd;
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (!dmeventd_lvm2_init_with_pool("thin_pool_state", state))
|
if (!dmeventd_lvm2_init())
|
||||||
goto_bad;
|
goto bad;
|
||||||
|
|
||||||
if (!dmeventd_lvm2_command(state->mem, state->cmd_str,
|
if (!(statemem = dm_pool_create("thin_pool_state", 2048)) ||
|
||||||
|
!(state = dm_pool_zalloc(statemem, sizeof(*state))) ||
|
||||||
|
!dmeventd_lvm2_command(statemem, state->cmd_str,
|
||||||
sizeof(state->cmd_str),
|
sizeof(state->cmd_str),
|
||||||
"_dmeventd_thin_command", device)) {
|
"lvextend --use-policies",
|
||||||
dmeventd_lvm2_exit_with_pool(state);
|
device)) {
|
||||||
goto_bad;
|
if (statemem)
|
||||||
|
dm_pool_destroy(statemem);
|
||||||
|
dmeventd_lvm2_exit();
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(state->cmd_str, "lvm ", 4)) {
|
state->mem = statemem;
|
||||||
maxcmd = 2; /* space for last NULL element */
|
state->metadata_percent_check = CHECK_MINIMUM;
|
||||||
for (str = state->cmd_str; *str; str++)
|
state->data_percent_check = CHECK_MINIMUM;
|
||||||
if (*str == ' ')
|
*private = state;
|
||||||
maxcmd++;
|
|
||||||
if (!(str = dm_pool_strdup(state->mem, state->cmd_str)) ||
|
|
||||||
!(state->argv = dm_pool_zalloc(state->mem, maxcmd * sizeof(char *)))) {
|
|
||||||
log_error("Failed to allocate memory for command.");
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
dm_split_words(str, maxcmd - 1, 0, state->argv);
|
syslog(LOG_INFO, "Monitoring thin %s.\n", device);
|
||||||
_init_thread_signals(state);
|
|
||||||
} else
|
|
||||||
memmove(state->cmd_str, state->cmd_str + 4, strlen(state->cmd_str + 4) + 1);
|
|
||||||
|
|
||||||
state->pid = -1;
|
|
||||||
*user = state;
|
|
||||||
|
|
||||||
log_info("Monitoring thin pool %s.", device);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
bad:
|
bad:
|
||||||
log_error("Failed to monitor thin pool %s.", device);
|
syslog(LOG_ERR, "Failed to monitor thin %s.\n", device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -398,34 +389,13 @@ int unregister_device(const char *device,
|
|||||||
const char *uuid __attribute__((unused)),
|
const char *uuid __attribute__((unused)),
|
||||||
int major __attribute__((unused)),
|
int major __attribute__((unused)),
|
||||||
int minor __attribute__((unused)),
|
int minor __attribute__((unused)),
|
||||||
void **user)
|
void **private)
|
||||||
{
|
{
|
||||||
struct dso_state *state = *user;
|
struct dso_state *state = *private;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; !_wait_for_pid(state) && (i < 6); ++i) {
|
syslog(LOG_INFO, "No longer monitoring thin %s.\n", device);
|
||||||
if (i == 0)
|
dm_pool_destroy(state->mem);
|
||||||
/* Give it 2 seconds, then try to terminate & kill it */
|
dmeventd_lvm2_exit();
|
||||||
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
1
daemons/lvmdbusd/.gitignore
vendored
1
daemons/lvmdbusd/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
path.py
|
|
||||||
@@ -1,66 +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 \
|
|
||||||
__init__.py \
|
|
||||||
job.py \
|
|
||||||
loader.py \
|
|
||||||
lvmdb.py \
|
|
||||||
main.py \
|
|
||||||
lvm_shell_proxy.py \
|
|
||||||
lv.py \
|
|
||||||
manager.py \
|
|
||||||
objectmanager.py \
|
|
||||||
pv.py \
|
|
||||||
request.py \
|
|
||||||
state.py \
|
|
||||||
udevwatch.py \
|
|
||||||
utils.py \
|
|
||||||
vg.py
|
|
||||||
|
|
||||||
LVMDBUS_BUILDDIR_FILES = \
|
|
||||||
path.py
|
|
||||||
|
|
||||||
LVMDBUSD = $(srcdir)/lvmdbusd
|
|
||||||
|
|
||||||
include $(top_builddir)/make.tmpl
|
|
||||||
|
|
||||||
.PHONY: install_lvmdbusd
|
|
||||||
|
|
||||||
install_lvmdbusd:
|
|
||||||
$(INSTALL_DIR) $(sbindir)
|
|
||||||
$(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
|
|
||||||
$(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
|
|
||||||
(cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
|
|
||||||
$(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
|
|
||||||
PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
|
||||||
$(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
|
|
||||||
$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
|
|
||||||
|
|
||||||
install_lvm2: install_lvmdbusd
|
|
||||||
|
|
||||||
install: install_lvm2
|
|
||||||
|
|
||||||
DISTCLEAN_TARGETS+= \
|
|
||||||
$(LVMDBUS_BUILDDIR_FILES)
|
|
||||||
@@ -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
|
|
||||||
@@ -1,173 +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] = self.GetAll(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
|
|
||||||
|
|
||||||
# Properties
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
|
||||||
in_signature='ss', out_signature='v')
|
|
||||||
def Get(self, interface_name, property_name):
|
|
||||||
value = getattr(self, 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
|
|
||||||
|
|
||||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
|
||||||
in_signature='s', out_signature='a{sv}')
|
|
||||||
def GetAll(self, interface_name):
|
|
||||||
if interface_name in self.interface(True):
|
|
||||||
# Using introspection, lets build this dynamically
|
|
||||||
properties = get_properties(self)
|
|
||||||
if interface_name in properties:
|
|
||||||
return properties[interface_name][1]
|
|
||||||
return {}
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
self._ap_interface,
|
|
||||||
'The object %s does not implement the %s interface'
|
|
||||||
% (self.__class__, interface_name))
|
|
||||||
|
|
||||||
@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
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1,142 +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
|
|
||||||
import dbus
|
|
||||||
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
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)
|
|
||||||
except ValueError:
|
|
||||||
log_error("Trying to parse percentage which failed for %s" %
|
|
||||||
line_str)
|
|
||||||
|
|
||||||
out = process.communicate()
|
|
||||||
|
|
||||||
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,))
|
|
||||||
t.start()
|
|
||||||
@@ -1,86 +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
|
|
||||||
ee = False
|
|
||||||
|
|
||||||
# Shared state variable across all processes
|
|
||||||
run = multiprocessing.Value('i', 1)
|
|
||||||
|
|
||||||
# If this is set to true, the current setup support lvm shell and we are
|
|
||||||
# running in that mode of operation
|
|
||||||
SHELL_IN_USE = None
|
|
||||||
|
|
||||||
# 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
|
|
||||||
@@ -1,751 +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
|
|
||||||
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.start = start
|
|
||||||
self.ended = ended
|
|
||||||
self.cmd = cmd
|
|
||||||
self.ec = ec
|
|
||||||
self.stdout_txt = stdout_txt
|
|
||||||
self.stderr_txt = stderr_txt
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "EC= %d for %s\n" \
|
|
||||||
"STARTED: %f, ENDED: %f\n" \
|
|
||||||
"STDOUT=%s\n" \
|
|
||||||
"STDERR=%s\n" % \
|
|
||||||
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
|
|
||||||
self.stderr_txt)
|
|
||||||
|
|
||||||
|
|
||||||
class LvmFlightRecorder(object):
|
|
||||||
|
|
||||||
def __init__(self, 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 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)
|
|
||||||
|
|
||||||
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 != "":
|
|
||||||
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, new_name, rename_options):
|
|
||||||
cmd = ['vgrename']
|
|
||||||
cmd.extend(options_to_cli_args(rename_options))
|
|
||||||
cmd.extend([vg, 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', str(size_bytes) + 'B'])
|
|
||||||
cmd.extend(['--name', name, vg_name])
|
|
||||||
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', str(size_bytes) + 'B'])
|
|
||||||
|
|
||||||
cmd.extend(['--name', name, vg_name])
|
|
||||||
return call(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def vg_lv_create_linear(vg_name, create_options, name, size_bytes, thin_pool):
|
|
||||||
cmd = ['lvcreate']
|
|
||||||
cmd.extend(options_to_cli_args(create_options))
|
|
||||||
|
|
||||||
if not thin_pool:
|
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
|
||||||
else:
|
|
||||||
cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
|
|
||||||
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 = ['lvcreate']
|
|
||||||
cmd.extend(options_to_cli_args(create_options))
|
|
||||||
|
|
||||||
if not thin_pool:
|
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
|
||||||
else:
|
|
||||||
cmd.extend(['--thin', '--size', str(size_bytes) + 'B'])
|
|
||||||
|
|
||||||
cmd.extend(['--stripes', str(num_stripes)])
|
|
||||||
|
|
||||||
if stripe_size_kb != 0:
|
|
||||||
cmd.extend(['--stripesize', str(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', str(size_bytes) + 'B'])
|
|
||||||
|
|
||||||
if num_stripes != 0:
|
|
||||||
cmd.extend(['--stripes', str(num_stripes)])
|
|
||||||
|
|
||||||
if stripe_size_kb != 0:
|
|
||||||
cmd.extend(['--stripesize', str(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))
|
|
||||||
|
|
||||||
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(num_copies)])
|
|
||||||
cmd.extend(['--size', str(size_bytes) + 'B'])
|
|
||||||
cmd.extend(['--name', name, vg_name])
|
|
||||||
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', str(size_bytes) + 'B', '-T'])
|
|
||||||
cmd.extend(['--name', name, lv_full_name])
|
|
||||||
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)
|
|
||||||
if rc == 0:
|
|
||||||
# With the current implementation, if we are using the shell then we
|
|
||||||
# are using JSON and JSON is returned back to us as it was parsed to
|
|
||||||
# figure out if we completed OK or not
|
|
||||||
if cfg.SHELL_IN_USE:
|
|
||||||
assert(type(out) == dict)
|
|
||||||
return out
|
|
||||||
else:
|
|
||||||
return json.loads(out)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def pv_retrieve_with_segs(device=None):
|
|
||||||
d = []
|
|
||||||
err = ""
|
|
||||||
out = ""
|
|
||||||
rc = 0
|
|
||||||
|
|
||||||
columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
|
||||||
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
|
||||||
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
|
|
||||||
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
|
|
||||||
'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
|
|
||||||
|
|
||||||
# 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(['--setphysicalvolumesize', str(size_bytes) + 'B'])
|
|
||||||
|
|
||||||
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 len(pv_devices) == 0:
|
|
||||||
cmd.append('--all')
|
|
||||||
if missing:
|
|
||||||
cmd.append('--removemissing')
|
|
||||||
|
|
||||||
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(number)],
|
|
||||||
max_options)
|
|
||||||
|
|
||||||
|
|
||||||
def vg_max_lv(vg_name, number, max_options):
|
|
||||||
return _vg_value_set(vg_name, ['-l', str(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))
|
|
||||||
@@ -1,161 +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 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):
|
|
||||||
while cfg.run.value != 0:
|
|
||||||
# noinspection PyBroadException
|
|
||||||
try:
|
|
||||||
queued_requests = []
|
|
||||||
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 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)
|
|
||||||
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
except Exception:
|
|
||||||
st = traceback.format_exc()
|
|
||||||
log_error("update_thread exception: \n%s" % st)
|
|
||||||
|
|
||||||
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,))
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -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_result, mt_run_no_wait
|
|
||||||
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_result(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_result(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_run_no_wait(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()
|
|
||||||
@@ -1,85 +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 . import cfg
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_construction(o_state, new_state):
|
|
||||||
# We need to check to see if the objects would get constructed
|
|
||||||
# the same
|
|
||||||
existing_ctor, existing_path = o_state.creation_signature()
|
|
||||||
new_ctor, new_path = new_state.creation_signature()
|
|
||||||
|
|
||||||
# print("%s == %s and %s == %s" % (str(existing_ctor), str(new_ctor),
|
|
||||||
# str(existing_path), str(new_path)))
|
|
||||||
|
|
||||||
return ((existing_ctor == new_ctor) and (existing_path == new_path))
|
|
||||||
|
|
||||||
|
|
||||||
def common(retrieve, o_type, search_keys,
|
|
||||||
object_path, refresh, emit_signal, cache_refresh):
|
|
||||||
num_changes = 0
|
|
||||||
existing_paths = []
|
|
||||||
rc = []
|
|
||||||
|
|
||||||
if search_keys:
|
|
||||||
assert isinstance(search_keys, list)
|
|
||||||
|
|
||||||
if cache_refresh:
|
|
||||||
cfg.db.refresh()
|
|
||||||
|
|
||||||
objects = retrieve(search_keys, cache_refresh=False)
|
|
||||||
|
|
||||||
# If we are doing a refresh we need to know what we have in memory, what's
|
|
||||||
# in lvm and add those that are new and remove those that are gone!
|
|
||||||
if refresh:
|
|
||||||
existing_paths = cfg.om.object_paths_by_type(o_type)
|
|
||||||
|
|
||||||
for o in objects:
|
|
||||||
# Assume we need to add this one to dbus, unless we are refreshing
|
|
||||||
# and it's already present
|
|
||||||
return_object = True
|
|
||||||
|
|
||||||
if refresh:
|
|
||||||
# We are refreshing all the PVs from LVM, if this one exists
|
|
||||||
# we need to refresh our state.
|
|
||||||
dbus_object = cfg.om.get_object_by_uuid_lvm_id(*o.identifiers())
|
|
||||||
|
|
||||||
if dbus_object:
|
|
||||||
del existing_paths[dbus_object.dbus_object_path()]
|
|
||||||
|
|
||||||
# If the old object state and new object state wouldn't be
|
|
||||||
# created with the same path and same object constructor we
|
|
||||||
# need to remove the old object and construct the new one
|
|
||||||
# instead!
|
|
||||||
if not _compare_construction(dbus_object.state, o):
|
|
||||||
# Remove existing and construct new one
|
|
||||||
cfg.om.remove_object(dbus_object, emit_signal)
|
|
||||||
dbus_object = o.create_dbus_object(None)
|
|
||||||
cfg.om.register_object(dbus_object, emit_signal)
|
|
||||||
num_changes += 1
|
|
||||||
else:
|
|
||||||
num_changes += dbus_object.refresh(object_state=o)
|
|
||||||
return_object = False
|
|
||||||
|
|
||||||
if return_object:
|
|
||||||
dbus_object = o.create_dbus_object(object_path)
|
|
||||||
cfg.om.register_object(dbus_object, emit_signal)
|
|
||||||
rc.append(dbus_object)
|
|
||||||
|
|
||||||
object_path = None
|
|
||||||
|
|
||||||
if refresh:
|
|
||||||
for k in list(existing_paths.keys()):
|
|
||||||
cfg.om.remove_object(cfg.om.get_object_by_path(k), True)
|
|
||||||
num_changes += 1
|
|
||||||
|
|
||||||
num_changes += len(rc)
|
|
||||||
|
|
||||||
return rc, num_changes
|
|
||||||
@@ -1,916 +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 . import utils
|
|
||||||
from .utils import vg_obj_path_generate
|
|
||||||
import dbus
|
|
||||||
from . import cmdhandler
|
|
||||||
from . import cfg
|
|
||||||
from .cfg import LV_INTERFACE, THIN_POOL_INTERFACE, SNAPSHOT_INTERFACE, \
|
|
||||||
LV_COMMON_INTERFACE, CACHE_POOL_INTERFACE, LV_CACHED
|
|
||||||
from .request import RequestEntry
|
|
||||||
from .utils import n, n32
|
|
||||||
from .loader import common
|
|
||||||
from .state import State
|
|
||||||
from . import background
|
|
||||||
from .utils import round_size, mt_remove_dbus_objects
|
|
||||||
from .job import JobState
|
|
||||||
|
|
||||||
|
|
||||||
# Try and build a key for a LV, so that we sort the LVs with least dependencies
|
|
||||||
# first. This may be error prone because of the flexibility LVM
|
|
||||||
# provides and what you can stack.
|
|
||||||
def get_key(i):
|
|
||||||
|
|
||||||
name = i['lv_name']
|
|
||||||
parent = i['lv_parent']
|
|
||||||
pool = i['pool_lv']
|
|
||||||
a1 = ""
|
|
||||||
a2 = ""
|
|
||||||
|
|
||||||
if name[0] == '[':
|
|
||||||
a1 = '#'
|
|
||||||
|
|
||||||
# We have a parent
|
|
||||||
if parent:
|
|
||||||
# Check if parent is hidden
|
|
||||||
if parent[0] == '[':
|
|
||||||
a2 = '##'
|
|
||||||
else:
|
|
||||||
a2 = '#'
|
|
||||||
|
|
||||||
# If a LV has a pool, then it should be sorted/loaded after the pool
|
|
||||||
# lv, unless it's a hidden too, then after other hidden, but before visible
|
|
||||||
if pool:
|
|
||||||
if pool[0] != '[':
|
|
||||||
a2 += '~'
|
|
||||||
else:
|
|
||||||
a1 = '$' + a1
|
|
||||||
|
|
||||||
return "%s%s%s" % (a1, a2, name)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
def lvs_state_retrieve(selection, cache_refresh=True):
|
|
||||||
rc = []
|
|
||||||
|
|
||||||
if cache_refresh:
|
|
||||||
cfg.db.refresh()
|
|
||||||
|
|
||||||
# When building up the model, it's best to process LVs with the least
|
|
||||||
# dependencies to those that are dependant upon other LVs. Otherwise, when
|
|
||||||
# we are trying to gather information we could be in a position where we
|
|
||||||
# don't have information available yet.
|
|
||||||
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
|
|
||||||
|
|
||||||
for l in lvs:
|
|
||||||
rc.append(LvState(
|
|
||||||
l['lv_uuid'], l['lv_name'],
|
|
||||||
l['lv_path'], n(l['lv_size']),
|
|
||||||
l['vg_name'],
|
|
||||||
l['vg_uuid'], l['pool_lv_uuid'],
|
|
||||||
l['pool_lv'], l['origin_uuid'], l['origin'],
|
|
||||||
n32(l['data_percent']), l['lv_attr'],
|
|
||||||
l['lv_tags'], l['lv_active'], l['data_lv'],
|
|
||||||
l['metadata_lv'], l['segtype'], l['lv_role'],
|
|
||||||
l['lv_layout'],
|
|
||||||
n32(l['snap_percent']),
|
|
||||||
n32(l['metadata_percent']),
|
|
||||||
n32(l['copy_percent']),
|
|
||||||
n32(l['sync_percent']),
|
|
||||||
n(l['lv_metadata_size']),
|
|
||||||
l['move_pv'],
|
|
||||||
l['move_pv_uuid']))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
|
|
||||||
def load_lvs(lv_name=None, object_path=None, refresh=False, emit_signal=False,
|
|
||||||
cache_refresh=True):
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
return common(
|
|
||||||
lvs_state_retrieve,
|
|
||||||
(LvCommon, Lv, LvThinPool, LvSnapShot),
|
|
||||||
lv_name, object_path, refresh, emit_signal, cache_refresh)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming,PyUnresolvedReferences,PyUnusedLocal
|
|
||||||
class LvState(State):
|
|
||||||
@staticmethod
|
|
||||||
def _pv_devices(uuid):
|
|
||||||
rc = []
|
|
||||||
for pv in sorted(cfg.db.lv_contained_pv(uuid)):
|
|
||||||
(pv_uuid, pv_name, pv_segs) = pv
|
|
||||||
pv_obj = cfg.om.get_object_path_by_uuid_lvm_id(pv_uuid, pv_name)
|
|
||||||
|
|
||||||
segs_decorate = []
|
|
||||||
for i in pv_segs:
|
|
||||||
segs_decorate.append((dbus.UInt64(i[0]),
|
|
||||||
dbus.UInt64(i[1]),
|
|
||||||
dbus.String(i[2])))
|
|
||||||
|
|
||||||
rc.append((dbus.ObjectPath(pv_obj), segs_decorate))
|
|
||||||
|
|
||||||
return dbus.Array(rc, signature="(oa(tts))")
|
|
||||||
|
|
||||||
def vg_name_lookup(self):
|
|
||||||
return cfg.om.get_object_by_path(self.Vg).Name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lvm_id(self):
|
|
||||||
return "%s/%s" % (self.vg_name_lookup(), self.Name)
|
|
||||||
|
|
||||||
def identifiers(self):
|
|
||||||
return (self.Uuid, self.lvm_id)
|
|
||||||
|
|
||||||
def _get_hidden_lv(self):
|
|
||||||
rc = dbus.Array([], "o")
|
|
||||||
|
|
||||||
vg_name = self.vg_name_lookup()
|
|
||||||
|
|
||||||
for l in cfg.db.hidden_lvs(self.Uuid):
|
|
||||||
full_name = "%s/%s" % (vg_name, l[1])
|
|
||||||
op = cfg.om.get_object_path_by_uuid_lvm_id(l[0], full_name)
|
|
||||||
assert op
|
|
||||||
rc.append(dbus.ObjectPath(op))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def __init__(self, Uuid, Name, Path, SizeBytes,
|
|
||||||
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
|
|
||||||
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
|
|
||||||
data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
|
|
||||||
MetaDataPercent, CopyPercent, SyncPercent, MetaDataSizeBytes,
|
|
||||||
move_pv, move_pv_uuid):
|
|
||||||
utils.init_class_from_arguments(self)
|
|
||||||
|
|
||||||
# The segtypes is possibly an array with potentially dupes or a single
|
|
||||||
# value
|
|
||||||
self._segs = dbus.Array([], signature='s')
|
|
||||||
if not isinstance(segtypes, list):
|
|
||||||
self._segs.append(dbus.String(segtypes))
|
|
||||||
else:
|
|
||||||
self._segs.extend([dbus.String(x) for x in set(segtypes)])
|
|
||||||
|
|
||||||
self.Vg = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
vg_uuid, vg_name, vg_obj_path_generate)
|
|
||||||
|
|
||||||
self.Devices = LvState._pv_devices(self.Uuid)
|
|
||||||
|
|
||||||
if PoolLv:
|
|
||||||
gen = utils.lv_object_path_method(Name, (Attr, layout, role))
|
|
||||||
|
|
||||||
self.PoolLv = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
pool_lv_uuid, '%s/%s' % (vg_name, PoolLv), gen)
|
|
||||||
else:
|
|
||||||
self.PoolLv = '/'
|
|
||||||
|
|
||||||
if OriginLv:
|
|
||||||
self.OriginLv = \
|
|
||||||
cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
origin_uuid, '%s/%s' % (vg_name, OriginLv),
|
|
||||||
vg_obj_path_generate)
|
|
||||||
else:
|
|
||||||
self.OriginLv = '/'
|
|
||||||
|
|
||||||
self.HiddenLvs = self._get_hidden_lv()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def SegType(self):
|
|
||||||
return self._segs
|
|
||||||
|
|
||||||
def _object_path_create(self):
|
|
||||||
return utils.lv_object_path_method(
|
|
||||||
self.Name, (self.Attr, self.layout, self.role))
|
|
||||||
|
|
||||||
def _object_type_create(self):
|
|
||||||
if self.Attr[0] == 't':
|
|
||||||
return LvThinPool
|
|
||||||
elif self.Attr[0] == 'C':
|
|
||||||
if 'pool' in self.layout:
|
|
||||||
return LvCachePool
|
|
||||||
else:
|
|
||||||
return LvCacheLv
|
|
||||||
elif self.Name[0] == '[':
|
|
||||||
return LvCommon
|
|
||||||
elif self.OriginLv != '/':
|
|
||||||
return LvSnapShot
|
|
||||||
else:
|
|
||||||
return Lv
|
|
||||||
|
|
||||||
def create_dbus_object(self, path):
|
|
||||||
if not path:
|
|
||||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
self.Uuid, self.lvm_id, self._object_path_create())
|
|
||||||
|
|
||||||
obj_ctor = self._object_type_create()
|
|
||||||
return obj_ctor(path, self)
|
|
||||||
|
|
||||||
def creation_signature(self):
|
|
||||||
klass = self._object_type_create()
|
|
||||||
path_method = self._object_path_create()
|
|
||||||
return (klass, path_method)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Uuid', 's')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Path', 's')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SizeBytes', 't')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SegType', 'as')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Vg', 'o')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'OriginLv', 'o')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'PoolLv', 'o')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Devices', "a(oa(tts))")
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'HiddenLvs', "ao")
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Attr', 's')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SnapPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'CopyPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SyncPercent', 'u')
|
|
||||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataSizeBytes', 't')
|
|
||||||
class LvCommon(AutomatedProperties):
|
|
||||||
_Tags_meta = ("as", LV_COMMON_INTERFACE)
|
|
||||||
_Roles_meta = ("as", LV_COMMON_INTERFACE)
|
|
||||||
_IsThinVolume_meta = ("b", LV_COMMON_INTERFACE)
|
|
||||||
_IsThinPool_meta = ("b", LV_COMMON_INTERFACE)
|
|
||||||
_Active_meta = ("b", LV_COMMON_INTERFACE)
|
|
||||||
_VolumeType_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_Permissions_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_AllocationPolicy_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_State_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_TargetType_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_Health_meta = ("(ss)", LV_COMMON_INTERFACE)
|
|
||||||
_FixedMinor_meta = ('b', LV_COMMON_INTERFACE)
|
|
||||||
_ZeroBlocks_meta = ('b', LV_COMMON_INTERFACE)
|
|
||||||
_SkipActivation_meta = ('b', LV_COMMON_INTERFACE)
|
|
||||||
_MovePv_meta = ('o', LV_COMMON_INTERFACE)
|
|
||||||
|
|
||||||
def _get_move_pv(self):
|
|
||||||
path = None
|
|
||||||
|
|
||||||
# It's likely that the move_pv is empty
|
|
||||||
if self.state.move_pv_uuid and self.state.move_pv:
|
|
||||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
self.state.move_pv_uuid, self.state.move_pv)
|
|
||||||
if not path:
|
|
||||||
path = '/'
|
|
||||||
return path
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyPep8Naming
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(LvCommon, self).__init__(object_path, lvs_state_retrieve)
|
|
||||||
self.set_interface(LV_COMMON_INTERFACE)
|
|
||||||
self.state = object_state
|
|
||||||
self._move_pv = self._get_move_pv()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def VolumeType(self):
|
|
||||||
type_map = {'C': 'Cache', 'm': 'mirrored',
|
|
||||||
'M': 'Mirrored without initial sync', 'o': 'origin',
|
|
||||||
'O': 'Origin with merging snapshot', 'r': 'raid',
|
|
||||||
'R': 'Raid without initial sync', 's': 'snapshot',
|
|
||||||
'S': 'merging Snapshot', 'p': 'pvmove',
|
|
||||||
'v': 'virtual', 'i': 'mirror or raid image',
|
|
||||||
'I': 'mirror or raid Image out-of-sync',
|
|
||||||
'l': 'mirror log device', 'c': 'under conversion',
|
|
||||||
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
|
|
||||||
'e': 'raid or pool metadata or pool metadata spare',
|
|
||||||
'-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[0], type_map[self.state.Attr[0]]),
|
|
||||||
signature="as")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Permissions(self):
|
|
||||||
type_map = {'w': 'writable', 'r': 'read-only',
|
|
||||||
'R': 'Read-only activation of non-read-only volume',
|
|
||||||
'-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[1], type_map[self.state.Attr[1]]),
|
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def AllocationPolicy(self):
|
|
||||||
type_map = {'a': 'anywhere', 'A': 'anywhere locked',
|
|
||||||
'c': 'contiguous', 'C': 'contiguous locked',
|
|
||||||
'i': 'inherited', 'I': 'inherited locked',
|
|
||||||
'l': 'cling', 'L': 'cling locked',
|
|
||||||
'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[2], type_map[self.state.Attr[2]]),
|
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def FixedMinor(self):
|
|
||||||
return dbus.Boolean(self.state.Attr[3] == 'm')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def State(self):
|
|
||||||
type_map = {'a': 'active', 's': 'suspended', 'I': 'Invalid snapshot',
|
|
||||||
'S': 'invalid Suspended snapshot',
|
|
||||||
'm': 'snapshot merge failed',
|
|
||||||
'M': 'suspended snapshot (M)erge failed',
|
|
||||||
'd': 'mapped device present without tables',
|
|
||||||
'i': 'mapped device present with inactive table',
|
|
||||||
'X': 'unknown', '-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[4], type_map[self.state.Attr[4]]),
|
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def TargetType(self):
|
|
||||||
type_map = {'C': 'Cache', 'm': 'mirror', 'r': 'raid',
|
|
||||||
's': 'snapshot', 't': 'thin', 'u': 'unknown',
|
|
||||||
'v': 'virtual', '-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[6], type_map[self.state.Attr[6]]),
|
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ZeroBlocks(self):
|
|
||||||
return dbus.Boolean(self.state.Attr[7] == 'z')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Health(self):
|
|
||||||
type_map = {'p': 'partial', 'r': 'refresh',
|
|
||||||
'm': 'mismatches', 'w': 'writemostly',
|
|
||||||
'X': 'X unknown', '-': 'Unspecified'}
|
|
||||||
return dbus.Struct((self.state.Attr[8], type_map[self.state.Attr[8]]),
|
|
||||||
signature="(ss)")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def SkipActivation(self):
|
|
||||||
return dbus.Boolean(self.state.Attr[9] == 'k')
|
|
||||||
|
|
||||||
def vg_name_lookup(self):
|
|
||||||
return self.state.vg_name_lookup()
|
|
||||||
|
|
||||||
def lv_full_name(self):
|
|
||||||
return "%s/%s" % (self.state.vg_name_lookup(), self.state.Name)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def identifiers(self):
|
|
||||||
return self.state.identifiers
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Tags(self):
|
|
||||||
return utils.parse_tags(self.state.Tags)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Roles(self):
|
|
||||||
return utils.parse_tags(self.state.role)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lvm_id(self):
|
|
||||||
return self.state.lvm_id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def IsThinVolume(self):
|
|
||||||
return dbus.Boolean(self.state.Attr[0] == 'V')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def IsThinPool(self):
|
|
||||||
return dbus.Boolean(self.state.Attr[0] == 't')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Active(self):
|
|
||||||
return dbus.Boolean(self.state.active == "active")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def MovePv(self):
|
|
||||||
return dbus.ObjectPath(self._move_pv)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class Lv(LvCommon):
|
|
||||||
def _fetch_hidden(self, name):
|
|
||||||
|
|
||||||
# The name is vg/name
|
|
||||||
full_name = "%s/%s" % (self.vg_name_lookup(), name)
|
|
||||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
|
||||||
|
|
||||||
def _get_data_meta(self):
|
|
||||||
|
|
||||||
# Get the data
|
|
||||||
return (self._fetch_hidden(self.state.data_lv),
|
|
||||||
self._fetch_hidden(self.state.metadata_lv))
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyPep8Naming
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(Lv, self).__init__(object_path, object_state)
|
|
||||||
self.set_interface(LV_INTERFACE)
|
|
||||||
self.state = object_state
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _remove(lv_uuid, lv_name, remove_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
# Remove the LV, if successful then remove from the model
|
|
||||||
rc, out, err = cmdhandler.lv_remove(lv_name, remove_options)
|
|
||||||
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Remove(self, tmo, remove_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._remove,
|
|
||||||
(self.Uuid, self.lvm_id, remove_options),
|
|
||||||
cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _rename(lv_uuid, lv_name, new_name, rename_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
# Rename the logical volume
|
|
||||||
rc, out, err = cmdhandler.lv_rename(lv_name, new_name,
|
|
||||||
rename_options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='sia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Rename(self, name, tmo, rename_options, cb, cbe):
|
|
||||||
utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._rename,
|
|
||||||
(self.Uuid, self.lvm_id, name, rename_options),
|
|
||||||
cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='o(tt)a(ott)ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Move(self, pv_src_obj, pv_source_range,
|
|
||||||
pv_dests_and_ranges,
|
|
||||||
tmo, move_options, cb, cbe):
|
|
||||||
|
|
||||||
job_state = JobState()
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, background.move,
|
|
||||||
(LV_INTERFACE, self.lvm_id, pv_src_obj, pv_source_range,
|
|
||||||
pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
|
|
||||||
job_state)
|
|
||||||
|
|
||||||
background.cmd_runner(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _snap_shot(lv_uuid, lv_name, name, optional_size,
|
|
||||||
snapshot_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
# If you specify a size you get a 'thick' snapshot even if
|
|
||||||
# it is a thin lv
|
|
||||||
if not dbo.IsThinVolume:
|
|
||||||
if optional_size == 0:
|
|
||||||
space = dbo.SizeBytes / 80
|
|
||||||
remainder = space % 512
|
|
||||||
optional_size = space + 512 - remainder
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_lv_snapshot(
|
|
||||||
lv_name, snapshot_options, name, optional_size)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
|
||||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='stia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Snapshot(self, name, optional_size, tmo,
|
|
||||||
snapshot_options, cb, cbe):
|
|
||||||
|
|
||||||
utils.validate_lv_name(LV_INTERFACE, self.vg_name_lookup(), name)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._snap_shot,
|
|
||||||
(self.Uuid, self.lvm_id, name,
|
|
||||||
optional_size, snapshot_options), cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _resize(lv_uuid, lv_name, new_size_bytes, pv_dests_and_ranges,
|
|
||||||
resize_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
pv_dests = []
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
# If we have PVs, verify them
|
|
||||||
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(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'PV Destination (%s) not found' % pr[0])
|
|
||||||
|
|
||||||
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
|
|
||||||
|
|
||||||
size_change = new_size_bytes - dbo.SizeBytes
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.lv_resize(dbo.lvm_id, size_change,
|
|
||||||
pv_dests, resize_options)
|
|
||||||
|
|
||||||
if rc == 0:
|
|
||||||
# Refresh what's changed
|
|
||||||
cfg.load()
|
|
||||||
return "/"
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='ta(ott)ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Resize(self, new_size_bytes, pv_dests_and_ranges, tmo,
|
|
||||||
resize_options, cb, cbe):
|
|
||||||
"""
|
|
||||||
Resize a LV
|
|
||||||
:param new_size_bytes: The requested final size in bytes
|
|
||||||
:param pv_dests_and_ranges: An array of pv object paths and src &
|
|
||||||
dst. segment ranges
|
|
||||||
:param tmo: -1 to wait forever, 0 to return job immediately, else
|
|
||||||
number of seconds to wait for operation to complete
|
|
||||||
before getting a job
|
|
||||||
:param resize_options: key/value hash of options
|
|
||||||
:param cb: Used by framework not client facing API
|
|
||||||
:param cbe: Used by framework not client facing API
|
|
||||||
:return: '/' if complete, else job object path
|
|
||||||
"""
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._resize,
|
|
||||||
(self.Uuid, self.lvm_id, round_size(new_size_bytes),
|
|
||||||
pv_dests_and_ranges,
|
|
||||||
resize_options), cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _lv_activate_deactivate(uuid, lv_name, activate, control_flags,
|
|
||||||
options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
rc, out, err = cmdhandler.activate_deactivate(
|
|
||||||
'lvchange', lv_name, activate, control_flags, options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
return '/'
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(uuid, lv_name))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='tia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Activate(self, control_flags, tmo, activate_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._lv_activate_deactivate,
|
|
||||||
(self.state.Uuid, self.state.lvm_id, True,
|
|
||||||
control_flags, activate_options),
|
|
||||||
cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
# noinspection PyProtectedMember
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='tia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Deactivate(self, control_flags, tmo, activate_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._lv_activate_deactivate,
|
|
||||||
(self.state.Uuid, self.state.lvm_id, False,
|
|
||||||
control_flags, activate_options),
|
|
||||||
cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _add_rm_tags(uuid, lv_name, tags_add, tags_del, tag_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.lv_tag(
|
|
||||||
lv_name, tags_add, tags_del, tag_options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
return '/'
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(uuid, lv_name))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='asia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def TagsAdd(self, tags, tmo, tag_options, cb, cbe):
|
|
||||||
|
|
||||||
for t in tags:
|
|
||||||
utils.validate_tag(LV_INTERFACE, t)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._add_rm_tags,
|
|
||||||
(self.state.Uuid, self.state.lvm_id,
|
|
||||||
tags, None, tag_options),
|
|
||||||
cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_INTERFACE,
|
|
||||||
in_signature='asia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def TagsDel(self, tags, tmo, tag_options, cb, cbe):
|
|
||||||
|
|
||||||
for t in tags:
|
|
||||||
utils.validate_tag(LV_INTERFACE, t)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Lv._add_rm_tags,
|
|
||||||
(self.state.Uuid, self.state.lvm_id,
|
|
||||||
None, tags, tag_options),
|
|
||||||
cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class LvThinPool(Lv):
|
|
||||||
_DataLv_meta = ("o", THIN_POOL_INTERFACE)
|
|
||||||
_MetaDataLv_meta = ("o", THIN_POOL_INTERFACE)
|
|
||||||
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(LvThinPool, self).__init__(object_path, object_state)
|
|
||||||
self.set_interface(THIN_POOL_INTERFACE)
|
|
||||||
self._data_lv, self._metadata_lv = self._get_data_meta()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def DataLv(self):
|
|
||||||
return dbus.ObjectPath(self._data_lv)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def MetaDataLv(self):
|
|
||||||
return dbus.ObjectPath(self._metadata_lv)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
rc, out, err = cmdhandler.lv_lv_create(
|
|
||||||
lv_name, create_options, name, size_bytes)
|
|
||||||
if rc == 0:
|
|
||||||
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
|
|
||||||
cfg.load()
|
|
||||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=THIN_POOL_INTERFACE,
|
|
||||||
in_signature='stia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def LvCreate(self, name, size_bytes, tmo, create_options, cb, cbe):
|
|
||||||
utils.validate_lv_name(THIN_POOL_INTERFACE, self.vg_name_lookup(), name)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, LvThinPool._lv_create,
|
|
||||||
(self.Uuid, self.lvm_id, name,
|
|
||||||
round_size(size_bytes), create_options), cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class LvCachePool(Lv):
|
|
||||||
_DataLv_meta = ("o", CACHE_POOL_INTERFACE)
|
|
||||||
_MetaDataLv_meta = ("o", CACHE_POOL_INTERFACE)
|
|
||||||
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(LvCachePool, self).__init__(object_path, object_state)
|
|
||||||
self.set_interface(CACHE_POOL_INTERFACE)
|
|
||||||
self._data_lv, self._metadata_lv = self._get_data_meta()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def DataLv(self):
|
|
||||||
return dbus.ObjectPath(self._data_lv)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def MetaDataLv(self):
|
|
||||||
return dbus.ObjectPath(self._metadata_lv)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _cache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
|
|
||||||
|
|
||||||
# Make sure we have a dbus object representing cache pool
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
# Make sure we have dbus object representing lv to cache
|
|
||||||
lv_to_cache = cfg.om.get_object_by_path(lv_object_path)
|
|
||||||
|
|
||||||
if dbo and lv_to_cache:
|
|
||||||
fcn = lv_to_cache.lv_full_name()
|
|
||||||
rc, out, err = cmdhandler.lv_cache_lv(
|
|
||||||
dbo.lv_full_name(), fcn, cache_options)
|
|
||||||
if rc == 0:
|
|
||||||
# When we cache an LV, the cache pool and the lv that is getting
|
|
||||||
# cached need to be removed from the object manager and
|
|
||||||
# re-created as their interfaces have changed!
|
|
||||||
mt_remove_dbus_objects((dbo, lv_to_cache))
|
|
||||||
cfg.load()
|
|
||||||
|
|
||||||
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
msg = ""
|
|
||||||
if not dbo:
|
|
||||||
dbo += 'CachePool LV with uuid %s and name %s not present!' % \
|
|
||||||
(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if not lv_to_cache:
|
|
||||||
dbo += 'LV to cache with object path %s not present!' % \
|
|
||||||
(lv_object_path)
|
|
||||||
|
|
||||||
raise dbus.exceptions.DBusException(LV_INTERFACE, msg)
|
|
||||||
return lv_converted
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=CACHE_POOL_INTERFACE,
|
|
||||||
in_signature='oia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def CacheLv(self, lv_object, tmo, cache_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, LvCachePool._cache_lv,
|
|
||||||
(self.Uuid, self.lvm_id, lv_object,
|
|
||||||
cache_options), cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class LvCacheLv(Lv):
|
|
||||||
_CachePool_meta = ("o", LV_CACHED)
|
|
||||||
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(LvCacheLv, self).__init__(object_path, object_state)
|
|
||||||
self.set_interface(LV_CACHED)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def CachePool(self):
|
|
||||||
return dbus.ObjectPath(self.state.PoolLv)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _detach_lv(lv_uuid, lv_name, detach_options, destroy_cache):
|
|
||||||
# Make sure we have a dbus object representing cache pool
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
|
|
||||||
# Get current cache name
|
|
||||||
cache_pool = cfg.om.get_object_by_path(dbo.CachePool)
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.lv_detach_cache(
|
|
||||||
dbo.lv_full_name(), detach_options, destroy_cache)
|
|
||||||
if rc == 0:
|
|
||||||
# The cache pool gets removed as hidden and put back to
|
|
||||||
# visible, so lets delete
|
|
||||||
mt_remove_dbus_objects((cache_pool, dbo))
|
|
||||||
cfg.load()
|
|
||||||
|
|
||||||
uncached_lv_path = cfg.om.get_object_path_by_lvm_id(lv_name)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
LV_INTERFACE,
|
|
||||||
'LV with uuid %s and name %s not present!' %
|
|
||||||
(lv_uuid, lv_name))
|
|
||||||
return uncached_lv_path
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=LV_CACHED,
|
|
||||||
in_signature='bia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def DetachCachePool(self, destroy_cache, tmo, detach_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, LvCacheLv._detach_lv,
|
|
||||||
(self.Uuid, self.lvm_id, detach_options,
|
|
||||||
destroy_cache), cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class LvSnapShot(Lv):
|
|
||||||
def __init__(self, object_path, object_state):
|
|
||||||
super(LvSnapShot, self).__init__(object_path, object_state)
|
|
||||||
self.set_interface(SNAPSHOT_INTERFACE)
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=SNAPSHOT_INTERFACE,
|
|
||||||
in_signature='ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Merge(self, tmo, merge_options, cb, cbe):
|
|
||||||
job_state = JobState()
|
|
||||||
|
|
||||||
r = RequestEntry(tmo, background.merge,
|
|
||||||
(SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
|
|
||||||
merge_options, job_state), cb, cbe, False,
|
|
||||||
job_state)
|
|
||||||
background.cmd_runner(r)
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# 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/>.
|
|
||||||
#
|
|
||||||
# Copyright 2015-2016, Vratislav Podzimek <vpodzime@redhat.com>
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import shlex
|
|
||||||
from fcntl import fcntl, F_GETFL, F_SETFL
|
|
||||||
import os
|
|
||||||
import traceback
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
import select
|
|
||||||
import copy
|
|
||||||
|
|
||||||
try:
|
|
||||||
import simplejson as json
|
|
||||||
except ImportError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
from lvmdbusd.cfg import LVM_CMD
|
|
||||||
from lvmdbusd.utils import log_debug, log_error
|
|
||||||
|
|
||||||
SHELL_PROMPT = "lvm> "
|
|
||||||
|
|
||||||
|
|
||||||
def _quote_arg(arg):
|
|
||||||
if len(shlex.split(arg)) > 1:
|
|
||||||
return '"%s"' % arg
|
|
||||||
else:
|
|
||||||
return arg
|
|
||||||
|
|
||||||
|
|
||||||
class LVMShellProxy(object):
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _read(stream):
|
|
||||||
tmp = stream.read()
|
|
||||||
if tmp:
|
|
||||||
return tmp.decode("utf-8")
|
|
||||||
return ''
|
|
||||||
|
|
||||||
# Read until we get prompt back and a result
|
|
||||||
# @param: no_output Caller expects no output to report FD
|
|
||||||
# Returns stdout, report, stderr (report is JSON!)
|
|
||||||
def _read_until_prompt(self, no_output=False):
|
|
||||||
stdout = ""
|
|
||||||
report = ""
|
|
||||||
stderr = ""
|
|
||||||
keep_reading = True
|
|
||||||
extra_passes = 3
|
|
||||||
report_json = {}
|
|
||||||
prev_report_len = 0
|
|
||||||
|
|
||||||
# Try reading from all FDs to prevent one from filling up and causing
|
|
||||||
# a hang. Keep reading until we get the prompt back and the report
|
|
||||||
# FD does not contain valid JSON
|
|
||||||
while keep_reading:
|
|
||||||
try:
|
|
||||||
rd_fd = [
|
|
||||||
self.lvm_shell.stdout.fileno(),
|
|
||||||
self.report_stream.fileno(),
|
|
||||||
self.lvm_shell.stderr.fileno()]
|
|
||||||
ready = select.select(rd_fd, [], [], 2)
|
|
||||||
|
|
||||||
for r in ready[0]:
|
|
||||||
if r == self.lvm_shell.stdout.fileno():
|
|
||||||
stdout += LVMShellProxy._read(self.lvm_shell.stdout)
|
|
||||||
elif r == self.report_stream.fileno():
|
|
||||||
report += LVMShellProxy._read(self.report_stream)
|
|
||||||
elif r == self.lvm_shell.stderr.fileno():
|
|
||||||
stderr += LVMShellProxy._read(self.lvm_shell.stderr)
|
|
||||||
|
|
||||||
# Check to see if the lvm process died on us
|
|
||||||
if self.lvm_shell.poll():
|
|
||||||
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
|
|
||||||
|
|
||||||
if stdout.endswith(SHELL_PROMPT):
|
|
||||||
if no_output:
|
|
||||||
keep_reading = False
|
|
||||||
else:
|
|
||||||
cur_report_len = len(report)
|
|
||||||
if cur_report_len != 0:
|
|
||||||
# Only bother to parse if we have more data
|
|
||||||
if prev_report_len != cur_report_len:
|
|
||||||
prev_report_len = cur_report_len
|
|
||||||
# Parse the JSON if it's good we are done,
|
|
||||||
# if not we will try to read some more.
|
|
||||||
try:
|
|
||||||
report_json = json.loads(report)
|
|
||||||
keep_reading = False
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if keep_reading:
|
|
||||||
extra_passes -= 1
|
|
||||||
if extra_passes <= 0:
|
|
||||||
if len(report):
|
|
||||||
raise ValueError("Invalid json: %s" %
|
|
||||||
report)
|
|
||||||
else:
|
|
||||||
raise ValueError(
|
|
||||||
"lvm returned no JSON output!")
|
|
||||||
|
|
||||||
except IOError as ioe:
|
|
||||||
log_debug(str(ioe))
|
|
||||||
pass
|
|
||||||
|
|
||||||
return stdout, report_json, stderr
|
|
||||||
|
|
||||||
def _write_cmd(self, cmd):
|
|
||||||
cmd_bytes = bytes(cmd, "utf-8")
|
|
||||||
num_written = self.lvm_shell.stdin.write(cmd_bytes)
|
|
||||||
assert (num_written == len(cmd_bytes))
|
|
||||||
self.lvm_shell.stdin.flush()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _make_non_block(stream):
|
|
||||||
flags = fcntl(stream, F_GETFL)
|
|
||||||
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
# Create a temp directory
|
|
||||||
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
|
|
||||||
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Lets create fifo for the report output
|
|
||||||
os.mkfifo(tmp_file, 0o600)
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# We have to open non-blocking as the other side isn't open until
|
|
||||||
# we actually fork the process.
|
|
||||||
self.report_fd = os.open(tmp_file, os.O_NONBLOCK)
|
|
||||||
self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
|
|
||||||
|
|
||||||
# Setup the environment for using our own socket for reporting
|
|
||||||
local_env = copy.deepcopy(os.environ)
|
|
||||||
local_env["LVM_REPORT_FD"] = "32"
|
|
||||||
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
|
|
||||||
|
|
||||||
# Disable the abort logic if lvm logs too much, which easily happens
|
|
||||||
# when utilizing the lvm shell.
|
|
||||||
local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
|
|
||||||
|
|
||||||
# run the lvm shell
|
|
||||||
self.lvm_shell = subprocess.Popen(
|
|
||||||
[LVM_CMD + " 32>%s" % tmp_file],
|
|
||||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
|
|
||||||
stderr=subprocess.PIPE, close_fds=True, shell=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
LVMShellProxy._make_non_block(self.lvm_shell.stdout)
|
|
||||||
LVMShellProxy._make_non_block(self.lvm_shell.stderr)
|
|
||||||
|
|
||||||
# wait for the first prompt
|
|
||||||
errors = self._read_until_prompt(no_output=True)[2]
|
|
||||||
if errors and len(errors):
|
|
||||||
raise RuntimeError(errors)
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
finally:
|
|
||||||
# These will get deleted when the FD count goes to zero so we
|
|
||||||
# can be sure to clean up correctly no matter how we finish
|
|
||||||
os.unlink(tmp_file)
|
|
||||||
os.rmdir(tmp_dir)
|
|
||||||
|
|
||||||
def get_error_msg(self):
|
|
||||||
# We got an error, lets go fetch the error message
|
|
||||||
self._write_cmd('lastlog\n')
|
|
||||||
|
|
||||||
# read everything from the STDOUT to the next prompt
|
|
||||||
stdout, report_json, stderr = self._read_until_prompt()
|
|
||||||
if 'log' in report_json:
|
|
||||||
error_msg = ""
|
|
||||||
# Walk the entire log array and build an error string
|
|
||||||
for log_entry in report_json['log']:
|
|
||||||
if log_entry['log_type'] == "error":
|
|
||||||
if error_msg:
|
|
||||||
error_msg += ', ' + log_entry['log_message']
|
|
||||||
else:
|
|
||||||
error_msg = log_entry['log_message']
|
|
||||||
|
|
||||||
return error_msg
|
|
||||||
|
|
||||||
return 'No error reason provided! (missing "log" section)'
|
|
||||||
|
|
||||||
def call_lvm(self, argv, debug=False):
|
|
||||||
rc = 1
|
|
||||||
error_msg = ""
|
|
||||||
|
|
||||||
if self.lvm_shell.poll():
|
|
||||||
raise Exception(
|
|
||||||
self.lvm_shell.returncode,
|
|
||||||
"Underlying lvm shell process is not present!")
|
|
||||||
|
|
||||||
# create the command string
|
|
||||||
cmd = " ".join(_quote_arg(arg) for arg in argv)
|
|
||||||
cmd += "\n"
|
|
||||||
|
|
||||||
# run the command by writing it to the shell's STDIN
|
|
||||||
self._write_cmd(cmd)
|
|
||||||
|
|
||||||
# read everything from the STDOUT to the next prompt
|
|
||||||
stdout, report_json, stderr = self._read_until_prompt()
|
|
||||||
|
|
||||||
# Parse the report to see what happened
|
|
||||||
if 'log' in report_json:
|
|
||||||
if report_json['log'][-1:][0]['log_ret_code'] == '1':
|
|
||||||
rc = 0
|
|
||||||
else:
|
|
||||||
error_msg = self.get_error_msg()
|
|
||||||
|
|
||||||
if debug or rc != 0:
|
|
||||||
log_error(('CMD: %s' % cmd))
|
|
||||||
log_error(("EC = %d" % rc))
|
|
||||||
log_error(("ERROR_MSG=\n %s\n" % error_msg))
|
|
||||||
|
|
||||||
return rc, report_json, error_msg
|
|
||||||
|
|
||||||
def exit_shell(self):
|
|
||||||
try:
|
|
||||||
self._write_cmd('exit\n')
|
|
||||||
except Exception as e:
|
|
||||||
log_error(str(e))
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
try:
|
|
||||||
self.lvm_shell.terminate()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
shell = LVMShellProxy()
|
|
||||||
in_line = "start"
|
|
||||||
try:
|
|
||||||
while in_line:
|
|
||||||
in_line = input("lvm> ")
|
|
||||||
if in_line:
|
|
||||||
start = time.time()
|
|
||||||
ret, out, err = shell.call_lvm(in_line.split())
|
|
||||||
end = time.time()
|
|
||||||
|
|
||||||
print(("RC: %d" % ret))
|
|
||||||
print(("OUT:\n%s" % out))
|
|
||||||
print(("ERR:\n%s" % err))
|
|
||||||
|
|
||||||
print("Command = %f seconds" % (end - start))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
except EOFError:
|
|
||||||
pass
|
|
||||||
except Exception:
|
|
||||||
traceback.print_exc(file=sys.stdout)
|
|
||||||
@@ -1,547 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# 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 collections import OrderedDict
|
|
||||||
|
|
||||||
import pprint as prettyprint
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from lvmdbusd import cmdhandler
|
|
||||||
from lvmdbusd.utils import log_debug, log_error
|
|
||||||
|
|
||||||
|
|
||||||
class DataStore(object):
|
|
||||||
def __init__(self, usejson=True):
|
|
||||||
self.pvs = {}
|
|
||||||
self.vgs = {}
|
|
||||||
self.lvs = {}
|
|
||||||
self.pv_lvs = {}
|
|
||||||
self.lv_pvs = {}
|
|
||||||
self.lvs_hidden = {}
|
|
||||||
|
|
||||||
self.pv_path_to_uuid = {}
|
|
||||||
self.vg_name_to_uuid = {}
|
|
||||||
self.lv_full_name_to_uuid = {}
|
|
||||||
|
|
||||||
self.lvs_in_vgs = {}
|
|
||||||
self.pvs_in_vgs = {}
|
|
||||||
|
|
||||||
# self.refresh()
|
|
||||||
self.num_refreshes = 0
|
|
||||||
|
|
||||||
if usejson:
|
|
||||||
self.json = cmdhandler.supports_json()
|
|
||||||
else:
|
|
||||||
self.json = usejson
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _insert_record(table, key, record, allowed_multiple):
|
|
||||||
if key in table:
|
|
||||||
existing = table[key]
|
|
||||||
|
|
||||||
for rec_k, rec_v in record.items():
|
|
||||||
if rec_k in allowed_multiple:
|
|
||||||
# This column name allows us to store multiple value for
|
|
||||||
# each type
|
|
||||||
if not isinstance(existing[rec_k], list):
|
|
||||||
existing_value = existing[rec_k]
|
|
||||||
existing[rec_k] = [existing_value, rec_v]
|
|
||||||
else:
|
|
||||||
existing[rec_k].append(rec_v)
|
|
||||||
else:
|
|
||||||
# If something is not expected to have changing values
|
|
||||||
# lets ensure that
|
|
||||||
if existing[rec_k] != rec_v:
|
|
||||||
raise RuntimeError(
|
|
||||||
"existing[%s]=%s != %s" %
|
|
||||||
(rec_k, str(existing[rec_k]),
|
|
||||||
str(rec_v)))
|
|
||||||
else:
|
|
||||||
table[key] = record
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_pvs(_pvs):
|
|
||||||
pvs = sorted(_pvs, key=lambda pk: pk['pv_name'])
|
|
||||||
|
|
||||||
c_pvs = OrderedDict()
|
|
||||||
c_lookup = {}
|
|
||||||
c_pvs_in_vgs = {}
|
|
||||||
|
|
||||||
for p in pvs:
|
|
||||||
DataStore._insert_record(
|
|
||||||
c_pvs, p['pv_uuid'], p,
|
|
||||||
['pvseg_start', 'pvseg_size', 'segtype'])
|
|
||||||
|
|
||||||
for p in c_pvs.values():
|
|
||||||
# Capture which PVs are associated with which VG
|
|
||||||
if p['vg_uuid'] not in c_pvs_in_vgs:
|
|
||||||
c_pvs_in_vgs[p['vg_uuid']] = []
|
|
||||||
|
|
||||||
if p['vg_name']:
|
|
||||||
c_pvs_in_vgs[p['vg_uuid']].append(
|
|
||||||
(p['pv_name'], p['pv_uuid']))
|
|
||||||
|
|
||||||
# Lookup for translating between /dev/<name> and pv uuid
|
|
||||||
c_lookup[p['pv_name']] = p['pv_uuid']
|
|
||||||
|
|
||||||
return c_pvs, c_lookup, c_pvs_in_vgs
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_pvs_json(_all):
|
|
||||||
|
|
||||||
c_pvs = OrderedDict()
|
|
||||||
c_lookup = {}
|
|
||||||
c_pvs_in_vgs = {}
|
|
||||||
|
|
||||||
# Each item item in the report is a collection of information pertaining
|
|
||||||
# to the vg
|
|
||||||
for r in _all['report']:
|
|
||||||
tmp_pv = []
|
|
||||||
|
|
||||||
# Get the pv data for this VG.
|
|
||||||
if 'pv' in r:
|
|
||||||
tmp_pv.extend(r['pv'])
|
|
||||||
|
|
||||||
# Sort them
|
|
||||||
sorted_tmp_pv = sorted(tmp_pv, key=lambda pk: pk['pv_name'])
|
|
||||||
|
|
||||||
# Add them to result set
|
|
||||||
for p in sorted_tmp_pv:
|
|
||||||
c_pvs[p['pv_uuid']] = p
|
|
||||||
|
|
||||||
if 'pvseg' in r:
|
|
||||||
for s in r['pvseg']:
|
|
||||||
r = c_pvs[s['pv_uuid']]
|
|
||||||
r.setdefault('pvseg_start', []).append(s['pvseg_start'])
|
|
||||||
r.setdefault('pvseg_size', []).append(s['pvseg_size'])
|
|
||||||
r.setdefault('segtype', []).append(s['segtype'])
|
|
||||||
|
|
||||||
# TODO: Remove this bug work around when we have orphan segs.
|
|
||||||
for i in c_pvs.values():
|
|
||||||
if 'pvseg_start' not in i:
|
|
||||||
i['pvseg_start'] = '0'
|
|
||||||
i['pvseg_size'] = i['pv_pe_count']
|
|
||||||
i['segtype'] = 'free'
|
|
||||||
|
|
||||||
for p in c_pvs.values():
|
|
||||||
# Capture which PVs are associated with which VG
|
|
||||||
if p['vg_uuid'] not in c_pvs_in_vgs:
|
|
||||||
c_pvs_in_vgs[p['vg_uuid']] = []
|
|
||||||
|
|
||||||
if p['vg_name']:
|
|
||||||
c_pvs_in_vgs[p['vg_uuid']].append(
|
|
||||||
(p['pv_name'], p['pv_uuid']))
|
|
||||||
|
|
||||||
# Lookup for translating between /dev/<name> and pv uuid
|
|
||||||
c_lookup[p['pv_name']] = p['pv_uuid']
|
|
||||||
|
|
||||||
return c_pvs, c_lookup, c_pvs_in_vgs
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_vgs(_vgs):
|
|
||||||
vgs = sorted(_vgs, key=lambda vk: vk['vg_name'])
|
|
||||||
|
|
||||||
c_vgs = OrderedDict()
|
|
||||||
c_lookup = {}
|
|
||||||
|
|
||||||
for i in vgs:
|
|
||||||
c_lookup[i['vg_name']] = i['vg_uuid']
|
|
||||||
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
|
|
||||||
|
|
||||||
return c_vgs, c_lookup
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_vgs_json(_all):
|
|
||||||
|
|
||||||
tmp_vg = []
|
|
||||||
for r in _all['report']:
|
|
||||||
# Get the pv data for this VG.
|
|
||||||
if 'vg' in r:
|
|
||||||
tmp_vg.extend(r['vg'])
|
|
||||||
|
|
||||||
# Sort for consistent output, however this is optional
|
|
||||||
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_name'])
|
|
||||||
|
|
||||||
c_vgs = OrderedDict()
|
|
||||||
c_lookup = {}
|
|
||||||
|
|
||||||
for i in vgs:
|
|
||||||
c_lookup[i['vg_name']] = i['vg_uuid']
|
|
||||||
c_vgs[i['vg_uuid']] = i
|
|
||||||
|
|
||||||
return c_vgs, c_lookup
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_lvs_common(c_lvs, c_lv_full_lookup):
|
|
||||||
|
|
||||||
c_lvs_in_vgs = OrderedDict()
|
|
||||||
c_lvs_hidden = OrderedDict()
|
|
||||||
|
|
||||||
for i in c_lvs.values():
|
|
||||||
if i['vg_uuid'] not in c_lvs_in_vgs:
|
|
||||||
c_lvs_in_vgs[i['vg_uuid']] = []
|
|
||||||
|
|
||||||
c_lvs_in_vgs[
|
|
||||||
i['vg_uuid']].append(
|
|
||||||
(i['lv_name'],
|
|
||||||
(i['lv_attr'], i['lv_layout'], i['lv_role']),
|
|
||||||
i['lv_uuid']))
|
|
||||||
|
|
||||||
if i['lv_parent']:
|
|
||||||
# Lookup what the parent refers too
|
|
||||||
parent_name = i['lv_parent']
|
|
||||||
full_parent_name = "%s/%s" % (i['vg_name'], parent_name)
|
|
||||||
if full_parent_name not in c_lv_full_lookup:
|
|
||||||
parent_name = '[%s]' % (parent_name)
|
|
||||||
full_parent_name = "%s/%s" % (i['vg_name'], parent_name)
|
|
||||||
|
|
||||||
parent_uuid = c_lv_full_lookup[full_parent_name]
|
|
||||||
|
|
||||||
if parent_uuid not in c_lvs_hidden:
|
|
||||||
c_lvs_hidden[parent_uuid] = []
|
|
||||||
|
|
||||||
c_lvs_hidden[parent_uuid].append(
|
|
||||||
(i['lv_uuid'], i['lv_name']))
|
|
||||||
|
|
||||||
return c_lvs, c_lvs_in_vgs, c_lvs_hidden, c_lv_full_lookup
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_lvs(_lvs):
|
|
||||||
lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
|
|
||||||
|
|
||||||
c_lvs = OrderedDict()
|
|
||||||
c_lv_full_lookup = OrderedDict()
|
|
||||||
|
|
||||||
for i in lvs:
|
|
||||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
|
||||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
|
||||||
DataStore._insert_record(
|
|
||||||
c_lvs, i['lv_uuid'], i,
|
|
||||||
['seg_pe_ranges', 'segtype'])
|
|
||||||
|
|
||||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_lvs_json(_all):
|
|
||||||
|
|
||||||
c_lvs = OrderedDict()
|
|
||||||
c_lv_full_lookup = {}
|
|
||||||
|
|
||||||
# Each item item in the report is a collection of information pertaining
|
|
||||||
# to the vg
|
|
||||||
for r in _all['report']:
|
|
||||||
# Get the lv data for this VG.
|
|
||||||
if 'lv' in r:
|
|
||||||
# Add them to result set
|
|
||||||
for i in r['lv']:
|
|
||||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
|
||||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
|
||||||
c_lvs[i['lv_uuid']] = i
|
|
||||||
|
|
||||||
# Add in the segment data
|
|
||||||
if 'seg' in r:
|
|
||||||
for s in r['seg']:
|
|
||||||
r = c_lvs[s['lv_uuid']]
|
|
||||||
r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges'])
|
|
||||||
r.setdefault('segtype', []).append(s['segtype'])
|
|
||||||
|
|
||||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _make_list(l):
|
|
||||||
if not isinstance(l, list):
|
|
||||||
l = [l]
|
|
||||||
return l
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _parse_seg_entry(se, segtype):
|
|
||||||
if se:
|
|
||||||
# print("_parse_seg_entry %s %s" % (str(se), str(segtype)))
|
|
||||||
device, segs = se.split(":")
|
|
||||||
start, end = segs.split('-')
|
|
||||||
return (device, (start, end), segtype)
|
|
||||||
else:
|
|
||||||
return ("", (), segtype)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _build_segments(l, seg_types):
|
|
||||||
rc = []
|
|
||||||
l = DataStore._make_list(l)
|
|
||||||
s = DataStore._make_list(seg_types)
|
|
||||||
|
|
||||||
assert len(l) == len(s)
|
|
||||||
ls = list(zip(l, s))
|
|
||||||
|
|
||||||
for i in ls:
|
|
||||||
if ' ' in i[0]:
|
|
||||||
tmp = i[0].split(' ')
|
|
||||||
for t in tmp:
|
|
||||||
rc.append(DataStore._parse_seg_entry(t, i[1]))
|
|
||||||
else:
|
|
||||||
rc.append(DataStore._parse_seg_entry(*i))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _pv_device_lv_entry(table, pv_device, lv_uuid, meta, lv_attr,
|
|
||||||
segment_info):
|
|
||||||
|
|
||||||
if pv_device not in table:
|
|
||||||
table[pv_device] = {}
|
|
||||||
|
|
||||||
if lv_uuid not in table[pv_device]:
|
|
||||||
table[pv_device][lv_uuid] = {}
|
|
||||||
table[pv_device][lv_uuid]['segs'] = [segment_info]
|
|
||||||
table[pv_device][lv_uuid]['name'] = meta
|
|
||||||
table[pv_device][lv_uuid]['meta'] = lv_attr
|
|
||||||
else:
|
|
||||||
table[pv_device][lv_uuid]['segs'].append(segment_info)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _pv_device_lv_format(pv_device_lvs):
|
|
||||||
rc = {}
|
|
||||||
|
|
||||||
for pv_device, pd in pv_device_lvs.items():
|
|
||||||
lvs = []
|
|
||||||
for lv_uuid, ld in sorted(pd.items()):
|
|
||||||
lvs.append((lv_uuid, ld['name'], ld['meta'], ld['segs']))
|
|
||||||
|
|
||||||
rc[pv_device] = lvs
|
|
||||||
return rc
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _lvs_device_pv_entry(table, lv_uuid, pv_device, pv_uuid, segment_info):
|
|
||||||
if lv_uuid not in table:
|
|
||||||
table[lv_uuid] = {}
|
|
||||||
|
|
||||||
if pv_device not in table[lv_uuid]:
|
|
||||||
table[lv_uuid][pv_device] = {}
|
|
||||||
table[lv_uuid][pv_device]['segs'] = [segment_info]
|
|
||||||
table[lv_uuid][pv_device]['pv_uuid'] = pv_uuid
|
|
||||||
else:
|
|
||||||
table[lv_uuid][pv_device]['segs'].append(segment_info)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _lvs_device_pv_format(lvs_device_pvs):
|
|
||||||
rc = {}
|
|
||||||
|
|
||||||
for lv_uuid, ld in lvs_device_pvs.items():
|
|
||||||
pvs = []
|
|
||||||
for pv_device, pd in sorted(ld.items()):
|
|
||||||
pvs.append((pd['pv_uuid'], pv_device, pd['segs']))
|
|
||||||
|
|
||||||
rc[lv_uuid] = pvs
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def _parse_pv_in_lvs(self):
|
|
||||||
pv_device_lvs = {} # What LVs are stored on a PV
|
|
||||||
lvs_device_pv = {} # Where LV data is stored
|
|
||||||
|
|
||||||
for i in self.lvs.values():
|
|
||||||
segs = self._build_segments(i['seg_pe_ranges'], i['segtype'])
|
|
||||||
for s in segs:
|
|
||||||
# We are referring to physical device
|
|
||||||
if '/dev/' in s[0]:
|
|
||||||
device, r, seg_type = s
|
|
||||||
|
|
||||||
DataStore._pv_device_lv_entry(
|
|
||||||
pv_device_lvs, device, i['lv_uuid'], i['lv_name'],
|
|
||||||
(i['lv_attr'], i['lv_layout'], i['lv_role']),
|
|
||||||
(r[0], r[1], seg_type))
|
|
||||||
|
|
||||||
# (pv_name, pv_segs, pv_uuid)
|
|
||||||
DataStore._lvs_device_pv_entry(
|
|
||||||
lvs_device_pv, i['lv_uuid'], device,
|
|
||||||
self.pv_path_to_uuid[device], (r[0], r[1], seg_type))
|
|
||||||
else:
|
|
||||||
# TODO Handle the case where the segments refer to a LV
|
|
||||||
# and not a PV
|
|
||||||
pass
|
|
||||||
# print("Handle this %s %s %s" % (s[0], s[1], s[2]))
|
|
||||||
|
|
||||||
# Convert form to needed result for consumption
|
|
||||||
pv_device_lvs_result = DataStore._pv_device_lv_format(pv_device_lvs)
|
|
||||||
lvs_device_pv_result = DataStore._lvs_device_pv_format(lvs_device_pv)
|
|
||||||
|
|
||||||
return pv_device_lvs_result, lvs_device_pv_result
|
|
||||||
|
|
||||||
def refresh(self, log=True):
|
|
||||||
"""
|
|
||||||
Go out and query lvm for the latest data in as few trips as possible
|
|
||||||
:param log Add debug log entry/exit messages
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
self.num_refreshes += 1
|
|
||||||
if log:
|
|
||||||
log_debug("lvmdb - refresh entry")
|
|
||||||
|
|
||||||
# Grab everything first then parse it
|
|
||||||
if self.json:
|
|
||||||
# Do a single lvm retrieve for everything in json
|
|
||||||
a = cmdhandler.lvm_full_report_json()
|
|
||||||
|
|
||||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
|
|
||||||
_vgs, _vgs_lookup = self._parse_vgs_json(a)
|
|
||||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
|
|
||||||
|
|
||||||
else:
|
|
||||||
_raw_pvs = cmdhandler.pv_retrieve_with_segs()
|
|
||||||
_raw_vgs = cmdhandler.vg_retrieve(None)
|
|
||||||
_raw_lvs = cmdhandler.lv_retrieve_with_segments()
|
|
||||||
|
|
||||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
|
|
||||||
_vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
|
|
||||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
|
|
||||||
|
|
||||||
# Set all
|
|
||||||
self.pvs = _pvs
|
|
||||||
self.pv_path_to_uuid = _pvs_lookup
|
|
||||||
self.vg_name_to_uuid = _vgs_lookup
|
|
||||||
self.lv_full_name_to_uuid = _lvs_lookup
|
|
||||||
|
|
||||||
self.vgs = _vgs
|
|
||||||
self.lvs = _lvs
|
|
||||||
self.lvs_in_vgs = _lvs_in_vgs
|
|
||||||
self.pvs_in_vgs = _pvs_in_vgs
|
|
||||||
self.lvs_hidden = _lvs_hidden
|
|
||||||
|
|
||||||
# Create lookup table for which LV and segments are on each PV
|
|
||||||
self.pv_lvs, self.lv_pvs = self._parse_pv_in_lvs()
|
|
||||||
|
|
||||||
if log:
|
|
||||||
log_debug("lvmdb - refresh exit")
|
|
||||||
|
|
||||||
def fetch_pvs(self, pv_name):
|
|
||||||
if not pv_name:
|
|
||||||
return self.pvs.values()
|
|
||||||
else:
|
|
||||||
rc = []
|
|
||||||
for s in pv_name:
|
|
||||||
# Ths user could be using a symlink instead of the actual
|
|
||||||
# block device, make sure we are using actual block device file
|
|
||||||
# if the pv name isn't in the lookup
|
|
||||||
if s not in self.pv_path_to_uuid:
|
|
||||||
s = os.path.realpath(s)
|
|
||||||
rc.append(self.pvs[self.pv_path_to_uuid[s]])
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def pv_missing(self, pv_uuid):
|
|
||||||
if pv_uuid in self.pvs:
|
|
||||||
if self.pvs[pv_uuid]['pv_missing'] == '':
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def fetch_vgs(self, vg_name):
|
|
||||||
if not vg_name:
|
|
||||||
return self.vgs.values()
|
|
||||||
else:
|
|
||||||
rc = []
|
|
||||||
for s in vg_name:
|
|
||||||
rc.append(self.vgs[self.vg_name_to_uuid[s]])
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def fetch_lvs(self, lv_names):
|
|
||||||
try:
|
|
||||||
if not lv_names:
|
|
||||||
return self.lvs.values()
|
|
||||||
else:
|
|
||||||
rc = []
|
|
||||||
for s in lv_names:
|
|
||||||
rc.append(self.lvs[self.lv_full_name_to_uuid[s]])
|
|
||||||
return rc
|
|
||||||
except KeyError as ke:
|
|
||||||
log_error("Key %s not found!" % (str(lv_names)))
|
|
||||||
log_error("lv name to uuid lookup")
|
|
||||||
for keys in sorted(self.lv_full_name_to_uuid.keys()):
|
|
||||||
log_error("%s" % (keys))
|
|
||||||
log_error("lvs entries by uuid")
|
|
||||||
for keys in sorted(self.lvs.keys()):
|
|
||||||
log_error("%s" % (keys))
|
|
||||||
raise ke
|
|
||||||
|
|
||||||
def pv_pe_segments(self, pv_uuid):
|
|
||||||
pv = self.pvs[pv_uuid]
|
|
||||||
return list(zip(pv['pvseg_start'], pv['pvseg_size']))
|
|
||||||
|
|
||||||
def pv_contained_lv(self, pv_device):
|
|
||||||
rc = []
|
|
||||||
if pv_device in self.pv_lvs:
|
|
||||||
rc = self.pv_lvs[pv_device]
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def lv_contained_pv(self, lv_uuid):
|
|
||||||
rc = []
|
|
||||||
if lv_uuid in self.lv_pvs:
|
|
||||||
rc = self.lv_pvs[lv_uuid]
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def lvs_in_vg(self, vg_uuid):
|
|
||||||
# Return an array of
|
|
||||||
# (lv_name, (lv_attr, lv_layout, lv_role), lv_uuid)
|
|
||||||
rc = []
|
|
||||||
if vg_uuid in self.lvs_in_vgs:
|
|
||||||
rc = self.lvs_in_vgs[vg_uuid]
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def pvs_in_vg(self, vg_uuid):
|
|
||||||
# Returns an array of (pv_name, pv_uuid)
|
|
||||||
rc = []
|
|
||||||
if vg_uuid in self.pvs_in_vgs:
|
|
||||||
rc = self.pvs_in_vgs[vg_uuid]
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def hidden_lvs(self, lv_uuid):
|
|
||||||
# For a specified LV, return a list of hidden lv_uuid, lv_name
|
|
||||||
# for it
|
|
||||||
rc = []
|
|
||||||
if lv_uuid in self.lvs_hidden:
|
|
||||||
rc = self.lvs_hidden[lv_uuid]
|
|
||||||
return rc
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
pp = prettyprint.PrettyPrinter(indent=4)
|
|
||||||
|
|
||||||
use_json = False
|
|
||||||
|
|
||||||
if len(sys.argv) != 1:
|
|
||||||
print(len(sys.argv))
|
|
||||||
use_json = True
|
|
||||||
|
|
||||||
ds = DataStore(use_json)
|
|
||||||
ds.refresh()
|
|
||||||
|
|
||||||
print("PVS")
|
|
||||||
for v in ds.pvs.values():
|
|
||||||
pp.pprint(v)
|
|
||||||
print('PV missing is %s' % ds.pv_missing(v['pv_uuid']))
|
|
||||||
|
|
||||||
print("VGS")
|
|
||||||
for v in ds.vgs.values():
|
|
||||||
pp.pprint(v)
|
|
||||||
|
|
||||||
print("LVS")
|
|
||||||
for v in ds.lvs.values():
|
|
||||||
pp.pprint(v)
|
|
||||||
|
|
||||||
print("LVS in VG")
|
|
||||||
for k, v in ds.lvs_in_vgs.items():
|
|
||||||
print("VG uuid = %s" % (k))
|
|
||||||
pp.pprint(v)
|
|
||||||
|
|
||||||
print("pv_in_lvs")
|
|
||||||
for k, v in ds.pv_lvs.items():
|
|
||||||
print("PV %s contains LVS:" % (k))
|
|
||||||
pp.pprint(v)
|
|
||||||
|
|
||||||
for k, v in ds.lv_pvs.items():
|
|
||||||
print("LV device = %s" % (k))
|
|
||||||
pp.pprint(v)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# 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 sys
|
|
||||||
from lvmdbusd import main
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,179 +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 . import cfg
|
|
||||||
from . import objectmanager
|
|
||||||
from . import utils
|
|
||||||
from .cfg import BUS_NAME, BASE_INTERFACE, BASE_OBJ_PATH, MANAGER_OBJ_PATH
|
|
||||||
import threading
|
|
||||||
from . import cmdhandler
|
|
||||||
import time
|
|
||||||
import signal
|
|
||||||
import dbus
|
|
||||||
import dbus.mainloop.glib
|
|
||||||
from . import lvmdb
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
from gi.repository import GLib
|
|
||||||
from .fetch import StateUpdate
|
|
||||||
from .manager import Manager
|
|
||||||
import traceback
|
|
||||||
import queue
|
|
||||||
from . import udevwatch
|
|
||||||
from .utils import log_debug, log_error
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from .cmdhandler import LvmFlightRecorder
|
|
||||||
|
|
||||||
|
|
||||||
class Lvm(objectmanager.ObjectManager):
|
|
||||||
def __init__(self, object_path):
|
|
||||||
super(Lvm, self).__init__(object_path, BASE_INTERFACE)
|
|
||||||
|
|
||||||
|
|
||||||
def process_request():
|
|
||||||
while cfg.run.value != 0:
|
|
||||||
# noinspection PyBroadException
|
|
||||||
try:
|
|
||||||
req = cfg.worker_q.get(True, 5)
|
|
||||||
log_debug(
|
|
||||||
"Running method: %s with args %s" %
|
|
||||||
(str(req.method), str(req.arguments)))
|
|
||||||
req.run_cmd()
|
|
||||||
log_debug("Method complete ")
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
except Exception:
|
|
||||||
st = traceback.format_exc()
|
|
||||||
utils.log_error("process_request exception: \n%s" % st)
|
|
||||||
|
|
||||||
|
|
||||||
def check_bb_size(value):
|
|
||||||
v = int(value)
|
|
||||||
if v < 0:
|
|
||||||
raise argparse.ArgumentTypeError(
|
|
||||||
"positive integers only ('%s' invalid)" % value)
|
|
||||||
return v
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
start = time.time()
|
|
||||||
# Add simple command line handling
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"--udev", action='store_true',
|
|
||||||
help="Use udev for updating state",
|
|
||||||
default=False,
|
|
||||||
dest='use_udev')
|
|
||||||
parser.add_argument(
|
|
||||||
"--debug", action='store_true',
|
|
||||||
help="Dump debug messages", default=False,
|
|
||||||
dest='debug')
|
|
||||||
parser.add_argument(
|
|
||||||
"--nojson", action='store_false',
|
|
||||||
help="Do not use LVM JSON output (disables lvmshell)", default=True,
|
|
||||||
dest='use_json')
|
|
||||||
parser.add_argument(
|
|
||||||
"--lvmshell", action='store_true',
|
|
||||||
help="Use the lvm shell, not fork & exec lvm",
|
|
||||||
default=False,
|
|
||||||
dest='use_lvm_shell')
|
|
||||||
parser.add_argument(
|
|
||||||
"--blackboxsize",
|
|
||||||
help="Size of the black box flight recorder, 0 to disable",
|
|
||||||
default=10,
|
|
||||||
type=check_bb_size,
|
|
||||||
dest='bb_size')
|
|
||||||
|
|
||||||
use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
|
|
||||||
|
|
||||||
# Ensure that we get consistent output for parsing stdout/stderr
|
|
||||||
os.environ["LC_ALL"] = "C"
|
|
||||||
|
|
||||||
cfg.args = parser.parse_args()
|
|
||||||
|
|
||||||
# We create a flight recorder in cmdhandler too, but we replace it here
|
|
||||||
# as the user may be specifying a different size. The default one in
|
|
||||||
# cmdhandler is for when we are running other code with a different main.
|
|
||||||
cfg.blackbox = LvmFlightRecorder(cfg.args.bb_size)
|
|
||||||
|
|
||||||
if cfg.args.use_lvm_shell and not cfg.args.use_json:
|
|
||||||
log_error("You cannot specify --lvmshell and --nojson")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# List of threads that we start up
|
|
||||||
thread_list = []
|
|
||||||
|
|
||||||
# Install signal handlers
|
|
||||||
for s in [signal.SIGHUP, signal.SIGINT]:
|
|
||||||
try:
|
|
||||||
signal.signal(s, utils.handler)
|
|
||||||
except RuntimeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
||||||
dbus.mainloop.glib.threads_init()
|
|
||||||
|
|
||||||
cmdhandler.set_execution(cfg.args.use_lvm_shell)
|
|
||||||
|
|
||||||
if use_session:
|
|
||||||
cfg.bus = dbus.SessionBus()
|
|
||||||
else:
|
|
||||||
cfg.bus = dbus.SystemBus()
|
|
||||||
# The base name variable needs to exist for things to work.
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
base_name = dbus.service.BusName(BUS_NAME, cfg.bus)
|
|
||||||
cfg.om = Lvm(BASE_OBJ_PATH)
|
|
||||||
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
|
|
||||||
|
|
||||||
cfg.db = lvmdb.DataStore(cfg.args.use_json)
|
|
||||||
|
|
||||||
# Using a thread to process requests, we cannot hang the dbus library
|
|
||||||
# thread that is handling the dbus interface
|
|
||||||
thread_list.append(threading.Thread(target=process_request))
|
|
||||||
|
|
||||||
# Have a single thread handling updating lvm and the dbus model so we
|
|
||||||
# don't have multiple threads doing this as the same time
|
|
||||||
updater = StateUpdate()
|
|
||||||
thread_list.append(updater.thread)
|
|
||||||
|
|
||||||
cfg.load = updater.load
|
|
||||||
cfg.event = updater.event
|
|
||||||
|
|
||||||
cfg.loop = GLib.MainLoop()
|
|
||||||
|
|
||||||
for thread in thread_list:
|
|
||||||
thread.damon = True
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
# Add udev watching
|
|
||||||
if cfg.args.use_udev:
|
|
||||||
log_debug('Utilizing udev to trigger updates')
|
|
||||||
|
|
||||||
# In all cases we are going to monitor for udev until we get an
|
|
||||||
# ExternalEvent. In the case where we get an external event and the user
|
|
||||||
# didn't specify --udev we will stop monitoring udev
|
|
||||||
udevwatch.add()
|
|
||||||
|
|
||||||
end = time.time()
|
|
||||||
log_debug(
|
|
||||||
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
|
|
||||||
(end - start, cmdhandler.total_time, cmdhandler.total_count),
|
|
||||||
'bg_black', 'fg_light_green')
|
|
||||||
|
|
||||||
try:
|
|
||||||
if cfg.run.value != 0:
|
|
||||||
cfg.loop.run()
|
|
||||||
udevwatch.remove()
|
|
||||||
|
|
||||||
for thread in thread_list:
|
|
||||||
thread.join()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
utils.handler(signal.SIGINT, None)
|
|
||||||
return 0
|
|
||||||
@@ -1,255 +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 . import utils
|
|
||||||
from .cfg import MANAGER_INTERFACE
|
|
||||||
import dbus
|
|
||||||
from . import cfg
|
|
||||||
from . import cmdhandler
|
|
||||||
from .request import RequestEntry
|
|
||||||
from . import udevwatch
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class Manager(AutomatedProperties):
|
|
||||||
_Version_meta = ("s", MANAGER_INTERFACE)
|
|
||||||
|
|
||||||
def __init__(self, object_path):
|
|
||||||
super(Manager, self).__init__(object_path)
|
|
||||||
self.set_interface(MANAGER_INTERFACE)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Version(self):
|
|
||||||
return dbus.String('1.0.0')
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _pv_create(device, create_options):
|
|
||||||
|
|
||||||
# Check to see if we are already trying to create a PV for an existing
|
|
||||||
# PV
|
|
||||||
pv = cfg.om.get_object_path_by_uuid_lvm_id(device, device)
|
|
||||||
if pv:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
MANAGER_INTERFACE, "PV Already exists!")
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.pv_create(create_options, [device])
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
created_pv = cfg.om.get_object_path_by_lvm_id(device)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
MANAGER_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
return created_pv
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='sia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def PvCreate(self, device, tmo, create_options, cb, cbe):
|
|
||||||
utils.validate_device_path(MANAGER_INTERFACE, device)
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Manager._pv_create,
|
|
||||||
(device, create_options), cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _create_vg(name, pv_object_paths, create_options):
|
|
||||||
pv_devices = []
|
|
||||||
|
|
||||||
for p in pv_object_paths:
|
|
||||||
pv = cfg.om.get_object_by_path(p)
|
|
||||||
if pv:
|
|
||||||
pv_devices.append(pv.Name)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
MANAGER_INTERFACE, 'object path = %s not found' % p)
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.vg_create(create_options, pv_devices, name)
|
|
||||||
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
return cfg.om.get_object_path_by_lvm_id(name)
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
MANAGER_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='saoia{sv}',
|
|
||||||
out_signature='(oo)',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def VgCreate(self, name, pv_object_paths, tmo, create_options, cb, cbe):
|
|
||||||
utils.validate_vg_name(MANAGER_INTERFACE, name)
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Manager._create_vg,
|
|
||||||
(name, pv_object_paths, create_options,),
|
|
||||||
cb, cbe)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _refresh():
|
|
||||||
utils.log_debug('Manager.Refresh - entry')
|
|
||||||
|
|
||||||
# This is a diagnostic and should not be run in normal operation, so
|
|
||||||
# lets remove the log entries for refresh as it's implied.
|
|
||||||
|
|
||||||
# Run an internal diagnostic on the object manager look up tables
|
|
||||||
lc = cfg.om.validate_lookups()
|
|
||||||
|
|
||||||
rc = cfg.load(log=False)
|
|
||||||
|
|
||||||
if rc != 0:
|
|
||||||
utils.log_debug('Manager.Refresh - exit %d' % (rc),
|
|
||||||
'bg_black', 'fg_light_red')
|
|
||||||
else:
|
|
||||||
utils.log_debug('Manager.Refresh - exit %d' % (rc))
|
|
||||||
return rc + lc
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
out_signature='t',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Refresh(self, cb, cbe):
|
|
||||||
"""
|
|
||||||
Take all the objects we know about and go out and grab the latest
|
|
||||||
more of a test method at the moment to make sure we are handling object
|
|
||||||
paths correctly.
|
|
||||||
|
|
||||||
:param cb Callback for result
|
|
||||||
:param cbe Callback for errors
|
|
||||||
|
|
||||||
Returns the number of changes, object add/remove/properties changed
|
|
||||||
"""
|
|
||||||
r = RequestEntry(-1, Manager._refresh, (), cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='s',
|
|
||||||
out_signature='o')
|
|
||||||
def LookUpByLvmId(self, key):
|
|
||||||
"""
|
|
||||||
Given a lvm id in one of the forms:
|
|
||||||
|
|
||||||
/dev/sda
|
|
||||||
some_vg
|
|
||||||
some_vg/some_lv
|
|
||||||
Oe1rPX-Pf0W-15E5-n41N-ZmtF-jXS0-Osg8fn
|
|
||||||
|
|
||||||
return the object path in O(1) time.
|
|
||||||
|
|
||||||
:param key: The lookup value
|
|
||||||
:return: Return the object path. If object not found you will get '/'
|
|
||||||
"""
|
|
||||||
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
|
|
||||||
if p:
|
|
||||||
return p
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _use_lvm_shell(yes_no):
|
|
||||||
return dbus.Boolean(cmdhandler.set_execution(yes_no))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='b', out_signature='b',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def UseLvmShell(self, yes_no, cb, cbe):
|
|
||||||
"""
|
|
||||||
Allow the client to enable/disable lvm shell, used for testing
|
|
||||||
:param yes_no:
|
|
||||||
:param cb: dbus python call back parameter, not client visible
|
|
||||||
:param cbe: dbus python error call back parameter, not client visible
|
|
||||||
:return: Nothing
|
|
||||||
"""
|
|
||||||
r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='s', out_signature='i')
|
|
||||||
def ExternalEvent(self, command):
|
|
||||||
|
|
||||||
# If a user didn't explicitly specify udev, we will turn it off now.
|
|
||||||
if not cfg.args.use_udev:
|
|
||||||
if udevwatch.remove():
|
|
||||||
utils.log_debug("ExternalEvent received, disabling "
|
|
||||||
"udev monitoring")
|
|
||||||
# We are dependent on external events now to stay current!
|
|
||||||
cfg.ee = True
|
|
||||||
utils.log_debug("ExternalEvent %s" % command)
|
|
||||||
cfg.event()
|
|
||||||
return dbus.Int32(0)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _pv_scan(activate, cache, device_path, major_minor, scan_options):
|
|
||||||
|
|
||||||
rc, out, err = cmdhandler.pv_scan(
|
|
||||||
activate, cache, device_path,
|
|
||||||
major_minor, scan_options)
|
|
||||||
|
|
||||||
if rc == 0:
|
|
||||||
# This could potentially change the state quite a bit, so lets
|
|
||||||
# update everything to be safe
|
|
||||||
cfg.load()
|
|
||||||
return '/'
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
MANAGER_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=MANAGER_INTERFACE,
|
|
||||||
in_signature='bbasa(ii)ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def PvScan(self, activate, cache, device_paths, major_minors,
|
|
||||||
tmo, scan_options, cb, cbe):
|
|
||||||
"""
|
|
||||||
Scan all supported LVM block devices in the system for physical volumes
|
|
||||||
NOTE: major_minors & device_paths only usable when cache == True
|
|
||||||
:param activate: If True, activate any newly found LVs
|
|
||||||
:param cache: If True, update lvmetad
|
|
||||||
:param device_paths: Array of device paths or empty
|
|
||||||
:param major_minors: Array of structures (major,minor)
|
|
||||||
:param tmo: Timeout for operation
|
|
||||||
:param scan_options: Additional options to pvscan
|
|
||||||
:param cb: Not visible in API (used for async. callback)
|
|
||||||
:param cbe: Not visible in API (used for async. error callback)
|
|
||||||
:return: '/' if operation done, else job path
|
|
||||||
"""
|
|
||||||
for d in device_paths:
|
|
||||||
utils.validate_device_path(MANAGER_INTERFACE, d)
|
|
||||||
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Manager._pv_scan,
|
|
||||||
(activate, cache, device_paths, major_minors,
|
|
||||||
scan_options), cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lvm_id(self):
|
|
||||||
"""
|
|
||||||
Intended to be overridden by classes that inherit
|
|
||||||
"""
|
|
||||||
return str(id(self))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Uuid(self):
|
|
||||||
"""
|
|
||||||
Intended to be overridden by classes that inherit
|
|
||||||
"""
|
|
||||||
import uuid
|
|
||||||
return uuid.uuid1()
|
|
||||||
@@ -1,377 +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 sys
|
|
||||||
import threading
|
|
||||||
import traceback
|
|
||||||
import dbus
|
|
||||||
import os
|
|
||||||
import copy
|
|
||||||
from . import cfg
|
|
||||||
from .utils import log_debug, pv_obj_path_generate, log_error
|
|
||||||
from .automatedproperties import AutomatedProperties
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
class ObjectManager(AutomatedProperties):
|
|
||||||
"""
|
|
||||||
Implements the org.freedesktop.DBus.ObjectManager interface
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, object_path, interface):
|
|
||||||
super(ObjectManager, self).__init__(object_path, interface)
|
|
||||||
self.set_interface(interface)
|
|
||||||
self._ap_o_path = object_path
|
|
||||||
self._objects = {}
|
|
||||||
self._id_to_object_path = {}
|
|
||||||
self.rlock = threading.RLock()
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface="org.freedesktop.DBus.ObjectManager",
|
|
||||||
out_signature='a{oa{sa{sv}}}')
|
|
||||||
def GetManagedObjects(self):
|
|
||||||
with self.rlock:
|
|
||||||
rc = {}
|
|
||||||
try:
|
|
||||||
for k, v in list(self._objects.items()):
|
|
||||||
path, props = v[0].emit_data()
|
|
||||||
rc[path] = props
|
|
||||||
except Exception:
|
|
||||||
traceback.print_exc(file=sys.stdout)
|
|
||||||
sys.exit(1)
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def locked(self):
|
|
||||||
"""
|
|
||||||
If some external code need to run across a number of different
|
|
||||||
calls into ObjectManager while blocking others they can use this method
|
|
||||||
to lock others out.
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
return ObjectManagerLock(self.rlock)
|
|
||||||
|
|
||||||
@dbus.service.signal(
|
|
||||||
dbus_interface="org.freedesktop.DBus.ObjectManager",
|
|
||||||
signature='oa{sa{sv}}')
|
|
||||||
def InterfacesAdded(self, object_path, int_name_prop_dict):
|
|
||||||
log_debug(
|
|
||||||
('SIGNAL: InterfacesAdded(%s, %s)' %
|
|
||||||
(str(object_path), str(int_name_prop_dict))))
|
|
||||||
|
|
||||||
@dbus.service.signal(
|
|
||||||
dbus_interface="org.freedesktop.DBus.ObjectManager",
|
|
||||||
signature='oas')
|
|
||||||
def InterfacesRemoved(self, object_path, interface_list):
|
|
||||||
log_debug(('SIGNAL: InterfacesRemoved(%s, %s)' %
|
|
||||||
(str(object_path), str(interface_list))))
|
|
||||||
|
|
||||||
def validate_lookups(self):
|
|
||||||
with self.rlock:
|
|
||||||
tmp_lookups = copy.deepcopy(self._id_to_object_path)
|
|
||||||
|
|
||||||
# iterate over all we know, removing from the copy. If all is well
|
|
||||||
# we will have zero items left over
|
|
||||||
for path, md in self._objects.items():
|
|
||||||
obj, lvm_id, uuid = md
|
|
||||||
|
|
||||||
if lvm_id:
|
|
||||||
assert path == tmp_lookups[lvm_id]
|
|
||||||
del tmp_lookups[lvm_id]
|
|
||||||
|
|
||||||
if uuid:
|
|
||||||
assert path == tmp_lookups[uuid]
|
|
||||||
del tmp_lookups[uuid]
|
|
||||||
|
|
||||||
rc = len(tmp_lookups)
|
|
||||||
if rc:
|
|
||||||
# Error condition
|
|
||||||
log_error("_id_to_object_path has extraneous lookups!")
|
|
||||||
for key, path in tmp_lookups.items():
|
|
||||||
log_error("Key= %s, path= %s" % (key, path))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def _lookup_add(self, obj, path, lvm_id, uuid):
|
|
||||||
"""
|
|
||||||
Store information about what we added to the caches so that we
|
|
||||||
can remove it cleanly
|
|
||||||
:param obj: The dbus object we are storing
|
|
||||||
:param lvm_id: The lvm id for the asset
|
|
||||||
:param uuid: The uuid for the asset
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
# Note: Only called internally, lock implied
|
|
||||||
|
|
||||||
# We could have a temp entry from the forward creation of a path
|
|
||||||
self._lookup_remove(path)
|
|
||||||
|
|
||||||
self._objects[path] = (obj, lvm_id, uuid)
|
|
||||||
|
|
||||||
# Make sure we have one or the other
|
|
||||||
assert lvm_id or uuid
|
|
||||||
|
|
||||||
if lvm_id:
|
|
||||||
self._id_to_object_path[lvm_id] = path
|
|
||||||
|
|
||||||
if uuid:
|
|
||||||
self._id_to_object_path[uuid] = path
|
|
||||||
|
|
||||||
def _lookup_remove(self, obj_path):
|
|
||||||
# Note: Only called internally, lock implied
|
|
||||||
if obj_path in self._objects:
|
|
||||||
(obj, lvm_id, uuid) = self._objects[obj_path]
|
|
||||||
|
|
||||||
if lvm_id in self._id_to_object_path:
|
|
||||||
del self._id_to_object_path[lvm_id]
|
|
||||||
|
|
||||||
if uuid in self._id_to_object_path:
|
|
||||||
del self._id_to_object_path[uuid]
|
|
||||||
|
|
||||||
del self._objects[obj_path]
|
|
||||||
|
|
||||||
def lookup_update(self, dbus_obj, new_uuid, new_lvm_id):
|
|
||||||
with self.rlock:
|
|
||||||
obj_path = dbus_obj.dbus_object_path()
|
|
||||||
self._lookup_remove(obj_path)
|
|
||||||
self._lookup_add(
|
|
||||||
dbus_obj, obj_path,
|
|
||||||
new_lvm_id, new_uuid)
|
|
||||||
|
|
||||||
def object_paths_by_type(self, o_type):
|
|
||||||
with self.rlock:
|
|
||||||
rc = {}
|
|
||||||
|
|
||||||
for k, v in list(self._objects.items()):
|
|
||||||
if isinstance(v[0], o_type):
|
|
||||||
rc[k] = True
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def register_object(self, dbus_object, emit_signal=False):
|
|
||||||
"""
|
|
||||||
Given a dbus object add it to the collection
|
|
||||||
:param dbus_object: Dbus object to register
|
|
||||||
:param emit_signal: If true emit a signal for interfaces added
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
path, props = dbus_object.emit_data()
|
|
||||||
|
|
||||||
# print('Registering object path %s for %s' %
|
|
||||||
# (path, dbus_object.lvm_id))
|
|
||||||
|
|
||||||
# We want fast access to the object by a number of different ways
|
|
||||||
# so we use multiple hashs with different keys
|
|
||||||
self._lookup_add(dbus_object, path, dbus_object.lvm_id,
|
|
||||||
dbus_object.Uuid)
|
|
||||||
|
|
||||||
if emit_signal:
|
|
||||||
self.InterfacesAdded(path, props)
|
|
||||||
|
|
||||||
def remove_object(self, dbus_object, emit_signal=False):
|
|
||||||
"""
|
|
||||||
Given a dbus object, remove it from the collection and remove it
|
|
||||||
from the dbus framework as well
|
|
||||||
:param dbus_object: Dbus object to remove
|
|
||||||
:param emit_signal: If true emit the interfaces removed signal
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
# Store off the object path and the interface first
|
|
||||||
path = dbus_object.dbus_object_path()
|
|
||||||
interfaces = dbus_object.interface()
|
|
||||||
|
|
||||||
# print 'UN-Registering object path %s for %s' % \
|
|
||||||
# (path, dbus_object.lvm_id)
|
|
||||||
|
|
||||||
self._lookup_remove(path)
|
|
||||||
|
|
||||||
# Remove from dbus library
|
|
||||||
dbus_object.remove_from_connection(cfg.bus, path)
|
|
||||||
|
|
||||||
# Optionally emit a signal
|
|
||||||
if emit_signal:
|
|
||||||
self.InterfacesRemoved(path, interfaces)
|
|
||||||
|
|
||||||
def get_object_by_path(self, path):
|
|
||||||
"""
|
|
||||||
Given a dbus path return the object registered for it
|
|
||||||
:param path: The dbus path
|
|
||||||
:return: The object
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
if path in self._objects:
|
|
||||||
return self._objects[path][0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_object_by_uuid_lvm_id(self, uuid, lvm_id):
|
|
||||||
with self.rlock:
|
|
||||||
return self.get_object_by_path(
|
|
||||||
self.get_object_path_by_uuid_lvm_id(uuid, lvm_id))
|
|
||||||
|
|
||||||
def get_object_by_lvm_id(self, lvm_id):
|
|
||||||
"""
|
|
||||||
Given an lvm identifier, return the object registered for it
|
|
||||||
:param lvm_id: The lvm identifier
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
if lvm_id in self._id_to_object_path:
|
|
||||||
return self.get_object_by_path(self._id_to_object_path[lvm_id])
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_object_path_by_lvm_id(self, lvm_id):
|
|
||||||
"""
|
|
||||||
Given an lvm identifier, return the object path for it
|
|
||||||
:param lvm_id: The lvm identifier
|
|
||||||
:return: Object path or '/' if not found
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
if lvm_id in self._id_to_object_path:
|
|
||||||
return self._id_to_object_path[lvm_id]
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
def _uuid_verify(self, path, uuid, lvm_id):
|
|
||||||
"""
|
|
||||||
Ensure uuid is present for a successful lvm_id lookup
|
|
||||||
NOTE: Internal call, assumes under object manager lock
|
|
||||||
:param path: Path to object we looked up
|
|
||||||
:param uuid: lvm uuid to verify
|
|
||||||
:param lvm_id: lvm_id used to find object
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
# This gets called when we found an object based on lvm_id, ensure
|
|
||||||
# uuid is correct too, as they can change. There is no durable
|
|
||||||
# non-changeable name in lvm
|
|
||||||
if lvm_id != uuid:
|
|
||||||
if uuid and uuid not in self._id_to_object_path:
|
|
||||||
obj = self.get_object_by_path(path)
|
|
||||||
self._lookup_add(obj, path, lvm_id, uuid)
|
|
||||||
|
|
||||||
def _lvm_id_verify(self, path, uuid, lvm_id):
|
|
||||||
"""
|
|
||||||
Ensure lvm_id is present for a successful uuid lookup
|
|
||||||
NOTE: Internal call, assumes under object manager lock
|
|
||||||
:param path: Path to object we looked up
|
|
||||||
:param uuid: uuid used to find object
|
|
||||||
:param lvm_id: lvm_id to verify
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
# This gets called when we found an object based on uuid, ensure
|
|
||||||
# lvm_id is correct too, as they can change. There is no durable
|
|
||||||
# non-changeable name in lvm
|
|
||||||
if lvm_id != uuid:
|
|
||||||
if lvm_id and lvm_id not in self._id_to_object_path:
|
|
||||||
obj = self.get_object_by_path(path)
|
|
||||||
self._lookup_add(obj, path, lvm_id, uuid)
|
|
||||||
|
|
||||||
def _id_lookup(self, the_id):
|
|
||||||
path = None
|
|
||||||
|
|
||||||
if the_id:
|
|
||||||
# The _id_to_object_path contains hash keys for everything, so
|
|
||||||
# uuid and lvm_id
|
|
||||||
if the_id in self._id_to_object_path:
|
|
||||||
path = self._id_to_object_path[the_id]
|
|
||||||
else:
|
|
||||||
if "/" in the_id:
|
|
||||||
if the_id.startswith('/'):
|
|
||||||
# We could have a pv device path lookup that failed,
|
|
||||||
# lets try canonical form and try again.
|
|
||||||
canonical = os.path.realpath(the_id)
|
|
||||||
if canonical in self._id_to_object_path:
|
|
||||||
path = self._id_to_object_path[canonical]
|
|
||||||
else:
|
|
||||||
vg, lv = the_id.split("/", 1)
|
|
||||||
int_lvm_id = vg + "/" + ("[%s]" % lv)
|
|
||||||
if int_lvm_id in self._id_to_object_path:
|
|
||||||
path = self._id_to_object_path[int_lvm_id]
|
|
||||||
return path
|
|
||||||
|
|
||||||
def get_object_path_by_uuid_lvm_id(self, uuid, lvm_id, path_create=None):
|
|
||||||
"""
|
|
||||||
For a given lvm asset return the dbus object path registered for it.
|
|
||||||
This method first looks up by uuid and then by lvm_id. You
|
|
||||||
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
|
|
||||||
If the object is not found and path_create is a not None, the
|
|
||||||
path_create function will be called to create a new object path and
|
|
||||||
register it with the object manager for the specified uuid & lvm_id.
|
|
||||||
Note: If path create is not None, uuid and lvm_id cannot be equal
|
|
||||||
:param uuid: The uuid for the lvm object we are searching for
|
|
||||||
:param lvm_id: The lvm name (eg. pv device path, vg name, lv full name)
|
|
||||||
:param path_create: If not None, create the path using this function if
|
|
||||||
we fail to find the object by uuid or lvm_id.
|
|
||||||
:returns None if lvm asset not found and path_create == None otherwise
|
|
||||||
a valid dbus object path
|
|
||||||
"""
|
|
||||||
with self.rlock:
|
|
||||||
assert lvm_id
|
|
||||||
assert uuid
|
|
||||||
|
|
||||||
if path_create:
|
|
||||||
assert uuid != lvm_id
|
|
||||||
|
|
||||||
# Check for Manager.LookUpByLvmId query, we cannot
|
|
||||||
# check/verify/update the uuid and lvm_id lookups so don't!
|
|
||||||
if uuid == lvm_id:
|
|
||||||
path = self._id_lookup(lvm_id)
|
|
||||||
else:
|
|
||||||
# We have a uuid and a lvm_id we can do sanity checks to ensure
|
|
||||||
# that they are consistent
|
|
||||||
|
|
||||||
# If a PV is missing it's device path is '[unknown]' or some
|
|
||||||
# other text derivation of unknown. When we find that a PV is
|
|
||||||
# missing we will clear out the lvm_id as it's likely not unique
|
|
||||||
# and thus not useful and potentially harmful for lookups.
|
|
||||||
if path_create == pv_obj_path_generate and \
|
|
||||||
cfg.db.pv_missing(uuid):
|
|
||||||
lvm_id = None
|
|
||||||
|
|
||||||
# Lets check for the uuid first
|
|
||||||
path = self._id_lookup(uuid)
|
|
||||||
if path:
|
|
||||||
# Verify the lvm_id is sane
|
|
||||||
self._lvm_id_verify(path, uuid, lvm_id)
|
|
||||||
else:
|
|
||||||
# Unable to find by UUID, lets lookup by lvm_id
|
|
||||||
path = self._id_lookup(lvm_id)
|
|
||||||
if path:
|
|
||||||
# Verify the uuid is sane
|
|
||||||
self._uuid_verify(path, uuid, lvm_id)
|
|
||||||
else:
|
|
||||||
# We have exhausted all lookups, let's create if we can
|
|
||||||
if path_create:
|
|
||||||
path = path_create()
|
|
||||||
self._lookup_add(None, path, lvm_id, uuid)
|
|
||||||
|
|
||||||
# print('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
|
|
||||||
# (uuid, lvm_id, str(path_create), str(gen_new), path))
|
|
||||||
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectManagerLock(object):
|
|
||||||
"""
|
|
||||||
The sole purpose of this class is to allow other code the ability to
|
|
||||||
lock the object manager using a `with` statement, eg.
|
|
||||||
|
|
||||||
with cfg.om.locked():
|
|
||||||
# Do stuff with object manager
|
|
||||||
|
|
||||||
This will ensure that the lock is always released (assuming this is done
|
|
||||||
correctly)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, recursive_lock):
|
|
||||||
self._lock = recursive_lock
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
# Acquire lock
|
|
||||||
self._lock.acquire()
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
def __exit__(self, e_type, e_value, e_traceback):
|
|
||||||
# Release lock
|
|
||||||
self._lock.release()
|
|
||||||
self._lock = None
|
|
||||||
@@ -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/>.
|
|
||||||
|
|
||||||
LVM_BINARY = "@LVM_PATH@"
|
|
||||||
@@ -1,273 +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 . import utils
|
|
||||||
from . import cfg
|
|
||||||
import dbus
|
|
||||||
from .cfg import PV_INTERFACE
|
|
||||||
from . import cmdhandler
|
|
||||||
from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
|
|
||||||
lv_object_path_method
|
|
||||||
from .loader import common
|
|
||||||
from .request import RequestEntry
|
|
||||||
from .state import State
|
|
||||||
from .utils import round_size
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
def pvs_state_retrieve(selection, cache_refresh=True):
|
|
||||||
rc = []
|
|
||||||
|
|
||||||
if cache_refresh:
|
|
||||||
cfg.db.refresh()
|
|
||||||
|
|
||||||
for p in cfg.db.fetch_pvs(selection):
|
|
||||||
rc.append(
|
|
||||||
PvState(
|
|
||||||
p["pv_name"], p["pv_uuid"], p["pv_name"],
|
|
||||||
p["pv_fmt"], n(p["pv_size"]), n(p["pv_free"]),
|
|
||||||
n(p["pv_used"]), n(p["dev_size"]), n(p["pv_mda_size"]),
|
|
||||||
n(p["pv_mda_free"]), int(p["pv_ba_start"]),
|
|
||||||
n(p["pv_ba_size"]), n(p["pe_start"]),
|
|
||||||
int(p["pv_pe_count"]), int(p["pv_pe_alloc_count"]),
|
|
||||||
p["pv_attr"], p["pv_tags"], p["vg_name"], p["vg_uuid"]))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
|
|
||||||
def load_pvs(device=None, object_path=None, refresh=False, emit_signal=False,
|
|
||||||
cache_refresh=True):
|
|
||||||
return common(
|
|
||||||
pvs_state_retrieve, (Pv,), device, object_path, refresh,
|
|
||||||
emit_signal, cache_refresh)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
class PvState(State):
|
|
||||||
@property
|
|
||||||
def lvm_id(self):
|
|
||||||
return self.lvm_path
|
|
||||||
|
|
||||||
def _lv_object_list(self, vg_name):
|
|
||||||
rc = []
|
|
||||||
if vg_name:
|
|
||||||
for lv in sorted(cfg.db.pv_contained_lv(self.lvm_id)):
|
|
||||||
lv_uuid, lv_name, meta, segs = lv
|
|
||||||
full_name = "%s/%s" % (vg_name, lv_name)
|
|
||||||
|
|
||||||
path_create = lv_object_path_method(lv_name, meta)
|
|
||||||
lv_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
lv_uuid, full_name, path_create)
|
|
||||||
|
|
||||||
rc.append((lv_path, segs))
|
|
||||||
return rc
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyPep8Naming
|
|
||||||
def __init__(self, lvm_path, Uuid, Name,
|
|
||||||
Fmt, SizeBytes, FreeBytes, UsedBytes, DevSizeBytes,
|
|
||||||
MdaSizeBytes, MdaFreeBytes, BaStart, BaSizeBytes,
|
|
||||||
PeStart, PeCount, PeAllocCount, attr, Tags, vg_name,
|
|
||||||
vg_uuid):
|
|
||||||
utils.init_class_from_arguments(self)
|
|
||||||
self.pe_segments = cfg.db.pv_pe_segments(Uuid)
|
|
||||||
|
|
||||||
self.lv = self._lv_object_list(vg_name)
|
|
||||||
|
|
||||||
if vg_name:
|
|
||||||
self.vg_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
|
||||||
vg_uuid, vg_name, vg_obj_path_generate)
|
|
||||||
else:
|
|
||||||
self.vg_path = '/'
|
|
||||||
|
|
||||||
def identifiers(self):
|
|
||||||
return (self.Uuid, self.lvm_path)
|
|
||||||
|
|
||||||
def create_dbus_object(self, path):
|
|
||||||
if not path:
|
|
||||||
path = cfg.om.get_object_path_by_uuid_lvm_id(self.Uuid, self.Name,
|
|
||||||
pv_obj_path_generate)
|
|
||||||
return Pv(path, self)
|
|
||||||
|
|
||||||
# noinspection PyMethodMayBeStatic
|
|
||||||
def creation_signature(self):
|
|
||||||
return (Pv, pv_obj_path_generate)
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'Uuid', 's') # PV UUID/pv_uuid
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'Name', 's') # PV/pv_name
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'Fmt', 's') # Fmt/pv_fmt
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'SizeBytes', 't') # PSize/pv_size
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'FreeBytes', 't') # PFree/pv_free
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'UsedBytes', 't') # Used/pv_used
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'DevSizeBytes', 't') # DevSize/dev_size
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'MdaSizeBytes', 't') # PMdaSize/pv_mda_size
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'MdaFreeBytes', 't') # PMdaFree/pv_mda_free
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'BaStart', 't') # BA start/pv_ba_start
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'BaSizeBytes', 't') # BA size/pv_ba_size
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'PeStart', 't') # 1st PE/pe_start
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'PeCount', 't') # PE/pv_pe_count
|
|
||||||
@utils.dbus_property(PV_INTERFACE, 'PeAllocCount', 't') # PE Allocation count
|
|
||||||
class Pv(AutomatedProperties):
|
|
||||||
# For properties that we need custom handlers we need these, otherwise
|
|
||||||
# we won't get our introspection data
|
|
||||||
_Tags_meta = ("as", PV_INTERFACE)
|
|
||||||
_PeSegments_meta = ("a(tt)", PV_INTERFACE)
|
|
||||||
_Exportable_meta = ("b", PV_INTERFACE)
|
|
||||||
_Allocatable_meta = ("b", PV_INTERFACE)
|
|
||||||
_Missing_meta = ("b", PV_INTERFACE)
|
|
||||||
_Lv_meta = ("a(oa(tts))", PV_INTERFACE)
|
|
||||||
_Vg_meta = ("o", PV_INTERFACE)
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal,PyPep8Naming
|
|
||||||
def __init__(self, object_path, state_obj):
|
|
||||||
super(Pv, self).__init__(object_path, pvs_state_retrieve)
|
|
||||||
self.set_interface(PV_INTERFACE)
|
|
||||||
self.state = state_obj
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _remove(pv_uuid, pv_name, remove_options):
|
|
||||||
# Remove the PV, if successful then remove from the model
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
rc, out, err = cmdhandler.pv_remove(pv_name, remove_options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
# Need to work on error handling, need consistent
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'PV with uuid %s and name %s not present!' %
|
|
||||||
(pv_uuid, pv_name))
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=PV_INTERFACE,
|
|
||||||
in_signature='ia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def Remove(self, tmo, remove_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Pv._remove,
|
|
||||||
(self.Uuid, self.lvm_id, remove_options),
|
|
||||||
cb, cbe, return_tuple=False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _resize(pv_uuid, pv_name, new_size_bytes, resize_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
rc, out, err = cmdhandler.pv_resize(pv_name, new_size_bytes,
|
|
||||||
resize_options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'PV with uuid %s and name %s not present!' %
|
|
||||||
(pv_uuid, pv_name))
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=PV_INTERFACE,
|
|
||||||
in_signature='tia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def ReSize(self, new_size_bytes, tmo, resize_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Pv._resize,
|
|
||||||
(self.Uuid, self.lvm_id, round_size(new_size_bytes),
|
|
||||||
resize_options), cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _allocation_enabled(pv_uuid, pv_name, yes_no, allocation_options):
|
|
||||||
# Make sure we have a dbus object representing it
|
|
||||||
dbo = cfg.om.get_object_by_uuid_lvm_id(pv_uuid, pv_name)
|
|
||||||
|
|
||||||
if dbo:
|
|
||||||
rc, out, err = cmdhandler.pv_allocatable(
|
|
||||||
pv_name, yes_no, allocation_options)
|
|
||||||
if rc == 0:
|
|
||||||
cfg.load()
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE, 'Exit code %s, stderr = %s' % (str(rc), err))
|
|
||||||
else:
|
|
||||||
raise dbus.exceptions.DBusException(
|
|
||||||
PV_INTERFACE,
|
|
||||||
'PV with uuid %s and name %s not present!' %
|
|
||||||
(pv_uuid, pv_name))
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
@dbus.service.method(
|
|
||||||
dbus_interface=PV_INTERFACE,
|
|
||||||
in_signature='bia{sv}',
|
|
||||||
out_signature='o',
|
|
||||||
async_callbacks=('cb', 'cbe'))
|
|
||||||
def AllocationEnabled(self, yes, tmo, allocation_options, cb, cbe):
|
|
||||||
r = RequestEntry(
|
|
||||||
tmo, Pv._allocation_enabled,
|
|
||||||
(self.Uuid, self.lvm_id,
|
|
||||||
yes, allocation_options),
|
|
||||||
cb, cbe, False)
|
|
||||||
cfg.worker_q.put(r)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Tags(self):
|
|
||||||
return utils.parse_tags(self.state.Tags)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def PeSegments(self):
|
|
||||||
if len(self.state.pe_segments):
|
|
||||||
return dbus.Array(self.state.pe_segments, signature='(tt)')
|
|
||||||
return dbus.Array([], '(tt)')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Exportable(self):
|
|
||||||
return dbus.Boolean(self.state.attr[1] == 'x')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Allocatable(self):
|
|
||||||
return dbus.Boolean(self.state.attr[0] == 'a')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Missing(self):
|
|
||||||
return dbus.Boolean(self.state.attr[2] == 'm')
|
|
||||||
|
|
||||||
def object_path(self):
|
|
||||||
return self._object_path
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lvm_id(self):
|
|
||||||
return self.state.lvm_id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def identifiers(self):
|
|
||||||
return self.state.identifiers()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Lv(self):
|
|
||||||
return dbus.Array(self.state.lv, signature="(oa(tts))")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Vg(self):
|
|
||||||
return dbus.ObjectPath(self.state.vg_path)
|
|
||||||
@@ -1,156 +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 threading
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
from gi.repository import GLib
|
|
||||||
from .job import Job
|
|
||||||
from . import cfg
|
|
||||||
import traceback
|
|
||||||
from .utils import log_error, mt_async_result
|
|
||||||
|
|
||||||
|
|
||||||
class RequestEntry(object):
|
|
||||||
def __init__(self, tmo, method, arguments, cb, cb_error,
|
|
||||||
return_tuple=True, job_state=None):
|
|
||||||
self.method = method
|
|
||||||
self.arguments = arguments
|
|
||||||
self.cb = cb
|
|
||||||
self.cb_error = cb_error
|
|
||||||
|
|
||||||
self.timer_id = -1
|
|
||||||
self.lock = threading.RLock()
|
|
||||||
self.done = False
|
|
||||||
self._result = None
|
|
||||||
self._job = None
|
|
||||||
self._rc = 0
|
|
||||||
self._rc_error = None
|
|
||||||
self._return_tuple = return_tuple
|
|
||||||
self._job_state = job_state
|
|
||||||
|
|
||||||
if tmo < 0:
|
|
||||||
# Client is willing to block forever
|
|
||||||
pass
|
|
||||||
elif tmo == 0:
|
|
||||||
self._return_job()
|
|
||||||
else:
|
|
||||||
# Note: using 990 instead of 1000 for second to ms conversion to
|
|
||||||
# account for overhead. Goal is to return just before the
|
|
||||||
# timeout amount has expired. Better to be a little early than
|
|
||||||
# late.
|
|
||||||
self.timer_id = GLib.timeout_add(
|
|
||||||
tmo * 990, RequestEntry._request_timeout, self)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _request_timeout(r):
|
|
||||||
"""
|
|
||||||
Method which gets called when the timer runs out!
|
|
||||||
:param r: RequestEntry which timed out
|
|
||||||
:return: Result of timer_expired
|
|
||||||
"""
|
|
||||||
return r.timer_expired()
|
|
||||||
|
|
||||||
def _return_job(self):
|
|
||||||
# Return job is only called when we create a request object or when
|
|
||||||
# we pop a timer. In both cases we are running in the correct context
|
|
||||||
# and do not need to schedule the call back in main context.
|
|
||||||
self._job = Job(self, self._job_state)
|
|
||||||
cfg.om.register_object(self._job, True)
|
|
||||||
if self._return_tuple:
|
|
||||||
self.cb(('/', self._job.dbus_object_path()))
|
|
||||||
else:
|
|
||||||
self.cb(self._job.dbus_object_path())
|
|
||||||
|
|
||||||
def run_cmd(self):
|
|
||||||
try:
|
|
||||||
result = self.method(*self.arguments)
|
|
||||||
self.register_result(result)
|
|
||||||
except Exception as e:
|
|
||||||
# Use the request entry to return the result as the client may
|
|
||||||
# have gotten a job by the time we hit an error
|
|
||||||
# Lets get the stacktrace and set that to the error message
|
|
||||||
st = traceback.format_exc()
|
|
||||||
cfg.blackbox.dump()
|
|
||||||
log_error("Exception returned to client: \n%s" % st)
|
|
||||||
self.register_error(-1, str(e), e)
|
|
||||||
|
|
||||||
def is_done(self):
|
|
||||||
with self.lock:
|
|
||||||
rc = self.done
|
|
||||||
return rc
|
|
||||||
|
|
||||||
def get_errors(self):
|
|
||||||
with self.lock:
|
|
||||||
return (self._rc, self._rc_error)
|
|
||||||
|
|
||||||
def result(self):
|
|
||||||
with self.lock:
|
|
||||||
if self.done:
|
|
||||||
return self._result
|
|
||||||
return '/'
|
|
||||||
|
|
||||||
def _reg_ending(self, result, error_rc=0, error_msg=None,
|
|
||||||
error_exception=None):
|
|
||||||
with self.lock:
|
|
||||||
self.done = True
|
|
||||||
if self.timer_id != -1:
|
|
||||||
# Try to prevent the timer from firing
|
|
||||||
GLib.source_remove(self.timer_id)
|
|
||||||
|
|
||||||
self._result = result
|
|
||||||
self._rc = error_rc
|
|
||||||
self._rc_error = error_msg
|
|
||||||
|
|
||||||
if not self._job:
|
|
||||||
# We finished and there is no job, so return result or error
|
|
||||||
# now!
|
|
||||||
# Note: If we don't have a valid cb or cbe, this indicates a
|
|
||||||
# request that doesn't need a response as we already returned
|
|
||||||
# one before the request was processed.
|
|
||||||
if error_rc == 0:
|
|
||||||
if self.cb:
|
|
||||||
if self._return_tuple:
|
|
||||||
mt_async_result(self.cb, (result, '/'))
|
|
||||||
else:
|
|
||||||
mt_async_result(self.cb, result)
|
|
||||||
else:
|
|
||||||
if self.cb_error:
|
|
||||||
if not error_exception:
|
|
||||||
if not error_msg:
|
|
||||||
error_exception = Exception(
|
|
||||||
"An error occurred, but no reason was "
|
|
||||||
"given, see service logs!")
|
|
||||||
else:
|
|
||||||
error_exception = Exception(error_msg)
|
|
||||||
|
|
||||||
mt_async_result(self.cb_error, error_exception)
|
|
||||||
else:
|
|
||||||
# We have a job and it's complete, indicate that it's done.
|
|
||||||
self._job.Complete = True
|
|
||||||
self._job = None
|
|
||||||
|
|
||||||
def register_error(self, error_rc, error_message, error_exception):
|
|
||||||
self._reg_ending('/', error_rc, error_message, error_exception)
|
|
||||||
|
|
||||||
def register_result(self, result):
|
|
||||||
self._reg_ending(result)
|
|
||||||
|
|
||||||
def timer_expired(self):
|
|
||||||
with self.lock:
|
|
||||||
# Set the timer back to -1 as we will get a warning if we try
|
|
||||||
# to remove a timer that doesn't exist
|
|
||||||
self.timer_id = -1
|
|
||||||
if not self.done:
|
|
||||||
# Create dbus job object and return path to caller
|
|
||||||
self._return_job()
|
|
||||||
else:
|
|
||||||
# The job is done, we have nothing to do
|
|
||||||
pass
|
|
||||||
|
|
||||||
return False
|
|
||||||
@@ -1,27 +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 abc import ABCMeta, abstractmethod
|
|
||||||
|
|
||||||
|
|
||||||
class State(object, metaclass=ABCMeta):
|
|
||||||
@abstractmethod
|
|
||||||
def lvm_id(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def identifiers(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def create_dbus_object(self, path):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '*****\n' + str(self.__dict__) + '\n******\n'
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user