diff --git a/Makefile.in b/Makefile.in index 482f14f..fed1756 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,7 +92,6 @@ SOURCE=\ thin-provisioning/restore_emitter.cc \ thin-provisioning/rmap_visitor.cc \ thin-provisioning/superblock.cc \ - thin-provisioning/shared_library_emitter.cc \ thin-provisioning/thin_check.cc \ thin-provisioning/thin_delta.cc \ thin-provisioning/thin_dump.cc \ @@ -119,10 +118,23 @@ ifeq ("@DEVTOOLS@", "yes") SOURCE+=$(DEVTOOLS_SOURCE) endif +ifeq ("@STATIC@", "yes") +SOURCE += thin-provisioning/static_library_emitter.cc +else +SOURCE += thin-provisioning/shared_library_emitter.cc +endif + CC:=@CC@ CXX:=@CXX@ STRIP:=@STRIP@ OBJECTS:=$(subst .cc,.o,$(SOURCE)) + +# FIXME OBJECTS += $(PLUGIN_LIBS) doesn't work, probably because it's empty at +# the time of use? +ifeq ("@STATIC@", "yes") +OBJECTS += contrib/*.a +endif + TOP_DIR:=@top_srcdir@ TOP_BUILDDIR:=@top_builddir@ CFLAGS+=-g -Wall -O3 -fPIC @@ -150,6 +162,10 @@ else CXXLIB+=-lstdc++ endif +ifeq ("@STATIC@", "yes") +LDFLAGS+=-static +endif + INSTALL:=@INSTALL@ PREFIX:=@prefix@ BINDIR:=$(DESTDIR)$(PREFIX)/sbin diff --git a/configure.ac b/configure.ac index 9b0b2ce..efca586 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,14 @@ AC_ARG_ENABLE(static_cxx, STATIC_CXX=$enableval, STATIC_CXX=no) AC_MSG_RESULT($STATIC_CXX) +################################################################################ +dnl -- Enable static linking. +AC_MSG_CHECKING(whether to statically link) +AC_ARG_ENABLE(static, + AC_HELP_STRING(--enable-static, [enable static link]), + STATIC=$enableval, STATIC=no) +AC_MSG_RESULT($STATIC) + ################################################################################ dnl -- Check for getopt AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.])) @@ -182,6 +190,7 @@ AC_SUBST(TESTING) AC_SUBST(THIN_PROVISIONING_TOOLS_VERSION) AC_SUBST(STATIC_CXX) AC_SUBST(DEVTOOLS) +AC_SUBST(STATIC) ################################################################################ dnl -- First and last lines should not contain files to generate in order to diff --git a/contrib/Makefile.in b/contrib/Makefile.in index 1df15ec..0b6c28f 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -1,20 +1,24 @@ +PLUGIN_LIBS= \ + contrib/thin_sexp_emitter.a \ + contrib/tmakatos_emitter.a \ + contrib/ewheeler_emitter.a + PLUGINS=\ contrib/thin_sexp_emitter.so \ contrib/tmakatos_emitter.so \ contrib/ewheeler_emitter.so -contrib: $(PLUGINS) +contrib: $(PLUGINS) $(PLUGIN_LIBS) -contrib/thin_sexp_emitter.so: contrib/thin_sexp_emitter.o +contrib/%.o: contrib/%.cc + $(V)echo " [CC] $@" + $(V)$(CC) $^ -o $@ + +contrib/%.a: contrib/%.o + $(V)echo " [AR] $@" + $(V)ar rcs $@ $^ + +contrib/%.so: contrib/%.a $(V)echo " [LD] $@" - $(V)$(CC) -shared -Wl,-soname,thin_sexp_emitter.so -o $@ $< - -contrib/tmakatos_emitter.so: contrib/tmakatos_emitter.o - $(V)echo " [LD] $@" - $(V)$(CC) -shared -Wl,-soname,tmakatos_emitter.so -o $@ $< - -contrib/ewheeler_emitter.so: contrib/ewheeler_emitter.o - $(V)echo " [LD] $@" - $(V)$(CC) -shared -Wl,-soname,ewheeler_emitter.so -o $@ $< - + $(V)$(CC) -shared -Wl,-soname,$@ -o $@ $< diff --git a/contrib/tmakatos_emitter.cc b/contrib/tmakatos_emitter.cc index 4699077..c2b1118 100644 --- a/contrib/tmakatos_emitter.cc +++ b/contrib/tmakatos_emitter.cc @@ -1,4 +1,5 @@ #include "thin-provisioning/emitter.h" +#include "contrib/tmakatos_emitter.h" #include #include @@ -8,7 +9,7 @@ using namespace thin_provisioning; //---------------------------------------------------------------- -namespace { +namespace tmakatos_emitter { template std::ostream &operator << (ostream &out, boost::optional const &maybe) { if (maybe) @@ -20,131 +21,108 @@ namespace { //------------------------------------------------ // binary generator //------------------------------------------------ - class binary_emitter : public emitter { - public: - binary_emitter(ostream &out) - : out_(out) { - } + binary_emitter::binary_emitter(ostream &out): out_(out) { + } - void begin_superblock(string const &uuid, - uint64_t time, - uint64_t trans_id, - boost::optional flags, - boost::optional version, - uint32_t data_block_size, - uint64_t nr_data_blocks, - boost::optional metadata_snap) { - } + void binary_emitter::begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + boost::optional flags, + boost::optional version, + uint32_t data_block_size, + uint64_t nr_data_blocks, + boost::optional metadata_snap) { + } - void end_superblock() { - } + void binary_emitter::end_superblock() { + } - void begin_device(uint32_t dev_id, - uint64_t mapped_blocks, - uint64_t trans_id, - uint64_t creation_time, - uint64_t snap_time) { - cur = 0; - bitmap = 0; - } + void binary_emitter::begin_device(uint32_t dev_id, + uint64_t mapped_blocks, + uint64_t trans_id, + uint64_t creation_time, + uint64_t snap_time) { + cur = 0; + bitmap = 0; + } - void end_device() { - emit_bmp(true); - } + void binary_emitter::end_device() { + emit_bmp(true); + } - void begin_named_mapping(string const &name) { } + void binary_emitter::begin_named_mapping(string const &name) { } - void end_named_mapping() { } + void binary_emitter::end_named_mapping() { } - void identifier(string const &name) { } - void range_map(uint64_t origin_begin, uint64_t, uint32_t, - uint64_t len) { + void binary_emitter::identifier(string const &name) { } - uint64_t n = origin_begin / unit; - uint64_t i; + void binary_emitter::range_map(uint64_t origin_begin, uint64_t, uint32_t, + uint64_t len) { - assert(n >= cur); - assert(len > 0); + uint64_t n = origin_begin / unit; + uint64_t i; - /* - * Cover the gap between the last emitted unit and the current one. - */ - if (n > cur) - do { emit_bmp(); } while (cur < n); - - /* - * Emit partial unit. - */ - if (origin_begin & (unit - 1)) { - const uint64_t j = min(len, - (origin_begin & ~(unit - 1)) + unit - origin_begin); - for (i = origin_begin; i < origin_begin + j; i++) - bitmap |= 1ULL << (i & (unit - 1)); - if (j == len) - return; - - emit_bmp(); - - len -= j; - origin_begin = i; - } - - /* - * Emit full units until end. - */ - n = (origin_begin + len) / unit; - while (cur < n) { - bitmap = ~0; - emit_bmp(); - len -= unit; - } - origin_begin = cur * unit; - - /* - * Emit final unit. - */ - for (i = origin_begin; i < origin_begin + len; i++) - bitmap |= 1ULL << (i & (unit - 1)); - } - - void single_map(uint64_t origin_block, uint64_t, uint32_t) { - range_map(origin_block, 0, 0, 1); - } - - private: - ostream &out_; - - /** - * The entire virtual block allocation bitmap is segmented into 64-bit - * sub-bitmaps (units). - */ - uint64_t bitmap; + assert(n >= cur); + assert(len > 0); /* - * Pointer to the current sub-bitmap (unit) that has not yet been - * emitted. + * Cover the gap between the last emitted unit and the current one. */ - uint64_t cur; + if (n > cur) + do { emit_bmp(); } while (cur < n); - /** - * Unit (sub-bitmap) size. Must be a power of 2. + /* + * Emit partial unit. */ - static const size_t unit = sizeof bitmap * CHAR_BIT; + if (origin_begin & (unit - 1)) { + const uint64_t j = min(len, + (origin_begin & ~(unit - 1)) + unit - origin_begin); + for (i = origin_begin; i < origin_begin + j; i++) + bitmap |= 1ULL << (i & (unit - 1)); + if (j == len) + return; - void emit_bmp(bool omit_if_zero = false) { - if (!bitmap && omit_if_zero) - out_.write((const char*)&bitmap, sizeof bitmap); - bitmap = 0; - cur++; + emit_bmp(); + + len -= j; + origin_begin = i; } - }; + + /* + * Emit full units until end. + */ + n = (origin_begin + len) / unit; + while (cur < n) { + bitmap = ~0; + emit_bmp(); + len -= unit; + } + origin_begin = cur * unit; + + /* + * Emit final unit. + */ + for (i = origin_begin; i < origin_begin + len; i++) + bitmap |= 1ULL << (i & (unit - 1)); + } + + void binary_emitter::single_map(uint64_t origin_block, uint64_t, uint32_t) { + range_map(origin_block, 0, 0, 1); + } + + void binary_emitter::emit_bmp(bool omit_if_zero) { + if (bitmap || !omit_if_zero) + out_.write((const char*)&bitmap, sizeof bitmap); + bitmap = 0; + cur++; + } } //---------------------------------------------------------------- extern "C" { emitter::ptr create_emitter(ostream &out) { - return emitter::ptr(new binary_emitter(out)); + return emitter::ptr(new tmakatos_emitter::binary_emitter(out)); } } diff --git a/contrib/tmakatos_emitter.h b/contrib/tmakatos_emitter.h new file mode 100644 index 0000000..51919b8 --- /dev/null +++ b/contrib/tmakatos_emitter.h @@ -0,0 +1,69 @@ +#ifndef _TMAKATOS_EMITTER_H_ +#define _TMAKATOS_EMITTER_H_ + +#include "thin-provisioning/emitter.h" +#include + +using namespace std; +using namespace thin_provisioning; + +namespace tmakatos_emitter { + class binary_emitter : public emitter { + public: + binary_emitter(ostream &out); + + void begin_superblock(string const &uuid, + uint64_t time, + uint64_t trans_id, + boost::optional flags, + boost::optional version, + uint32_t data_block_size, + uint64_t nr_data_blocks, + boost::optional metadata_snap); + + void end_superblock(); + + void begin_device(uint32_t dev_id, + uint64_t mapped_blocks, + uint64_t trans_id, + uint64_t creation_time, + uint64_t snap_time); + + void end_device(); + + void begin_named_mapping(string const &name); + + void end_named_mapping(); + + void identifier(string const &name); + + void range_map(uint64_t origin_begin, uint64_t, uint32_t, + uint64_t len); + + void single_map(uint64_t origin_block, uint64_t, uint32_t); + + private: + ostream &out_; + + /** + * The entire virtual block allocation bitmap is segmented into 64-bit + * sub-bitmaps (units). + */ + uint64_t bitmap; + + /* + * Pointer to the current sub-bitmap (unit) that has not yet been + * emitted. + */ + uint64_t cur; + + /** + * Unit (sub-bitmap) size. Must be a power of 2. + */ + static const size_t unit = sizeof bitmap * CHAR_BIT; + + void emit_bmp(bool omit_if_zero = false); + }; +} + +#endif /* _TMAKATOS_EMITTER_H_ */ diff --git a/persistent-data/file_utils.cc b/persistent-data/file_utils.cc index 88ee945..4853040 100644 --- a/persistent-data/file_utils.cc +++ b/persistent-data/file_utils.cc @@ -21,7 +21,8 @@ persistent_data::get_nr_blocks(string const &path, sector_t block_size) int r = ::stat(path.c_str(), &info); if (r) - throw runtime_error("Couldn't stat dev path"); + throw runtime_error("Couldn't stat dev path " + path + ": " + + strerror(errno)); if (S_ISREG(info.st_mode) && info.st_size) nr_blocks = div_up(info.st_size, block_size); diff --git a/thin-provisioning/static_library_emitter.cc b/thin-provisioning/static_library_emitter.cc new file mode 100644 index 0000000..8caa507 --- /dev/null +++ b/thin-provisioning/static_library_emitter.cc @@ -0,0 +1,22 @@ +#include "thin-provisioning/shared_library_emitter.h" +#include +#include "contrib/tmakatos_emitter.h" + +using namespace std; +using namespace thin_provisioning; + +//---------------------------------------------------------------- + +emitter::ptr +thin_provisioning::create_custom_emitter(string const &shared_lib, ostream &out) +{ + if (shared_lib != "tmakatos_emitter.so") + throw runtime_error(shared_lib + ": no such emitter"); + + cout << "XXX creating tmakatos_emitter" << endl; + cout << flush; + + return emitter::ptr(new tmakatos_emitter::binary_emitter(out)); +} + +//----------------------------------------------------------------