1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-21 15:33:18 +03:00

Compare commits

...

116 Commits

Author SHA1 Message Date
Alasdair G Kergon
a37fd93fbb pre-release 2015-08-26 23:11:13 +01:00
Alasdair G Kergon
8740b7cb77 vgdisplay: Drop error message for exported VGs.
Originally when vgdisplay encountered an exported VG it issued a
WARNING.  Commit d6b1de30 replaced this with an error message
but still exited with success (incorrect).  A backtrace was recently
added in commit b193809987.

As vgdisplay already states that the VG is exported in its output,
just drop these messages completely.
2015-08-26 21:11:46 +01:00
Alasdair G Kergon
746b1bcf2a libdm: Drop ignored duplicate export designation.
dm_stats_create_region is now assigned to DM_1_02_106 by default:
the DM_1_02_104 .exported_symbols file entry was moved into
libdm-stats.c as:
  DM_EXPORT_SYMBOL(dm_stats_create_region, 1_02_104)
so delete it from .exported_symbols.DM_1_02_104.
2015-08-26 17:30:36 +01:00
Alasdair G Kergon
34c956afc1 make.tmpl: Mark internal sharedlib symbols local.
Since commit 797c18d543 some internal symbols
have been exported in shared libraries by mistake because 'local: *' got
lost.  Fix the shell script not to compare the whole filename with
'Base'
2015-08-26 13:36:23 +01:00
Zdenek Kabelac
d0ff35c5a6 tests: update cache tests 2015-08-26 11:24:41 +02:00
Zdenek Kabelac
1307fafe0f man: replace to with for
Better word.
2015-08-26 11:24:41 +02:00
Zdenek Kabelac
9886fd236e cache: lvconvert accepts --cachemode for --cache
All cache args could be specified when caching LV
(means converting LV to cached).

When --cachemode arg is given during cache-pool conversion,
store it in the metadata.

https://bugzilla.redhat.com/show_bug.cgi?id=1255184
2015-08-26 11:24:41 +02:00
Zdenek Kabelac
a4fdfc098d cache: report cache pool attrs also for pools
Since cache-pool actualy keeps info about caching,
display this info for cache-pool LV as well
(matches info for cache LV when cache-pool is asociated with it).
2015-08-26 11:24:41 +02:00
Zdenek Kabelac
cbe81ad393 cache: no report error for cpool without mode
It's perferctly valid to not have cachemode for
unused cache-pool.

https://bugzilla.redhat.com/show_bug.cgi?id=1255184
2015-08-26 10:49:23 +02:00
Bryn M. Reeves
8c09f12943 makefiles: remove stray ')' 2015-08-25 19:05:45 +01:00
Bryn M. Reeves
19ef3e0f31 makefiles: fix ld version script generation for older make versions
Commit 82a27a8 introduced a change to the symbol versioning macros
that allows a new version of a function to be introduced while
keeping the old behaviour via a versioned symbol export. The new
symbol is listed in the current .exported_symbols.DM_* file and a
default (@@VERSION) binding is created during linking.

This broke the build on RHEL5, RHEL6 and Debian Lenny. This is
because the make version in these distros returns results from the
$(wildcard *) command in a different order to the RHEL7 and F22
versions: this affects the ordering of the generated .export.sym
version script:

RHEL7/F22
for i in ./.exported_symbols.Base ./.exported_symbols.DM_1_02_99
 ./.exported_symbols.DM_1_02_98 ./.exported_symbols.DM_1_02_97
 ./.exported_symbols.DM_1_02_106 ./.exported_symbols.DM_1_02_105
 ./.exported_symbols.DM_1_02_103 ./.exported_symbols.DM_1_02_101
 ./.exported_symbols.DM_1_02_104 ./.exported_symbols.DM_1_02_100

 290: 000000000003d101   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region_v1_02_104
*388: 000000000003cfc7   314 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region@@DM_1_02_106
 391: 000000000003d101   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region@DM_1_02_104
*552: 000000000003cfc7   314 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region
 944: 000000000003d101   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region_v1_02_104
 992: 000000000003d101   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region@DM_1_02_104

RHEL6:
for i in ./.exported_symbols.Base ./.exported_symbols.DM_1_02_100
 ./.exported_symbols.DM_1_02_101 ./.exported_symbols.DM_1_02_103
 ./.exported_symbols.DM_1_02_104 ./.exported_symbols.DM_1_02_105
 ./.exported_symbols.DM_1_02_106 ./.exported_symbols.DM_1_02_97
 ./.exported_symbols.DM_1_02_98 ./.exported_symbols.DM_1_02_99; do\

 290: 000000000003d0e1   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region_v1_02_104
 390: 000000000003d0e1   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region@DM_1_02_104
*479: 000000000003cfa7   314 FUNC    LOCAL  DEFAULT   12 dm_stats_create_region
 944: 000000000003d0e1   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region_v1_02_104
 992: 000000000003d0e1   106 FUNC    GLOBAL DEFAULT   12 dm_stats_create_region@DM_1_02_104

The F22 build has the correct behaviour (although the sort order is
inconsistent) but on RHEL6 the 1_02_106 symbol file appears after
version 1_02_104 which introduced the original symbol. This causes
the later version of the symbol to lose its version binding and be
reduced to local scope.

If using un-versioned exports of the current version of a symbol
(i.e.  exported with the plain symbol name and no macro) and using
the linker script to set the symbol version, the current version
node must appear first in the version script: the un-versioned
symbol will be bound to the first version node found that contains
it.

On RHEL6 and the other older distros the original version of the
dm_stats_create_region() call sorted before the current version
(DM_1_02_104 vs. DM_1_02_106) leading to a subsequent link error for
the later symbol version:

dmsetup.o: In function `_do_stats_create_regions':
/root/src/git/lvm2/tools/dmsetup.c:4658: undefined reference to
`dm_stats_create_region'

Ensure that the ordering of entries in the version script is
consistent to avoid an old implementation shadowing a newer one by
sorting the list of file names before the loop:

  $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | sort -rnt_ -k5 )

This only sorts by patch level but this is sufficient to maintain
the correct order for current version files.

Tested on RHEL5, 6, 7 and F22.
2015-08-25 18:51:57 +01:00
Bryn M. Reeves
463f59eca4 dmstats: add 'precise' flag field to stats report
Add a flag indicating whether or not precise_timestamps are enabled for
a given region or area.
2015-08-24 20:03:21 +01:00
Bryn M. Reeves
e4145ebc47 dmstats: add --precise switch to enable nanosecond counters. 2015-08-24 20:03:21 +01:00
Bryn M. Reeves
567189cc76 libdm: add per region precise timestamps property methods 2015-08-24 20:03:21 +01:00
Bryn M. Reeves
f4262026b6 libdm: add precise timestamps support to libdm-stats
Add support for the kernel precise_timestamps feature. This allows
regions to be created using counters with nanosecond precision.

A new dm_stats method, dm_stats_set_precise_timestamps() causes all
future regions created with this handle to attempt to enable precise
counters.
2015-08-24 20:03:21 +01:00
Bryn M. Reeves
82a27a85b5 macros: fix default symbol export control
Fix the version export macros to make it possible to export two
different DM_* versions of a symbol: currently it is only possible for a
DM_* symbol to override a symbol in Base. Attempting to export two
symbols at different DM_* version levels (e.g. DM_1_02_104 and
DM_1_02_106) leads to a linker error due to a duplicate symbol
definition.

This is because the DM_EXPORTED_SYMBOL macro makes each exported symbol
the default (@@VERSION):

       __asm__(".symver " #func "_v" #ver ", " #func "@@DM_" #ver )

Fix the macro to use a single '@' for a symbols exported in multiple
versions and rename the macros to DM_EXPORT_*:

  DM_EXPORT_SYMBOL(func,ver)
  DM_EXPORT_SYMBOL_BASE(func,ver)

For functions that have multiple implementations these macros control
symbol export and versioning.

Function definitions that exist in only one version never need to use
these macros.

Backwards compatible implementations must include a version tag of
the form "_v1_02_104" as a suffix to the function name and use the
macro DM_EXPORT_SYMBOL to export the function and bind it to the
specified version string.

Since versioning is only available when compiling with GCC the entire
compatibility version should be enclosed in '#if defined(__GNUC__)',
for example:

  int dm_foo(int bar)
  {
    return bar;
  }

  #if defined(__GNUC__)
  // Backward compatible dm_foo() version 1.02.104
  int dm_foo_v1_02_104(void);
  int dm_foo_v1_02_104(void)
  {
    return 0;
  }
  DM_EXPORT_SYMBOL(dm_foo,1_02_104)
  #endif

A prototype for the compatibility version is required as these
functions must not be declared static.

The DM_EXPORT_SYMBOL_BASE macro is only used to export the base
versions of library symbols prior to the introduction of symbol
versioning: it must never be used for new symbols.
2015-08-24 20:03:21 +01:00
David Teigland
ba898b9ab6 tests: fix check for lvmlockd test 2015-08-21 17:00:21 -05:00
David Teigland
d827dd8b05 tests: add test for lvmlockd lock_args 2015-08-21 15:09:38 -05:00
David Teigland
e53758c5f6 tests: add lib function to test hidden LVs with lvs -a 2015-08-21 15:09:38 -05:00
David Teigland
1f27c9f6a4 tests: create/remove improvements for lvmlockd testing 2015-08-21 15:09:38 -05:00
David Teigland
d310e1f907 test: allow tests with lvmlockd 2015-08-21 15:09:38 -05:00
Zdenek Kabelac
81d4c4a84c WHATS_NEW 2015-08-21 15:37:56 +02:00
Zdenek Kabelac
1c811bfcd9 tests: check cachepolicy with lvconvert 2015-08-21 15:35:45 +02:00
Zdenek Kabelac
6d9e7d48fb cleanup: add . 2015-08-21 15:35:45 +02:00
Zdenek Kabelac
c868609cff man: fix sqm typo 2015-08-21 15:35:45 +02:00
Zdenek Kabelac
e4b9ac46d7 thin: metadata size cannot be reduced
Until we implement offline metadata manipulation,
the size of metadata LV cannot be reduced.
2015-08-21 15:35:45 +02:00
Zdenek Kabelac
45f3e8bbef cache: enable setting cachepolicy in lvconvert 2015-08-21 15:35:45 +02:00
David Teigland
1fae121b22 lvmlockd: fix sending debug info to lvmlockctl
Single messages sent over unix sockets are limited in
size to /proc/sys/net/core/wmem_max, so send the 1MB
debug buffer in smaller chunks to avoid EMSGSIZE.

Also look for EAGAIN and retry sending for a limited
time when the reader is slower than the writer.

Also shift the location of that code so it's the same
as other requests.
2015-08-20 14:07:11 -05:00
Heinz Mauelshagen
180f92d3dc WHATS_NEW: Update. 2015-08-20 19:06:47 +02:00
Ferenc Wágner
5476ee8655 cmirrord: avoid resync buffer overflow in LOG_SPRINT
Use snprintf() instead of sprintf() to exclude the possibility of
overflowing the resync history buffers.
2015-08-20 19:06:47 +02:00
Ferenc Wágner
3c396cf1e1 cmirrord: avoid debugging buffer overflow in LOG_SPRINT
Use snprintf() instead of sprintf() to exclude the possibility of
overflowing the debugging history buffers.
2015-08-20 19:06:47 +02:00
Ferenc Wágner
1ea1cb6dc9 cmirrord: fix stack smashing
With clusters larger than 3 nodes, the 32-byte debug buffer in
cpg_join_callback() is too small to contain all the node IDs, because
32-bit identifiers are generally rendered in 10 decimal digits.  No fixed
size is good in all cases, but this is conditionally logged debug info,
so we can simply truncate it.  Double the size, nevertheless.
2015-08-20 19:06:47 +02:00
Ferenc Wágner
8821cc416e cmirrord manual: add --foreground and --help options 2015-08-20 19:06:47 +02:00
Ferenc Wágner
92a4b5cc3c cmirrord: add --foreground and --help options. 2015-08-20 19:06:47 +02:00
Ferenc Wágner
c0d6056870 cmirrord: move generic setup from daemonize() to init_all()
Apply pidfile creation, removal and signal setup to foreground processes too.
2015-08-20 19:06:47 +02:00
Bryn M. Reeves
23770214a9 man: fix program_id string in dmstats.8.in 2015-08-20 17:27:28 +01:00
Bryn M. Reeves
386e91addb libdm: add dm_message_supports_precise_timestamps()
Add a function to test whether the kernel precise_timestamps
feature is available in the current device-mapper driver version.

Presence of precise_timestamps also implies the availability of
latency histograms.
2015-08-20 12:11:23 +01:00
David Teigland
62a87c84ed lvmlockd: ignore cmd close if no locks were taken
When a command closes its connection, don't waste
time looking for locks to purge if it did not make
any lock requests.
2015-08-19 12:16:04 -05:00
David Teigland
ce2e60ab45 lvmlockd: change log_error to log_debug for non error
It's not uncommon for a command like vgchange -an to
deactivate and unlock LVs that were not active, so
don't lock that as an error.
2015-08-19 11:43:39 -05:00
David Teigland
9c5a85ce24 lvmlockctl: fix debug output 2015-08-18 16:49:33 -05:00
David Teigland
c09dad71fb tests: fix lockd options in sanlock-prepare 2015-08-18 15:06:49 -05:00
David Teigland
d08427030d config: improve description text layout
This mainly makes the description text use 80 columns.
There are a few minor adjustments to wording to help
the text layout, and a couple minor improvements to
descriptions.
2015-08-18 14:02:32 -05:00
David Teigland
7b570840cd lockd: no error when unlock fails
The unlock call will fail in expected and normal cases,
and should not cause the command to fail.  (An actual
unlock in the lock manager should never fail.)
2015-08-18 11:18:40 -05:00
Bryn M. Reeves
c1bd76d6fc configure: check for -lm and log10 function
We already use -lm functions in a couple of places (these are
satisfied by gcc built-ins for most builds): add a configure.in
check and explicitly link to -lm.
2015-08-18 15:25:54 +01:00
Zdenek Kabelac
a7abade088 cleanup: compare fgets pointer
Check pointer for not being NULL.
2015-08-18 16:05:04 +02:00
Zdenek Kabelac
abb24370e9 cleanup: move var declaration 2015-08-18 16:05:04 +02:00
Zdenek Kabelac
6e1feb0f73 cleanup: preserve constness of some pointers 2015-08-18 16:05:04 +02:00
Zdenek Kabelac
ef7264807f cleanup: log_debug format matches args 2015-08-18 16:05:04 +02:00
Bryn M. Reeves
bc39506792 man: update dmstats.8.in examples 2015-08-18 14:40:45 +01:00
Zdenek Kabelac
28b4fa3e27 Revert "lvmcache: check for too long pvid"
This reverts commit 70db1d523d.
Since we use 'strncpy' even for case where it exactly matches
the buffer size and \0 is not expected to be added there.
2015-08-18 15:22:13 +02:00
Zdenek Kabelac
b193809987 debug: vgdisplay trace failing result code
Add stack on error path.
2015-08-18 15:00:08 +02:00
Zdenek Kabelac
a8fd88463e cleanup: trace error from lvmcache_update_vgname_and_id
Check result value from lvmcache_update_vgname_and_id().
2015-08-18 15:00:08 +02:00
Zdenek Kabelac
3a3e17d603 cleanup: check pthread result codes 2015-08-18 15:00:08 +02:00
Zdenek Kabelac
40af31729f cleanup: typo fix and drop \
Fix 'th e'  and use % directly.
2015-08-18 15:00:08 +02:00
Zdenek Kabelac
58f8f29c41 cleanup: add FMTssize_t
Add define to print nicely ssize_t type.
2015-08-18 15:00:08 +02:00
Zdenek Kabelac
3d08a49790 cleanup: add cast 2015-08-18 15:00:08 +02:00
Zdenek Kabelac
55a9262bdb cleanup: unused header files (Coverity) 2015-08-18 15:00:08 +02:00
Zdenek Kabelac
ba94d0f144 libdm: simplify dmstats formula.
Since we check for stats for not being 0,
simplify the operation and use a single division.
2015-08-18 15:00:08 +02:00
Zdenek Kabelac
ae4db9f302 lockd: check for failing unlock
Avoid ignoring unlocking error.
2015-08-18 15:00:07 +02:00
Zdenek Kabelac
70db1d523d lvmcache: check for too long pvid 2015-08-18 14:53:36 +02:00
Bryn M. Reeves
8e229cb7ea dmstats: reduce minimum field widths 2015-08-18 10:30:53 +01:00
Bryn M. Reeves
13d3eeb2ee dmstats: fix type formatting
Fix several instances of 'const char * const*' to be:

  'const char * const *'
2015-08-18 10:30:53 +01:00
David Teigland
dece918bc8 config: create lists of accepted values in descriptions 2015-08-17 14:50:41 -05:00
David Teigland
b091c37595 config: add empty lines around examples
When --withspaces is used, a blank line is
added before and after an Example section,
making the text less dense.
2015-08-17 13:52:34 -05:00
David Teigland
ca70770cfd config: recognize a blank comment line
Consider the comment line "#\n" to be a blank line, and
print a blank line at that position when --withspaces is set.
2015-08-17 13:52:34 -05:00
David Teigland
5243a81c29 config: explain automatic default values
Before printing a commented automatic config value,
print a line describing what it is.  Otherwise, the
commented value can look like it's a part of an
example preceding it.
2015-08-17 13:52:34 -05:00
Bryn M. Reeves
12acf852c5 dmsetup: check timerfd reads for valid byte count (Coverity)
The timerfd guarantees that it will return 8 bytes when a read(2)
is issued (a uint64_t giving the number of timer events during the
call). Check that it does so and log a non-fatal error if the byte
count is not 8.
2015-08-17 19:28:53 +01:00
Bryn M. Reeves
074b5de771 libdm: check for zero in _nr_areas() (Coverity) 2015-08-17 18:37:16 +01:00
Bryn M. Reeves
69fa16048a dmstats: check for zero in _nr_areas_from_step() (Coverity) 2015-08-17 18:37:16 +01:00
Bryn M. Reeves
b01e9651b0 dmsetup: make sure subcommand is initialised (Coverity) 2015-08-17 18:37:16 +01:00
Bryn M. Reeves
8967776713 libdm: do not read region before checking dms for NULL (Coverity)
dm_stats_get_area_start() attempts to assign a region pointer from
a stats handle before checking it is non-NULL: move the assignment
after the test.
2015-08-17 18:37:16 +01:00
Alasdair G Kergon
d1c65d1b28 post-release 2015-08-17 17:26:20 +01:00
Alasdair G Kergon
be1db6b6c1 pre-release 2015-08-17 17:20:14 +01:00
Bryn M. Reeves
4227b2ebb4 libdm-stats: only return uint64_t when required
Several interfaced in libdm-stats return a uint64_t when it is
only used to signal success/failure: change all these uses to
return a simple int instead.
2015-08-17 16:59:52 +01:00
Alasdair G Kergon
15e20bb5c0 conf: Regenerate example.conf. 2015-08-17 16:51:43 +01:00
Zdenek Kabelac
80bc87e377 cache: more comments for new setting 2015-08-17 17:26:39 +02:00
Zdenek Kabelac
77357081c8 tests: update thin test
Since we now let pass activation of thin-pool 'off-by-one' for
plain 'vgchange -ay' update the test to use higher TID.
2015-08-17 17:07:09 +02:00
Zdenek Kabelac
4b28383b1c cache: move detection code to cache_set_policy
Move code which runtime detects settings for cache_policy
out of config dir to cache seg handling code.

Also mark cache_mode as command profilable setting.
2015-08-17 15:52:06 +02:00
Zdenek Kabelac
94c56559ca dmsetup: fix usage of ifdefs 2015-08-17 15:52:06 +02:00
Bryn M. Reeves
427d0a5e92 libdm: ensure dm_stats_get_area_offset() returns a value 2015-08-17 14:40:48 +01:00
Alasdair G Kergon
623b46a17d device: Don't try to close config file on failure.
$file: open failed: Permission denied
Failed to load config file $file
Attempt to close device '$file' which is not open.
2015-08-17 12:57:01 +01:00
Zdenek Kabelac
a606966029 tests: Revert update for new thin pool messaging
This reverts commit 3dbb9a57ca.
Original code is back as the code restored previous TID handling.
2015-08-17 11:25:03 +02:00
Zdenek Kabelac
79ea81b8a8 thin: restore transaction_id handling
Revert back to already existing behavior which has been slightly
modified by a900d150e4.

At the end however it seem to be equal to change TID right with first
metadata write.

Existing code missed handling for 'unused' thin-pool which would
require to also check empty message list for TID==0.

So with the fix we now again preserve 'active' thin-pool volume
when first thin volume is created - this property was lost and caused
problems in cluster, where the lock was hold, but volume was no longer
active on the node.

Another missing part was the proper support for already increased,
but unfinished TID change.

So going back here with existing logic -

TID is increased with first MDA update.

Code allows start with either same TID or (TID-1).

If there are messages, TID must be lower by 1 for sending,
otherwise messages were already posted.
2015-08-17 11:25:03 +02:00
Zdenek Kabelac
d4c024c836 cache: use undefined settings for cache_policy
As cache_policy is evaluated in runtime, we no longer should use
CFG_COMMENTED, but have to switch to CFG_UNDEFINED.

So as long as the value is undefined, it's runtime evaluated.
Once it's set - it's always respected (no runtime fallback).

Also fix version of introduced settings to 2.2.128.
2015-08-17 11:25:03 +02:00
Alasdair G Kergon
b297d78367 WHATS_NEW: Update. 2015-08-16 01:16:16 +01:00
Bryn M. Reeves
4a6d5e2012 dmstats: fix --length argument
Commit f10ad95 introduced a regression causing the size of regions
passed in on the command line to be truncated to zero. Initialise
the 'this_len' variable to the supplied length to correct this.
2015-08-15 18:35:10 +01:00
Bryn M. Reeves
9d5cd4ca14 dmstats: fix new area count for 'create --areasize'
Commit f10ad95 introduced a regression in the calculation of the
number of areas in a region created with the --areasize switch:

vg_hex-lv_home: Created new region with 0 area(s) as region ID 1
vg_hex-lv_swap: Created new region with 0 area(s) as region ID 1

Fis this by using the correct region size when calculating the
value.
2015-08-15 00:42:51 +01:00
Bryn M. Reeves
0b487802a0 dmstats: change region fields prefix to 'region_' 2015-08-14 23:53:42 +01:00
Bryn M. Reeves
f3891e90e3 dmstats: make -v enable per area reports for 'stats list'
When dmstats is run with -v or higher enable a per-area reporting
mode for statistics regions. This will output one row per area
(rather than one row per region) and adds additional fields of use
when viewing areas:

 area_id    - index within the region assigned by libdm-stats
 area_start - the start location of the area in the containing
              device.
2015-08-14 22:03:37 +01:00
Bryn M. Reeves
0f3b81bb2e dmstats: add 'area_offset' field to stats reports 2015-08-14 22:03:37 +01:00
Bryn M. Reeves
00ed523659 libdm: add dm_stats_get_{current_}area_offset()
Add a method to retrieve the offset of an area within the
containing region (rather than the offset within the containing
device returned by dm_stats_get_area_start()).

Although users of the library can calculate this themselves it is
better to provide this through a method call to avoid users making
assumptions about the structure of regions and areas.
2015-08-14 22:03:37 +01:00
Bryn M. Reeves
77fae3d852 libdm: ensure dm_stats_get_area_start includes region offset
The dm_stats_get_area_start (and its '_current_' variant) methods
are expected to return the start sector of the area in the
containing device.

Make sure the call adds region->start to the returned value.
2015-08-14 22:03:37 +01:00
Bryn M. Reeves
16ff2d927f dmsetup: add support for 'stats report --raw'
Add a '--raw' switch to stats reports that causes us to report the
basic counter values rather than derived metrics for each visible
statistics region.
2015-08-14 22:03:37 +01:00
Bryn M. Reeves
fc7a27bc3d dmsetup: add prefixes for all report types
Add prefixes to all dmsetup report types to allow the 'group_all'
option to be effective:

  DR_NAME       name_
  DR_INFO       info_
  DR_DEPS       deps_
  DR_TREE       tree_
  DR_NAME       splitname_
2015-08-14 22:03:37 +01:00
Bryn M. Reeves
666722324f dmstats: add 'stat_' prefix to stats report columns 2015-08-14 22:03:37 +01:00
Marian Csontos
bfb58b7e1c spec: Add cache-*.profile 2015-08-14 21:45:11 +02:00
Bryn M. Reeves
8852b25fc7 dmsetup: do not track moving average for interval estimate
When run with full verbosity dmsetup or dmstats reports will
output a figure that tracks a moving average over a window of the
last two intervals:

Interval     #3        time delta:    999991087ns
Interval     #3     mean duration:    999907064ns, current err: -8913ns
End interval #3          duration:    999991087ns
Adjusted sample interval duration:    999991087ns

Due to the narrow window this is a very crude estimate and is only
of use to someone debugging or modifying the stats clock: remove
the value and the global variables used to track it.

Anyone with a particular use for this information can construct a
better mean by calculating the value of a greater number of
intervals.
2015-08-14 13:55:26 +01:00
Bryn M. Reeves
4d5b618d52 WHATS_NEW_DM: recent commits (stats field split and timestamp headers) 2015-08-14 13:43:12 +01:00
Bryn M. Reeves
e6724f0303 dmstats: make 'dmstats list' use common report infrastructure
Unlike 'info -c' and 'stats report' the 'dmstats list' subcommand
does its own report processing. This complicates the handling of
the DR_STATS and DR_STATS_META fields and leads to inconsistent
behaviour between the different commands. In particular it causes
'stats list' to segfault when using 'all' field options:

Segmentation fault (core dumped)

Delete _stats_list() entirely and adapt _stats_report so that it
can correctly format a DR_STATS_META-only report request.

This requires passing the subcommand into _report_init() where it
is used in addition to the command name to select the default set
of report fields for the 'list' and 'report' stats subcommands.

With this change both 'list' and 'report' dmstats report will use
the correct report object type and ensure that it is initialised
appropriately for the field selection in use.
2015-08-14 13:43:12 +01:00
Bryn M. Reeves
37dd26e322 dmstats: separate stats meta fields into their own report type
Although statistics and meta fields (region and area properties) share
the same object type the state of the handle they expect differs: meta
only expects a dm_stats_list() operation to have been performed whereas
statistics require a fully populated handle.

Distinguish between these requirements by separating the fields into
two distinct report types:

  DR_STATS = 32,
  DR_STATS_META = 64

The new category is described as "Mapped Device Statistics Region
Information" in the help text.
2015-08-14 13:43:03 +01:00
Bryn M. Reeves
f10ad95c36 dmstats: cleanup _do_stats_create_regions()
Make the use of the this_start and this_len variables easier to
follow and clarify the use of zero start and len arguments to
request a whole-device region.
2015-08-14 13:36:52 +01:00
Bryn M. Reeves
9b3dc72506 dmstats: add 'interval' and 'interval_ns' report fields
Add a pair of fields to expose the current per-interval duation
estimate. The 'interval' field provides a real value in units of
seconds and the 'interval_ns' field provides the same quantity
expressed as a whole number of nanoseconds.
2015-08-14 13:36:50 +01:00
Natanael Copa
4534f0fbcf libdm: do not in include internal bits/time.h header
Do not include bits/time.h as it is an internal libc header file.

A comment at the top of the glibc specific bits/time.h says:
"Never include this file directly; use <time.h> instead."

This fixes the following build error with musl libc:
libdm-timestamp.c:37:23: fatal error: bits/time.h: No such file or directory
---
Compile tested with Alpine Linx (musl libc) and ubuntu 15.04

 libdm/libdm-timestamp.c | 1 -
 1 file changed, 1 deletion(-)
2015-08-14 11:33:12 +01:00
Alasdair G Kergon
6a93206882 dmsetup: Fix dmsetup return code. 2015-08-14 00:09:40 +01:00
Alasdair G Kergon
043fb32c4b dmsetup: Restructure arg handling.
Introduce enums and global variables to record cleanly which command we
are processing and eliminate the historically inconsistent use of the
shifted argv[0] and fix assorted bugs discovered along the way.

Add dm_report_is_empty() to indicate there is no data awaiting output
and use this to suppress dmsetup report headings when no data is output
so we don't get a stray line saying 'Help' at the end of reporting help.

Define a report type (as the interface requires) so -o all selects
the right fields in splitname.  (A fix for stats list will follow.)

Exit immediately if no device is supplied to dmsetup wipe_table instead
of hitting errors later and failing.

Adjust the command name printed in usage/help output to match command
invoked (most of the time).
2015-08-13 22:30:39 +01:00
Bryn M. Reeves
b3cd5d2945 dmstats: do not use "region_id" in error messages
Refer to either '--regionid' or '--allregions' when the user fails
to specify either a single region ID or the --allregions switch.
2015-08-13 19:05:48 +01:00
Bryn M. Reeves
6b81ac5807 dmstats: replace --force with new stats-specific --alldevices
The '--force' switch is only used by dmstats to allow either
creation or deletion of one or more regions on all devices.

These operations do not carry any risk: just a possible mess of
region IDs to be cleaned up.

Remove the use of '--force' for stats commands and change current
uses to a new '--alldevices' switch.
2015-08-13 19:05:46 +01:00
Bryn M. Reeves
988ca74351 dmstats: improve region creation messages
The region creation message just outputs the new region_id, e.g.:

Created region: 0

This is fine when the device is unambigous (as above) but produces
unhelpful output when creating multiple regions, or regions on
multiple devices:

Created region: 0
Created region: 0
Created region: 1
Created region: 2
Created region: 0

To address this refactor _stats_create_segments() (previously only
used when creating one-region-per-target for --segments) into a
more general _do_stats_create_regions() that can create regions
for each segment, or a single region spanning either the entire
device or a specied start/len range.

This allows us to output all region creation messages from a
single point where both the device name and all information needed
to derive the number of areas is available.

This allows us to log all these facts in the resulting messages:

vg_hex-lv_home: Created new region with 13 area(s) as region ID 0
vg_hex-lv_home: Created new region with 4 area(s) as region ID 1
vg_hex-lv_home: Created new region with 1 area(s) as region ID 2
vg_hex-lv_swap: Created new region with 1 area(s) as region ID 0
vg_hex-lv_root: Created new region with 10 area(s) as region ID 0
luks-79733921-3f68-4c92-9eb7-d0aca4c6ba3e: Created new region with 17 area(s) as region ID 0
vg_hex-lv_images: Created new region with 20 area(s) as region ID 0
vg_hex-lv_images: Created new region with 4 area(s) as region ID 1
2015-08-13 19:05:45 +01:00
Bryn M. Reeves
86adb6ca63 dmsetup: make timekeeping debug messages more readable
Don't use cryptic abbreviations and make sure that all values can
be understood by someone not familiar with the clock internals.

Include the current interval number (inverse of the _count) in all
interval update messages and attempt to align interval timestamp
logs for interval counts < 99,999.
2015-08-13 19:05:45 +01:00
Alasdair G Kergon
b22b7d7ba9 dmsetup: Use #define for command names. 2015-08-13 13:10:23 +01:00
Bryn M. Reeves
7995eedd35 dmstats: don't output column headings if report fails
If _stats_report fails (e.g. due to an invalid device on the
command line) destroy the _report to prevent stats columns headings
from being displayed.

This also requires a change in main to test the return from
_perform_command_for_all_repeatable_args inside the interval loop
and exit immediately in case of error.
2015-08-12 22:02:23 +01:00
Bryn M. Reeves
098528513f dmstats: don't output column headings when args checks fail
The clear, create, delete, and print commands do not use _report:
make sure it is freed and set to NULL before checking arguments.
2015-08-12 21:40:43 +01:00
David Teigland
829384f46d config: description updates
Make the first line of every description a complete one
line sentence for the benefit of lvmconfig --withsummary.
2015-08-12 15:35:45 -05:00
Bryn M. Reeves
e96041e18f dmsetup: only free resources once in the final interval
The _update_interval_times() function is called once per reported
object: when shutting down at the end of a run only the first call
should free timestamps. Clear the timestamp pointers after free
and use this to signal to other callers that the clock is already
shut down.
2015-08-12 19:16:05 +01:00
Zdenek Kabelac
0f45aa7f31 udev: fix missing escape for +
Commit 3ea396e9d2 missed to escape +
which is used by 'sed' as separator for 's'.
2015-08-12 19:46:44 +02:00
Zdenek Kabelac
2cf3336130 lvcreate: fix return value
Return correct 0 instead of NULL.
2015-08-12 19:46:43 +02:00
72 changed files with 3554 additions and 2268 deletions

View File

@@ -1 +1 @@
2.02.128(2)-git (2015-08-10)
2.02.129(2)-git (2015-08-26)

View File

@@ -1 +1 @@
1.02.105-git (2015-08-10)
1.02.106-git (2015-08-26)

View File

@@ -1,10 +1,22 @@
Version 2.02.128 -
Version 2.02.129 - 26th August 2015
===================================
Drop error message when vgdisplay encounters an exported VG. (2.02.27)
Fix shared library generation to stop exporting internal functions.(2.02.120)
Accept --cachemode with lvconvert.
Fix and improve reporting properties of cache-pool.
Enable usage of --cachepolicy and --cachesetting with lvconvert.
Don't allow to reduce size of thin-pool metadata.
Fix debug buffer overflows in cmirrord logging.
Add --foreground and --help to cmirrord.
Version 2.02.128 - 17th August 2015
===================================
Allocation setting cache_pool_cachemode is replaced by cache_mode.
Don't attempt to close config file that couldn't be opened.
Check for valid cache mode in validation of cache segment.
Enhance internal API cache_set_mode() and cache_set_policy().
Enhance toollib's get_cache_params().
Runtime detect presence of cache smq policy.
Add demo cache-mq and cache-smq profiles.
Change internal interface handling cache mode and policy.
When no cache policy specified, prefer smq (if available) over mq.
Add demo cache-mq and cache-smq profiles.
Add cmd profilable allocation/cache_policy,cache_settings,cache_mode.
Require cache_check 0.5.4 for use of --clear-needs-check-flag.
Fix lvmetad udev rules to not override SYSTEMD_WANTS, add the service instead.

View File

@@ -1,6 +1,24 @@
Version 1.02.105 -
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
===================================

File diff suppressed because it is too large Load Diff

View File

@@ -24,34 +24,33 @@ 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,
# 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.
#
# Example
# Set no system ID:
# system_id = ""
# Example:
# Set the system_id to the string 'host1'.
# 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.
# 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 a unique among all hosts,
# and must be between 1 and 2000.
# This must be unique among all hosts, and must be between 1 and 2000.
# This configuration option has an automatic default value.
# host_id = 0
}

46
configure vendored
View File

@@ -665,6 +665,7 @@ PYTHON_LIBDIRS
PYTHON_INCDIRS
PYTHON_BINDINGS
PTHREAD_LIBS
M_LIBS
POOL
PKGCONFIG
OCFDIR
@@ -12569,6 +12570,50 @@ if [ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
as_fn_error $? "Features cannot be 'shared' when building statically" "$LINENO" 5
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for log10 in -lm" >&5
$as_echo_n "checking for log10 in -lm... " >&6; }
if ${ac_cv_lib_m_log10+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char log10 ();
int
main ()
{
return log10 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_m_log10=yes
else
ac_cv_lib_m_log10=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_log10" >&5
$as_echo "$ac_cv_lib_m_log10" >&6; }
if test "x$ac_cv_lib_m_log10" = xyes; then :
M_LIBS="-lm"
else
hard_bailout
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5
$as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; }
@@ -14151,6 +14196,7 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
################################################################################

View File

@@ -1537,6 +1537,10 @@ if [[ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \
AC_MSG_ERROR([Features cannot be 'shared' when building statically])
fi
################################################################################
AC_CHECK_LIB(m, log10,
[M_LIBS="-lm"], hard_bailout)
################################################################################
AC_CHECK_LIB([pthread], [pthread_mutex_lock],
[PTHREAD_LIBS="-lpthread"], hard_bailout)
@@ -1984,6 +1988,7 @@ AC_SUBST(OCF)
AC_SUBST(OCFDIR)
AC_SUBST(PKGCONFIG)
AC_SUBST(POOL)
AC_SUBST(M_LIBS)
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PYTHON)
AC_SUBST(PYTHON_BINDINGS)

View File

@@ -855,12 +855,12 @@ static void main_loop(int cmd_timeout)
int quorate = clops->is_quorate();
int client_count = 0;
int max_fd = 0;
struct local_client *lastfd = &local_client_head;
struct local_client *nextfd = local_client_head.next;
/* Wait on the cluster FD and all local sockets/pipes */
local_client_head.fd = clops->get_main_cluster_fd();
FD_ZERO(&in);
struct local_client *lastfd = &local_client_head;
struct local_client *nextfd = local_client_head.next;
for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) {
client_count++;

View File

@@ -15,6 +15,7 @@
#include "link_mon.h"
#include "local.h"
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
@@ -32,14 +33,49 @@ static void daemonize(void);
static void init_all(void);
static void cleanup_all(void);
int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
static void usage (FILE *dest)
{
daemonize();
fprintf (dest, "Usage: cmirrord [options]\n"
" -f, --foreground stay in the foreground, log to the terminal\n"
" -h, --help print this help\n");
}
int main(int argc, char *argv[])
{
int foreground_mode = 0;
struct option longopts[] = {
{ "foreground", no_argument, NULL, 'f' },
{ "help" , no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
int opt;
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
switch (opt) {
case 'f':
foreground_mode = 1;
break;
case 'h':
usage (stdout);
exit (0);
default:
usage (stderr);
exit (2);
}
}
if (optind < argc) {
usage (stderr);
exit (2);
}
if (!foreground_mode)
daemonize();
init_all();
/* Parent can now exit, we're ready to handle requests */
kill(getppid(), SIGTERM);
if (!foreground_mode)
kill(getppid(), SIGTERM);
LOG_PRINT("Starting cmirrord:");
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
@@ -209,6 +245,16 @@ static void daemonize(void)
}
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
}
/*
* init_all
*
* Initialize modules. Exit on failure.
*/
static void init_all(void)
{
int r;
(void) dm_prepare_selinux_context(CMIRRORD_PIDFILE, S_IFREG);
if (dm_create_lockfile(CMIRRORD_PIDFILE) == 0)
@@ -227,16 +273,6 @@ static void daemonize(void)
signal(SIGUSR2, &sig_handler);
sigemptyset(&signal_mask);
signal_received = 0;
}
/*
* init_all
*
* Initialize modules. Exit on failure.
*/
static void init_all(void)
{
int r;
if ((r = init_local()) ||
(r = init_cluster())) {

View File

@@ -104,10 +104,11 @@ static SaVersionT version = { 'B', 1, 1 };
#endif
#define DEBUGGING_HISTORY 100
#define DEBUGGING_BUFLEN 128
#define LOG_SPRINT(cc, f, arg...) do { \
cc->idx++; \
cc->idx = cc->idx % DEBUGGING_HISTORY; \
sprintf(cc->debugging[cc->idx], f, ## arg); \
snprintf(cc->debugging[cc->idx], DEBUGGING_BUFLEN, f, ## arg); \
} while (0)
static int log_resp_rec = 0;
@@ -150,7 +151,7 @@ struct clog_cpg {
uint32_t checkpoint_requesters[MAX_CHECKPOINT_REQUESTERS];
struct checkpoint_data *checkpoint_list;
int idx;
char debugging[DEBUGGING_HISTORY][128];
char debugging[DEBUGGING_HISTORY][DEBUGGING_BUFLEN];
};
static struct dm_list clog_cpg_list;
@@ -1294,7 +1295,9 @@ static void cpg_join_callback(struct clog_cpg *match,
uint32_t my_pid = (uint32_t)getpid();
uint32_t lowest = match->lowest_id;
struct clog_request *rq;
char dbuf[32] = { 0 };
char dbuf[64] = { 0 };
char *dbuf_p = dbuf;
size_t dbuf_rem = sizeof dbuf;
/* Assign my_cluster_id */
if ((my_cluster_id == 0xDEAD) && (joined->pid == my_pid))
@@ -1310,9 +1313,17 @@ static void cpg_join_callback(struct clog_cpg *match,
if (joined->nodeid == my_cluster_id)
goto out;
for (i = 0; i < member_list_entries - 1; i++)
sprintf(dbuf+strlen(dbuf), "%u-", member_list[i].nodeid);
sprintf(dbuf+strlen(dbuf), "(%u)", joined->nodeid);
for (i = 0; i < member_list_entries - 1; i++) {
int written = snprintf(dbuf_p, dbuf_rem, "%u-", member_list[i].nodeid);
if (written < 0) continue; /* impossible */
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]",
SHORT_UUID(match->name.value), joined->nodeid, dbuf);

View File

@@ -32,12 +32,13 @@
#define LOG_OFFSET 2
#define RESYNC_HISTORY 50
#define RESYNC_BUFLEN 128
//static char resync_history[RESYNC_HISTORY][128];
//static int idx = 0;
#define LOG_SPRINT(_lc, f, arg...) do { \
lc->idx++; \
lc->idx = lc->idx % RESYNC_HISTORY; \
sprintf(lc->resync_history[lc->idx], f, ## arg); \
snprintf(lc->resync_history[lc->idx], RESYNC_BUFLEN, f, ## arg); \
} while (0)
struct log_header {
@@ -88,7 +89,7 @@ struct log_c {
size_t disk_size; /* size of disk_buffer in bytes */
void *disk_buffer; /* aligned memory for O_DIRECT */
int idx;
char resync_history[RESYNC_HISTORY][128];
char resync_history[RESYNC_HISTORY][RESYNC_BUFLEN];
};
struct mark_entry {

View File

@@ -151,13 +151,12 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
r_name, r_type, mode, sh_count, &ver);
/* when mode is not un, wait and print each lk line */
strcpy(r_name_out, r_name);
strcpy(r_type_out, r_type);
if (strcmp(mode, "un")) {
strcpy(r_name_out, r_name);
strcpy(r_type_out, r_type);
/* when mode is not un, wait and print each lk line */
if (strcmp(mode, "un"))
return;
}
/* when mode is un, there will be no lk lines, so print now */
@@ -229,7 +228,7 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
find_client_info(client_id, &pid, cl_name);
if (strcmp(op, "lock")) {
printf("OP %s pid %u (%s)", op, pid, cl_name);
printf("OP %s pid %u (%s)\n", op, pid, cl_name);
return;
}
@@ -380,6 +379,7 @@ static int setup_dump_socket(void)
rv = bind(s, (struct sockaddr *) &dump_addr, dump_addrlen);
if (rv < 0) {
rv = -errno;
if (!close(s))
log_error("failed to close dump socket");
return rv;
@@ -393,6 +393,7 @@ static int do_dump(const char *req_name)
daemon_reply reply;
int result;
int fd, rv = 0;
int count = 0;
fd = setup_dump_socket();
if (fd < 0) {
@@ -423,13 +424,18 @@ static int do_dump(const char *req_name)
memset(dump_buf, 0, sizeof(dump_buf));
rv = recvfrom(fd, dump_buf, dump_len, MSG_WAITALL,
retry:
rv = recvfrom(fd, dump_buf + count, dump_len - count, MSG_WAITALL,
(struct sockaddr *)&dump_addr, &dump_addrlen);
if (rv < 0) {
log_error("recvfrom error %d %d", rv, errno);
rv = -errno;
goto out;
}
count += rv;
if (count < dump_len)
goto retry;
rv = 0;
if ((info && dump) || !strcmp(req_name, "dump"))

View File

@@ -265,6 +265,10 @@ static int alloc_new_structs; /* used for initializing in setup_structs */
static int add_lock_action(struct action *act);
static int str_to_lm(const char *str);
static int clear_lockspace_inactive(char *name);
static int setup_dump_socket(void);
static void send_dump_buf(int fd, int dump_len);
static int dump_info(int *dump_len);
static int dump_log(int *dump_len);
static int _syslog_name_to_num(const char *name)
{
@@ -739,6 +743,10 @@ static const char *op_str(int x)
return "kill_vg";
case LD_OP_DROP_VG:
return "drop_vg";
case LD_OP_DUMP_LOG:
return "dump_log";
case LD_OP_DUMP_INFO:
return "dump_info";
default:
return "op_unknown";
};
@@ -1283,7 +1291,7 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
}
if (act->op != LD_OP_CLOSE)
log_error("S %s R %s res_unlock no locks", ls->name, r->name);
log_debug("S %s R %s res_unlock no locks", ls->name, r->name);
return -ENOENT;
do_unlock:
@@ -3414,6 +3422,8 @@ static void client_send_result(struct client *cl, struct action *act)
{
response res;
char result_flags[128];
int dump_len = 0;
int dump_fd = -1;
if (cl->dead) {
log_debug("client send %d skip dead", cl->id);
@@ -3498,6 +3508,33 @@ static void client_send_result(struct client *cl, struct action *act)
"lv_lock_args = %s", lv_args,
"result_flags = %s", result_flags[0] ? result_flags : "none",
NULL);
} else if (act->op == LD_OP_DUMP_LOG || act->op == LD_OP_DUMP_INFO) {
/*
* lvmlockctl creates the unix socket then asks us to write to it.
* FIXME: move processing this to a new dedicated query thread to
* avoid having a large data dump interfere with normal operation
* of the client thread?
*/
dump_fd = setup_dump_socket();
if (dump_fd < 0)
act->result = dump_fd;
else if (act->op == LD_OP_DUMP_LOG)
act->result = dump_log(&dump_len);
else if (act->op == LD_OP_DUMP_INFO)
act->result = dump_info(&dump_len);
else
act->result = -EINVAL;
log_debug("send %s[%d.%u] dump result %d dump_len %d",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
act->result, dump_len);
res = daemon_reply_simple("OK",
"result = %d", act->result,
"dump_len = %d", dump_len,
NULL);
} else {
/*
* A normal reply.
@@ -3521,6 +3558,12 @@ static void client_send_result(struct client *cl, struct action *act)
buffer_destroy(&res.buffer);
client_resume(cl);
if (dump_fd >= 0) {
/* To avoid deadlock, send data here after the reply. */
send_dump_buf(dump_fd, dump_len);
close(dump_fd);
}
}
/* called from client_thread */
@@ -3529,6 +3572,13 @@ static void client_purge(struct client *cl)
struct lockspace *ls;
struct action *act;
/*
* If the client made no lock requests, there can be
* no locks to release for it.
*/
if (!cl->lock_ops)
return;
pthread_mutex_lock(&lockspaces_mutex);
list_for_each_entry(ls, &lockspaces, list) {
if (!(act = alloc_action()))
@@ -3887,23 +3937,43 @@ static int setup_dump_socket(void)
return s;
}
static int send_dump_buf(int fd, int dump_len)
#define MAX_SEND_LEN 65536
#define RESEND_DELAY_US 1000
#define RESEND_DELAY_US_MAX 500000
static void send_dump_buf(int fd, int dump_len)
{
int pos = 0;
int ret;
int send_len;
int delay = 0;
retry:
ret = sendto(fd, dump_buf + pos, dump_len - pos, MSG_DONTWAIT | MSG_NOSIGNAL,
if (!dump_len)
return;
repeat:
if (dump_len - pos < MAX_SEND_LEN)
send_len = dump_len - pos;
else
send_len = MAX_SEND_LEN;
ret = sendto(fd, dump_buf + pos, send_len, MSG_NOSIGNAL | MSG_DONTWAIT,
(struct sockaddr *)&dump_addr, dump_addrlen);
if (ret <= 0)
return ret;
if (ret < 0) {
if ((errno == EAGAIN || errno == EINTR) && (delay < RESEND_DELAY_US_MAX)) {
usleep(RESEND_DELAY_US);
delay += RESEND_DELAY_US;
goto repeat;
}
log_error("send_dump_buf delay %d errno %d", delay, errno);
return;
}
pos += ret;
if (pos < dump_len)
goto retry;
goto repeat;
return 0;
log_debug("send_dump_buf delay %d total %d", delay, pos);
}
static int print_structs(const char *prefix, int pos, int len)
@@ -4186,8 +4256,7 @@ static void client_recv_action(struct client *cl)
return;
}
if (op == LD_OP_HELLO || op == LD_OP_QUIT ||
op == LD_OP_DUMP_INFO || op == LD_OP_DUMP_LOG) {
if (op == LD_OP_HELLO || op == LD_OP_QUIT) {
/*
* FIXME: add the client command name to the hello messages
@@ -4208,37 +4277,11 @@ static void client_recv_action(struct client *cl)
buffer_init(&res.buffer);
if (op == LD_OP_DUMP_INFO || op == LD_OP_DUMP_LOG) {
int dump_len = 0;
int fd;
fd = setup_dump_socket();
if (fd < 0)
result = fd;
else if (op == LD_OP_DUMP_INFO)
result = dump_info(&dump_len);
else if (op == LD_OP_DUMP_LOG)
result = dump_log(&dump_len);
else
result = -EINVAL;
res = daemon_reply_simple("OK",
"result = %d", result,
"dump_len = %d", dump_len,
NULL);
if (fd >= 0) {
send_dump_buf(fd, dump_len);
close(fd);
}
} else {
res = daemon_reply_simple("OK",
res = daemon_reply_simple("OK",
"result = %d", result,
"protocol = %s", lvmlockd_protocol,
"version = %d", lvmlockd_protocol_version,
NULL);
}
buffer_write(cl->fd, &res.buffer);
buffer_destroy(&res.buffer);
dm_config_destroy(req.cft);
@@ -4345,6 +4388,9 @@ static void client_recv_action(struct client *cl)
goto out;
}
if (act->op == LD_OP_LOCK && act->mode != LD_LK_UN)
cl->lock_ops = 1;
switch (act->op) {
case LD_OP_START:
rv = add_lockspace(act);
@@ -4352,6 +4398,12 @@ static void client_recv_action(struct client *cl)
case LD_OP_STOP:
rv = rem_lockspace(act);
break;
case LD_OP_DUMP_LOG:
case LD_OP_DUMP_INFO:
/* The client thread reply will copy and send the dump. */
add_client_result(act);
rv = 0;
break;
case LD_OP_INIT:
case LD_OP_START_WAIT:
case LD_OP_STOP_ALL:

View File

@@ -85,6 +85,7 @@ struct client {
unsigned int recv : 1;
unsigned int dead : 1;
unsigned int poll_ignore : 1;
unsigned int lock_ops : 1;
char name[MAX_NAME+1];
};

View File

@@ -585,12 +585,16 @@ static int spawn_detached_thread(struct lvmpolld_lv *pdlv)
int r;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_attr_init(&attr) != 0)
return 0;
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
return 0;
r = pthread_create(&pdlv->tid, &attr, fork_and_poll, (void *)pdlv);
pthread_attr_destroy(&attr);
if (pthread_attr_destroy(&attr) != 0)
return 0;
return !r;
}

View File

@@ -23,7 +23,6 @@
#include "toolcontext.h"
#include "lvm-file.h"
#include "memlock.h"
#include "segtype.h"
#include <sys/stat.h>
#include <sys/mman.h>
@@ -582,8 +581,11 @@ int config_file_read(struct dm_config_tree *cft)
if (!(cf->dev = dev_create_file(filename, NULL, NULL, 1)))
return_0;
if (!dev_open_readonly_buffered(cf->dev))
if (!dev_open_readonly_buffered(cf->dev)) {
dev_destroy_file(cf->dev);
cf->dev = NULL;
return_0;
}
}
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
@@ -1692,6 +1694,11 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
if (cfg_def->comment) {
int pos = 0;
while (_copy_one_line(cfg_def->comment, commentline, &pos, strlen(cfg_def->comment))) {
if ((commentline[0] == '#') && (strlen(commentline) == 1)) {
if (!out->tree_spec->withspaces)
continue;
commentline[0] = '\0';
}
fprintf(out->fp, "%s# %s\n", line, commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
@@ -1714,6 +1721,9 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
if (cfg_def->flags & CFG_DEFAULT_UNDEFINED)
fprintf(out->fp, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
if (cfg_def->flags & CFG_DEFAULT_COMMENTED)
fprintf(out->fp, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
if ((out->tree_spec->type == CFG_DEF_TREE_FULL) &&
(out->tree_spec->check_status[cn->id] & CFG_USED))
fprintf(out->fp, "%s# Value defined in existing configuration has been used for this setting.\n", line);
@@ -2416,27 +2426,3 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
{
return DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
}
const char *get_default_allocation_cache_policy_CFG(struct cmd_context *cmd, struct profile *profile)
{
const struct segment_type *segtype = get_segtype_from_string(cmd, "cache");
unsigned attr = ~0;
if (!segtype ||
!segtype->ops->target_present ||
!segtype->ops->target_present(cmd, NULL, &attr)) {
log_warn("WARNING: Cannot detect default cache policy, using \""
DEFAULT_CACHE_POLICY "\".");
return DEFAULT_CACHE_POLICY;
}
if (attr & CACHE_FEATURE_POLICY_SMQ)
return "smq";
if (attr & CACHE_FEATURE_POLICY_MQ)
return "mq";
log_warn("WARNING: Default cache policy not available.");
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -71,6 +71,16 @@ static void _dev_init(struct device *dev, int max_error_count)
dm_list_init(&dev->open_list);
}
void dev_destroy_file(struct device *dev)
{
if (!(dev->flags & DEV_ALLOCED))
return;
dm_free((void *) dm_list_item(dev->aliases.n, struct dm_str_list)->str);
dm_free(dev->aliases.n);
dm_free(dev);
}
struct device *dev_create_file(const char *filename, struct device *dev,
struct dm_str_list *alias, int use_malloc)
{

View File

@@ -586,12 +586,8 @@ static void _close(struct device *dev)
log_debug_devs("Closed %s", dev_name(dev));
if (dev->flags & DEV_ALLOCED) {
dm_free((void *) dm_list_item(dev->aliases.n, struct dm_str_list)->
str);
dm_free(dev->aliases.n);
dm_free(dev);
}
if (dev->flags & DEV_ALLOCED)
dev_destroy_file(dev);
}
static int _dev_close(struct device *dev, int immediate)

View File

@@ -123,6 +123,7 @@ void dev_flush(struct device *dev);
struct device *dev_create_file(const char *filename, struct device *dev,
struct dm_str_list *alias, int use_malloc);
void dev_destroy_file(struct device *dev);
/* Return a valid device name from the alias list; NULL otherwise */
const char *dev_name_confirmed(struct device *dev, int quiet);

View File

@@ -453,8 +453,9 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
"not match expected name %s.", vgname);
bad:
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)))
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)) &&
!lvmcache_update_vgname_and_id(info, &vgsummary_orphan))
stack;
return NULL;
}

View File

@@ -105,7 +105,8 @@ static void _update_lvmcache_orphan(struct lvmcache_info *info)
memcpy(&vgsummary_orphan.vgid, lvmcache_fmt(info)->orphan_vg_name, strlen(lvmcache_fmt(info)->orphan_vg_name));
lvmcache_update_vgname_and_id(info, &vgsummary_orphan);
if (!lvmcache_update_vgname_and_id(info, &vgsummary_orphan))
stack;
}
static struct labeller *_find_labeller(struct device *dev, char *buf,

View File

@@ -434,6 +434,34 @@ int lv_is_cache_origin(const struct logical_volume *lv)
return seg && lv_is_cache(seg->lv) && !lv_is_pending_delete(seg->lv) && (seg_lv(seg, 0) == lv);
}
static const char *_get_default_cache_policy(struct cmd_context *cmd)
{
const struct segment_type *segtype = get_segtype_from_string(cmd, "cache");
unsigned attr = ~0;
const char *def = NULL;
if (!segtype ||
!segtype->ops->target_present ||
!segtype->ops->target_present(cmd, NULL, &attr)) {
log_warn("WARNING: Cannot detect default cache policy, using \""
DEFAULT_CACHE_POLICY "\".");
return DEFAULT_CACHE_POLICY;
}
if (attr & CACHE_FEATURE_POLICY_SMQ)
def = "smq";
else if (attr & CACHE_FEATURE_POLICY_MQ)
def = "mq";
else {
log_error("Default cache policy is not available.");
return NULL;
}
log_debug_metadata("Detected default cache_policy \"%s\".", def);
return def;
}
int cache_set_policy(struct lv_segment *seg, const char *name,
const struct dm_config_tree *settings)
{
@@ -451,8 +479,11 @@ int cache_set_policy(struct lv_segment *seg, const char *name,
log_error("Failed to duplicate policy name.");
return 0;
}
} else if (!seg->policy_name && passed_seg_is_cache)
seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL);
} else if (!seg->policy_name && passed_seg_is_cache) {
if (!(seg->policy_name = find_config_tree_str(seg->lv->vg->cmd, allocation_cache_policy_CFG, NULL)) &&
!(seg->policy_name = _get_default_cache_policy(seg->lv->vg->cmd)))
return_0;
}
if (settings) {
if (!seg->policy_name) {

View File

@@ -5105,6 +5105,11 @@ static int _lvresize_check_type(struct cmd_context *cmd, const struct logical_vo
}
}
if ((lp->resize == LV_REDUCE) && lv_is_thin_pool_metadata(lv)) {
log_error("Thin pool metadata volumes cannot be reduced.");
return 0;
}
if (lv_is_thin_volume(lv) && first_seg(lv)->external_lv &&
(lp->resize == LV_EXTEND)) {
/* Validate thin target supports bigger size of thin volume then external origin */
@@ -5296,7 +5301,7 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
*/
inactive = 1;
if (!activate_lv_excl(cmd, lock_lv)) {
log_error("Failed to activate %s.", lock_lv->name);
log_error("Failed to activate %s.", display_lvname(lock_lv));
return 0;
}
}
@@ -5317,12 +5322,12 @@ int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
backup(vg);
if (inactive && !deactivate_lv(cmd, lock_lv)) {
log_error("Problem deactivating %s.", lock_lv->name);
log_error("Problem deactivating %s.", display_lvname(lock_lv));
return 0;
}
}
log_print_unless_silent("Logical volume %s successfully resized", lp->lv_name);
log_print_unless_silent("Logical volume %s successfully resized.", lp->lv_name);
if (lp->resizefs && (lp->resize == LV_EXTEND) &&
!_fsadm_cmd(cmd, vg, lp, FSADM_CMD_RESIZE, NULL))

View File

@@ -21,7 +21,6 @@
#include "activate.h"
#include "lv_alloc.h"
#include "lvm-string.h"
#include "lvmlockd.h"
static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
struct logical_volume **tracking)

View File

@@ -63,6 +63,10 @@ int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
tmsg->type = type;
/* If the 1st message is add in non-read-only mode, modify transaction_id */
if (!no_update && dm_list_empty(&pool_seg->thin_messages))
pool_seg->transaction_id++;
dm_list_add(&pool_seg->thin_messages, &tmsg->list);
log_debug_metadata("Added %s message.",
@@ -476,9 +480,6 @@ int update_pool_lv(struct logical_volume *lv, int activate)
dm_list_init(&(first_seg(lv)->thin_messages));
/* thin-pool target transaction is finished, increase lvm2 TID */
first_seg(lv)->transaction_id++;
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
return_0;

View File

@@ -20,7 +20,6 @@
#include "toolcontext.h"
#include "lvmcache.h"
#include "archiver.h"
#include "lvmlockd.h"
struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd,
const char *vg_name)

View File

@@ -25,14 +25,57 @@
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
/*
* Symbol export control macros
*
* DM_EXPORT_SYMBOL(func,ver)
* DM_EXPORT_SYMBOL_BASE(func,ver)
*
* For functions that have multiple implementations these macros control
* symbol export and versioning.
*
* Function definitions that exist in only one version never need to use
* these macros.
*
* Backwards compatible implementations must include a version tag of
* the form "_v1_02_104" as a suffix to the function name and use the
* macro DM_EXPORT_SYMBOL to export the function and bind it to the
* specified version string.
*
* Since versioning is only available when compiling with GCC the entire
* compatibility version should be enclosed in '#if defined(__GNUC__)',
* for example:
*
* int dm_foo(int bar)
* {
* return bar;
* }
*
* #if defined(__GNUC__)
* // Backward compatible dm_foo() version 1.02.104
* int dm_foo_v1_02_104(void);
* int dm_foo_v1_02_104(void)
* {
* return 0;
* }
* DM_EXPORT_SYMBOL(dm_foo,1_02_104)
* #endif
*
* A prototype for the compatibility version is required as these
* functions must not be declared static.
*
* The DM_EXPORT_SYMBOL_BASE macro is only used to export the base
* versions of library symbols prior to the introduction of symbol
* versioning: it must never be used for new symbols.
*/
#if defined(__GNUC__)
#define DM_EXPORTED_SYMBOL(func, ver) \
__asm__(".symver " #func "_v" #ver ", " #func "@@DM_" #ver )
#define DM_EXPORTED_SYMBOL_BASE(func) \
#define DM_EXPORT_SYMBOL(func, ver) \
__asm__(".symver " #func "_v" #ver ", " #func "@DM_" #ver )
#define DM_EXPORT_SYMBOL_BASE(func) \
__asm__(".symver " #func "_base, " #func "@Base" )
#else
#define DM_EXPORTED_SYMBOL(func, ver)
#define DM_EXPORTED_SYMBOL_BASE(func)
#define DM_EXPORT_SYMBOL(func, ver)
#define DM_EXPORT_SYMBOL_BASE(func)
#endif

View File

@@ -37,11 +37,13 @@
/* Define some portable printing types */
#define PRIsize_t "zu"
#define PRIssize_t "zd"
#define PRIptrdiff_t "td"
#define PRIpid_t PRId32
/* For convenience */
#define FMTsize_t "%" PRIsize_t
#define FMTssize_t "%" PRIssize_t
#define FMTptrdiff_t "%" PRIptrdiff_t
#define FMTpid_t "%" PRIpid_t

View File

@@ -1344,7 +1344,7 @@ static int _cache_settings_disp(struct dm_report *rh, struct dm_pool *mem,
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
else {
else if (!seg_is_cache_pool(seg)) {
dm_list_init(&dummy_list);
return _field_set_string_list(rh, field, &dummy_list, private, 0);
/* TODO: once we have support for STR_LIST reserved values, replace with:
@@ -1384,7 +1384,7 @@ static int _cache_policy_disp(struct dm_report *rh, struct dm_pool *mem,
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
else
else if (!seg_is_cache_pool(seg) || !seg->policy_name)
return _field_set_value(field, GET_FIRST_RESERVED_NAME(cache_policy_undef),
GET_FIELD_RESERVED_VALUE(cache_policy_undef));
@@ -2078,7 +2078,7 @@ static int _cachemode_disp(struct dm_report *rh, struct dm_pool *mem,
if (seg_is_cache(seg))
seg = first_seg(seg->pool_lv);
if (seg_is_cache_pool(seg)) {
if (seg_is_cache_pool(seg) && cache_mode_is_set(seg)) {
if (!(cachemode_str = get_cache_mode_name(seg)))
return_0;

View File

@@ -295,7 +295,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
}
if (!dm_tree_node_add_thin_pool_target(node, len,
seg->transaction_id + (laopts->send_messages ? 1 : 0),
seg->transaction_id,
metadata_dlid, pool_dlid,
seg->chunk_size, seg->low_water_mark,
seg->zero_new_blocks ? 0 : 1))
@@ -345,7 +345,7 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
*/
if (!lv_thin_pool_transaction_id(seg->lv, &transaction_id))
return_0; /* Thin pool should exist and work */
if (transaction_id != seg->transaction_id) {
if ((transaction_id + 1) != seg->transaction_id) {
log_error("Can't create snapshot %s as origin %s is not suspended.",
lmsg->u.lv->name, origin->name);
return 0;
@@ -373,11 +373,11 @@ static int _thin_pool_add_target_line(struct dev_manager *dm,
if (!dm_list_empty(&seg->thin_messages)) {
/* Messages were passed, modify transaction_id as the last one */
log_debug_activation("Thin pool set transaction id %" PRIu64 ".", seg->transaction_id + 1);
log_debug_activation("Thin pool set transaction id %" PRIu64 ".", seg->transaction_id);
if (!dm_tree_node_add_thin_pool_message(node,
DM_THIN_MESSAGE_SET_TRANSACTION_ID,
seg->transaction_id,
seg->transaction_id + 1))
seg->transaction_id - 1,
seg->transaction_id))
return_0;
}

View File

@@ -539,6 +539,7 @@ void daemon_start(daemon_state s)
log_state _log = { { 0 } };
thread_state _threads = { .next = NULL };
unsigned timeout_count = 0;
fd_set in;
/*
* Switch to C locale to avoid reading large locale-archive file used by
@@ -623,7 +624,6 @@ void daemon_start(daemon_state s)
while (!_shutdown_requested && !failed) {
_reset_timeout(s);
fd_set in;
FD_ZERO(&in);
FD_SET(s.socket_fd, &in);
if (select(FD_SETSIZE, &in, NULL, NULL, _get_timeout(s)) < 0 && errno != EINTR)

View File

@@ -179,7 +179,6 @@ dm_task_destroy
dm_task_enable_checks
dm_task_get_deps
dm_task_get_driver_version
dm_task_get_info
dm_task_get_info_with_deferred_remove
dm_task_get_message_response
dm_task_get_name

View File

@@ -6,7 +6,6 @@ dm_stats_bind_uuid
dm_stats_buffer_destroy
dm_stats_clear_region
dm_stats_create
dm_stats_create_region
dm_stats_delete_region
dm_stats_destroy
dm_stats_get_area_start
@@ -72,7 +71,6 @@ dm_task_get_ioctl_timestamp
dm_task_set_record_timestamp
dm_timestamp_alloc
dm_timestamp_compare
dm_timestamp_copy
dm_timestamp_delta
dm_timestamp_destroy
dm_timestamp_get

View File

@@ -0,0 +1,4 @@
dm_report_is_empty
dm_stats_get_area_offset
dm_stats_get_current_area_offset
dm_timestamp_copy

View File

@@ -0,0 +1,5 @@
dm_message_supports_precise_timestamps
dm_stats_create_region
dm_stats_driver_supports_precise
dm_stats_get_current_region_precise_timestamps
dm_stats_get_region_precise_timestamps

View File

@@ -55,7 +55,7 @@ include $(top_builddir)/make.tmpl
CFLAGS += $(UDEV_CFLAGS) $(VALGRIND_CFLAGS)
LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS)
LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS)
device-mapper: all

View File

@@ -604,6 +604,20 @@ static int dm_inactive_supported(void)
return inactive_supported;
}
int dm_message_supports_precise_timestamps(void)
{
/*
* 4.32.0 supports "precise_timestamps" and "histogram:" options
* to @stats_create messages but lacks the ability to report
* these properties via a subsequent @stats_list: require at
* least 4.33.0 in order to use these features.
*/
if (dm_check_version() && _dm_version >= 4)
if (_dm_version_minor >= 33)
return 1;
return 0;
}
void *dm_get_next_target(struct dm_task *dmt, void *next,
uint64_t *start, uint64_t *length,
char **target_type, char **params)
@@ -667,13 +681,7 @@ int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
return 1;
}
#if defined(__GNUC__)
int dm_task_get_info_v1_02_97(struct dm_task *dmt, struct dm_info *info);
DM_EXPORTED_SYMBOL(dm_task_get_info, 1_02_97);
int dm_task_get_info_v1_02_97(struct dm_task *dmt, struct dm_info *info)
#else
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
#endif
{
if (!dmt->dmi.v4)
return 0;
@@ -2126,12 +2134,12 @@ void dm_lib_exit(void)
*/
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info);
DM_EXPORTED_SYMBOL_BASE(dm_task_get_info);
DM_EXPORT_SYMBOL_BASE(dm_task_get_info);
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info)
{
struct dm_info new_info;
if (!dm_task_get_info_v1_02_97(dmt, &new_info))
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove));
@@ -2144,7 +2152,7 @@ int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *i
{
struct dm_info new_info;
if (!dm_task_get_info_v1_02_97(dmt, &new_info))
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend));

View File

@@ -464,6 +464,38 @@ int dm_stats_bind_name(struct dm_stats *dms, const char *name);
*/
int dm_stats_bind_uuid(struct dm_stats *dms, const char *uuid);
/*
* Test whether the running kernel supports the precise_timestamps
* feature. Presence of this feature also implies histogram support.
* The library will check this call internally and fails any attempt
* to use nanosecond counters or histograms on kernels that fail to
* meet this check.
*/
int dm_message_supports_precise_timestamps(void);
/*
* Precise timetamps support.
*
* Test for the presence of precise_timestamps support.
*/
int dm_stats_driver_supports_precise(void);
/*
* Returns 1 if the specified region has the precise_timestamps feature
* enabled (i.e. produces nanosecond-precision counter values) or 0 for
* a region using the default milisecond precision.
*/
int dm_stats_get_region_precise_timestamps(const struct dm_stats *dms,
uint64_t region_id);
/*
* Returns 1 if the region at the current cursor location has the
* precise_timestamps feature enabled (i.e. produces
* nanosecond-precision counter values) or 0 for a region using the
* default milisecond precision.
*/
int dm_stats_get_current_region_precise_timestamps(const struct dm_stats *dms);
#define DM_STATS_ALL_PROGRAMS ""
/*
* Parse the response from a @stats_list message. dm_stats_list will
@@ -526,6 +558,9 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
*
* dm_stats_create_region(dms, 1024, 1 << 11, -2, p, a);
*
* If precise is non-zero attempt to create a region with nanosecond
* precision counters using the kernel precise_timestamps feature.
*
* program_id is an optional string argument that identifies the
* program creating the region. If program_id is NULL or the empty
* string the default program_id stored in the handle will be used.
@@ -539,6 +574,7 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id,
*/
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
int precise,
const char *program_id, const char *aux_data);
/*
@@ -697,26 +733,36 @@ int dm_stats_set_program_id(struct dm_stats *dms, int allow_empty,
*
* All values are returned in units of 512b sectors.
*/
uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id);
uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
uint64_t region_id);
uint64_t dm_stats_get_region_area_len(const struct dm_stats *dms,
uint64_t *area_len, uint64_t region_id);
int dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id);
int dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
uint64_t region_id);
int dm_stats_get_region_area_len(const struct dm_stats *dms,
uint64_t *len, uint64_t region_id);
/*
* Area properties: start and length.
* Area properties: start, offset and length.
*
* The area length is always equal to the area length of the region
* that contains it and is obtained from dm_stats_get_region_area_len().
*
* The start offset of an area is a function of the area_id and the
* containing region's start and area length.
* The start of an area is a function of the area_id and the containing
* region's start and area length: it gives the absolute offset into the
* containing device of the beginning of the area.
*
* The offset expresses the area's relative offset into the current
* region. I.e. the area start minus the start offset of the containing
* region.
*
* All values are returned in units of 512b sectors.
*/
uint64_t dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id, uint64_t area_id);
int dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id, uint64_t area_id);
int dm_stats_get_area_offset(const struct dm_stats *dms, uint64_t *offset,
uint64_t region_id, uint64_t area_id);
/*
* Retrieve program_id and aux_data for a specific region. Only valid
@@ -856,14 +902,14 @@ uint64_t dm_stats_get_current_area(const struct dm_stats *dms);
*
* All values are returned in units of 512b sectors.
*/
uint64_t dm_stats_get_current_region_start(const struct dm_stats *dms,
uint64_t *start);
int dm_stats_get_current_region_start(const struct dm_stats *dms,
uint64_t *start);
uint64_t dm_stats_get_current_region_len(const struct dm_stats *dms,
uint64_t *len);
int dm_stats_get_current_region_len(const struct dm_stats *dms,
uint64_t *len);
uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
uint64_t *area_len);
int dm_stats_get_current_region_area_len(const struct dm_stats *dms,
uint64_t *area_len);
/*
* Current area properties: start and length.
@@ -873,10 +919,13 @@ uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
*
* All values are returned in units of 512b sectors.
*/
uint64_t dm_stats_get_current_area_start(const struct dm_stats *dms,
uint64_t *start);
int dm_stats_get_current_area_start(const struct dm_stats *dms,
uint64_t *start);
uint64_t dm_stats_get_current_area_len(const struct dm_stats *dms,
int dm_stats_get_current_area_offset(const struct dm_stats *dms,
uint64_t *offset);
int dm_stats_get_current_area_len(const struct dm_stats *dms,
uint64_t *start);
/*
@@ -2396,6 +2445,11 @@ int dm_report_object_is_selected(struct dm_report *rh, void *object, int do_outp
*/
int dm_report_compact_fields(struct dm_report *rh);
/*
* Returns 1 if there is no data waiting to be output.
*/
int dm_report_is_empty(struct dm_report *rh);
int dm_report_output(struct dm_report *rh);
/*

View File

@@ -1586,7 +1586,7 @@ static int _node_send_messages(struct dm_tree_node *dnode,
}
/* Error if there are no stacked messages or id mismatches */
if (trans_id != (seg->transaction_id - have_messages)) {
if ((trans_id + 1) != seg->transaction_id) {
log_error("Thin pool %s transaction_id is %" PRIu64 ", while expected %" PRIu64 ".",
_node_name(dnode), trans_id, seg->transaction_id - have_messages);
return 0;

View File

@@ -257,7 +257,7 @@ static int _selected_disp(struct dm_report *rh,
const void *data,
void *private __attribute__((unused)))
{
struct row *row = (struct row *)data;
const struct row *row = (const struct row *)data;
return dm_report_field_int(rh, field, &row->selected);
}
@@ -1387,11 +1387,11 @@ static int _dbl_less_or_equal(double d1, double d2)
return _dbl_less(d1, d2) || _dbl_equal(d1, d2);
}
#define _uint64 *(uint64_t *)
#define _uint64arr(var,index) ((uint64_t *)var)[index]
#define _uint64 *(const uint64_t *)
#define _uint64arr(var,index) ((const uint64_t *)var)[index]
#define _str (const char *)
#define _dbl *(double *)
#define _dblarr(var,index) ((double *)var)[index]
#define _dbl *(const double *)
#define _dblarr(var,index) ((const double *)var)[index]
static int _do_check_value_is_strictly_reserved(unsigned type, const void *res_val, int res_range,
const void *val, struct field_selection *fs)
@@ -1790,7 +1790,7 @@ static int _compare_selection_field(struct dm_report *rh,
r = _cmp_field_int(rh, f->props->field_num, field_id, *(const uint64_t *) f->sort_value, fs);
break;
case DM_REPORT_FIELD_TYPE_SIZE:
r = _cmp_field_double(rh, f->props->field_num, field_id, *(double *) f->sort_value, fs);
r = _cmp_field_double(rh, f->props->field_num, field_id, *(const double *) f->sort_value, fs);
break;
case DM_REPORT_FIELD_TYPE_STRING:
r = _cmp_field_string(rh, f->props->field_num, field_id, (const char *) f->sort_value, fs);
@@ -2446,8 +2446,8 @@ static const char *_tok_value_regex(struct dm_report *rh,
static int _str_list_item_cmp(const void *a, const void *b)
{
const struct dm_str_list **item_a = (const struct dm_str_list **) a;
const struct dm_str_list **item_b = (const struct dm_str_list **) b;
const struct dm_str_list * const *item_a = (const struct dm_str_list * const *) a;
const struct dm_str_list * const *item_b = (const struct dm_str_list * const *) b;
return strcmp((*item_a)->str, (*item_b)->str);
}
@@ -3357,7 +3357,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
memcpy(s, v, len);
s[len] = '\0';
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char **) &s, 1);
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char * const *) &s, 1);
dm_free(s);
if (!fs->value->v.r) {
log_error("dm_report: failed to create regex "
@@ -3377,7 +3377,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
if (rvw->value) {
fs->value->v.s = (const char *) rvw->value;
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
fs->value->next->v.s = (((const char **) rvw->value)[1]);
fs->value->next->v.s = (((const char * const *) rvw->value)[1]);
dm_pool_free(rh->selection->mem, s);
} else {
fs->value->v.s = s;
@@ -3389,9 +3389,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
break;
case DM_REPORT_FIELD_TYPE_NUMBER:
if (rvw->value) {
fs->value->v.i = *(uint64_t *) rvw->value;
fs->value->v.i = *(const uint64_t *) rvw->value;
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
fs->value->next->v.i = (((uint64_t *) rvw->value)[1]);
fs->value->next->v.i = (((const uint64_t *) rvw->value)[1]);
} else {
if (((fs->value->v.i = strtoull(s, NULL, 10)) == ULLONG_MAX) &&
(errno == ERANGE)) {
@@ -3407,16 +3407,16 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
break;
case DM_REPORT_FIELD_TYPE_SIZE:
if (rvw->value) {
fs->value->v.d = *(double *) rvw->value;
fs->value->v.d = *(const double *) rvw->value;
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
fs->value->next->v.d = (((double *) rvw->value)[1]);
fs->value->next->v.d = (((const double *) rvw->value)[1]);
} else {
fs->value->v.d = strtod(s, NULL);
if (errno == ERANGE) {
log_error(_out_of_range_msg, s, field_id);
goto error;
}
if (custom && (factor = *((uint64_t *)custom)))
if (custom && (factor = *((const uint64_t *)custom)))
fs->value->v.d *= factor;
fs->value->v.d /= 512; /* store size in sectors! */
if (_check_value_is_strictly_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_SIZE, &fs->value->v.d, NULL)) {
@@ -3428,9 +3428,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
break;
case DM_REPORT_FIELD_TYPE_PERCENT:
if (rvw->value) {
fs->value->v.i = *(uint64_t *) rvw->value;
fs->value->v.i = *(const uint64_t *) rvw->value;
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
fs->value->next->v.i = (((uint64_t *) rvw->value)[1]);
fs->value->next->v.i = (((const uint64_t *) rvw->value)[1]);
} else {
fs->value->v.d = strtod(s, NULL);
if ((errno == ERANGE) || (fs->value->v.d < 0) || (fs->value->v.d > 100)) {
@@ -3455,9 +3455,9 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
break;
case DM_REPORT_FIELD_TYPE_TIME:
if (rvw->value) {
fs->value->v.t = *(time_t *) rvw->value;
fs->value->v.t = *(const time_t *) rvw->value;
if (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)
fs->value->next->v.t = (((time_t *) rvw->value)[1]);
fs->value->next->v.t = (((const time_t *) rvw->value)[1]);
} else {
tval = (struct time_value *) custom;
fs->value->v.t = tval->t1;
@@ -4305,6 +4305,11 @@ static int _output_as_columns(struct dm_report *rh)
return 0;
}
int dm_report_is_empty(struct dm_report *rh)
{
return dm_list_empty(&rh->rows) ? 1 : 0;
}
int dm_report_output(struct dm_report *rh)
{
if (dm_list_empty(&rh->rows))

View File

@@ -13,14 +13,14 @@
*/
#include "dmlib.h"
#include "libdm-targets.h"
#include "libdm-common.h"
#define DM_STATS_REGION_NOT_PRESENT UINT64_MAX
#define NSEC_PER_MSEC 1000000L
#define NSEC_PER_SEC 1000000000L
#define PRECISE_ARG "precise_timestamps"
/*
* See Documentation/device-mapper/statistics.txt for full descriptions
* of the device-mapper statistics counter fields.
@@ -63,7 +63,8 @@ struct dm_stats {
uint64_t nr_regions; /* total number of present regions */
uint64_t max_region; /* size of the regions table */
uint64_t interval_ns; /* sampling interval in nanoseconds */
uint64_t timescale; /* sample value multiplier */
uint64_t timescale; /* default sample value multiplier */
int precise; /* use precise_timestamps when creating regions */
struct dm_stats_region *regions;
/* statistics cursor */
uint64_t cur_region;
@@ -111,8 +112,9 @@ struct dm_stats *dm_stats_create(const char *program_id)
dms->name = NULL;
dms->uuid = NULL;
/* all regions currently use msec precision */
/* by default all regions use msec precision */
dms->timescale = NSEC_PER_MSEC;
dms->precise = 0;
dms->nr_regions = DM_STATS_REGION_NOT_PRESENT;
dms->max_region = DM_STATS_REGION_NOT_PRESENT;
@@ -227,6 +229,19 @@ int dm_stats_bind_uuid(struct dm_stats *dms, const char *uuid)
return 1;
}
static int _stats_check_precise_timestamps(const struct dm_stats *dms)
{
/* Already checked? */
if (dms && dms->precise)
return 1;
return dm_message_supports_precise_timestamps();
}
int dm_stats_driver_supports_precise(void)
{
return _stats_check_precise_timestamps(NULL);
}
static struct dm_task *_stats_send_message(struct dm_stats *dms, char *msg)
{
struct dm_task *dmt;
@@ -251,24 +266,55 @@ out:
static int _stats_parse_list_region(struct dm_stats_region *region, char *line)
{
/* FIXME: the kernel imposes no length limit here */
char program_id[256], aux_data[256];
char *p = NULL, string_data[4096]; /* FIXME: add dm_sscanf with %ms? */
const char *program_id, *aux_data, *stats_args;
const char *empty_string = "";
int r;
/* line format:
* <region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
*/
r = sscanf(line, FMTu64 ": " FMTu64 "+" FMTu64 " " FMTu64 "%255s %255s",
&region->region_id, &region->start, &region->len, &region->step,
program_id, aux_data);
memset(string_data, 0, sizeof(string_data));
if (r != 6)
/*
* Parse fixed fields, line format:
*
* <region_id>: <start_sector>+<length> <step> <string data>
*
* Maximum string data size is 4096 - 1 bytes.
*/
r = sscanf(line, FMTu64 ": " FMTu64 "+" FMTu64 " " FMTu64 " %4095c",
&region->region_id, &region->start, &region->len,
&region->step, string_data);
if (r != 5)
return_0;
if (!strcmp(program_id, "-"))
program_id[0] = '\0';
if (!strcmp(aux_data, "-"))
aux_data[0] = '\0';
/* program_id is guaranteed to be first. */
program_id = string_data;
/*
* FIXME: support embedded '\ ' in string data:
* s/strchr/_find_unescaped_space()/
*/
if ((p = strchr(string_data, ' '))) {
/* terminate program_id string. */
*p = '\0';
if (!strcmp(program_id, "-"))
program_id = empty_string;
aux_data = p + 1;
if ((p = strchr(aux_data, ' '))) {
/* terminate aux_data string. */
*p = '\0';
if (!strcmp(aux_data, "-"))
aux_data = empty_string;
stats_args = p + 1;
} else
stats_args = empty_string;
} else
aux_data = stats_args = empty_string;
if (strstr(stats_args, PRECISE_ARG))
region->timescale = 1;
else
region->timescale = NSEC_PER_MSEC;
if (!(region->program_id = dm_strdup(program_id)))
return_0;
@@ -504,14 +550,16 @@ out:
static uint64_t _nr_areas(uint64_t len, uint64_t step)
{
/* Default is one area. */
if (!len || !step)
return 1;
/*
* drivers/md/dm-stats.c::message_stats_create()
* A region may be sub-divided into areas with their own counters.
* If step is non-zero, divide len into that many areas, otherwise
* treat the entire region as a single area. Any partial area at the
* end of the region is treated as an additional complete area.
* Any partial area at the end of the region is treated as an
* additional complete area.
*/
return (len / (step ? : len)) + !!(len % step);
return (len + step - 1) / step;
}
static uint64_t _nr_areas_region(struct dm_stats_region *region)
@@ -621,14 +669,17 @@ uint64_t dm_stats_get_nr_areas(const struct dm_stats *dms)
return nr_areas;
}
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
const char *program_id, const char *aux_data)
static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
int precise,
const char *program_id, const char *aux_data)
{
struct dm_task *dmt = NULL;
char msg[1024], range[64];
const char *err_fmt = "Could not prepare @stats_create %s.";
const char *resp;
const char *precise_str = PRECISE_ARG;
const char *resp, *opt_args = NULL;
int nr_opt = 0, r = 0; /* number of optional args. */
if (!_stats_bound(dms))
return_0;
@@ -640,16 +691,35 @@ int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
if (!dm_snprintf(range, sizeof(range), FMTu64 "+" FMTu64,
start, len)) {
log_error(err_fmt, "range");
goto out;
return 0;
}
}
if (!dm_snprintf(msg, sizeof(msg), "@stats_create %s %s" FMTu64 " %s %s",
(start || len) ? range : "-",
if (precise < 0)
precise = dms->precise;
if (precise)
nr_opt++;
else
precise_str = "";
if (nr_opt) {
if ((dm_asprintf((char **)&opt_args, "%d %s", nr_opt,
precise_str)) < 0) {
log_error(err_fmt, PRECISE_ARG " option.");
return 0;
}
} else
opt_args = dm_strdup("");
if (!dm_snprintf(msg, sizeof(msg), "@stats_create %s %s" FMTu64
" %s %s %s", (start || len) ? range : "-",
(step < 0) ? "/" : "",
(uint64_t)llabs(step), program_id, aux_data)) {
(uint64_t)llabs(step),
opt_args, program_id, aux_data)) {
log_error(err_fmt, "message");
goto out;
dm_free((void *) opt_args);
return 0;
}
if (!(dmt = _stats_send_message(dms, msg)))
@@ -668,15 +738,46 @@ int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
goto_out;
}
dm_task_destroy(dmt);
r = 1;
return 1;
out:
if(dmt)
dm_task_destroy(dmt);
return 0;
dm_free((void *) opt_args);
return r;
}
int dm_stats_create_region(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
int precise,
const char *program_id,
const char *aux_data)
{
/* Nanosecond counters need precise_timestamps. */
if (precise && !_stats_check_precise_timestamps(dms))
return 0;
return _stats_create_region(dms, region_id, start, len, step,
precise,
program_id, aux_data);
}
/* Backward compatible dm_stats_create_region() */
#if defined(__GNUC__)
int dm_stats_create_region_v1_02_104(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
const char *program_id, const char *aux_data);
int dm_stats_create_region_v1_02_104(struct dm_stats *dms, uint64_t *region_id,
uint64_t start, uint64_t len, int64_t step,
const char *program_id, const char *aux_data)
{
return _stats_create_region(dms, region_id, start, len, step,
dms->precise,
program_id, aux_data);
}
DM_EXPORT_SYMBOL(dm_stats_create_region, 1_02_104);
#endif
int dm_stats_delete_region(struct dm_stats *dms, uint64_t region_id)
{
struct dm_task *dmt;
@@ -815,7 +916,7 @@ static int _dm_stats_populate_region(struct dm_stats *dms, uint64_t region_id,
if (!_stats_bound(dms))
return_0;
if (!_stats_parse_region(dms->mem, resp, region, dms->timescale)) {
if (!_stats_parse_region(dms->mem, resp, region, region->timescale)) {
log_error("Could not parse @stats_print message response.");
return 0;
}
@@ -1280,7 +1381,7 @@ uint64_t dm_stats_get_current_area(const struct dm_stats *dms)
return dms->cur_area;
}
uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
int dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id)
{
if (!dms || !dms->regions)
@@ -1289,7 +1390,7 @@ uint64_t dm_stats_get_region_start(const struct dm_stats *dms, uint64_t *start,
return 1;
}
uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
int dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
uint64_t region_id)
{
if (!dms || !dms->regions)
@@ -1298,51 +1399,69 @@ uint64_t dm_stats_get_region_len(const struct dm_stats *dms, uint64_t *len,
return 1;
}
uint64_t dm_stats_get_region_area_len(const struct dm_stats *dms, uint64_t *step,
uint64_t region_id)
int dm_stats_get_region_area_len(const struct dm_stats *dms, uint64_t *len,
uint64_t region_id)
{
if (!dms || !dms->regions)
return_0;
*step = dms->regions[region_id].step;
*len = dms->regions[region_id].step;
return 1;
}
uint64_t dm_stats_get_current_region_start(const struct dm_stats *dms,
uint64_t *start)
int dm_stats_get_current_region_start(const struct dm_stats *dms,
uint64_t *start)
{
return dm_stats_get_region_start(dms, start, dms->cur_region);
}
uint64_t dm_stats_get_current_region_len(const struct dm_stats *dms,
uint64_t *len)
int dm_stats_get_current_region_len(const struct dm_stats *dms,
uint64_t *len)
{
return dm_stats_get_region_len(dms, len, dms->cur_region);
}
uint64_t dm_stats_get_current_region_area_len(const struct dm_stats *dms,
uint64_t *step)
int dm_stats_get_current_region_area_len(const struct dm_stats *dms,
uint64_t *step)
{
return dm_stats_get_region_area_len(dms, step, dms->cur_region);
}
uint64_t dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id, uint64_t area_id)
int dm_stats_get_area_start(const struct dm_stats *dms, uint64_t *start,
uint64_t region_id, uint64_t area_id)
{
struct dm_stats_region *region;
if (!dms || !dms->regions)
return_0;
*start = dms->regions[region_id].step * area_id;
region = &dms->regions[region_id];
*start = region->start + region->step * area_id;
return 1;
}
uint64_t dm_stats_get_current_area_start(const struct dm_stats *dms,
uint64_t *start)
int dm_stats_get_area_offset(const struct dm_stats *dms, uint64_t *offset,
uint64_t region_id, uint64_t area_id)
{
if (!dms || !dms->regions)
return_0;
*offset = dms->regions[region_id].step * area_id;
return 1;
}
int dm_stats_get_current_area_start(const struct dm_stats *dms,
uint64_t *start)
{
return dm_stats_get_area_start(dms, start,
dms->cur_region, dms->cur_area);
}
uint64_t dm_stats_get_current_area_len(const struct dm_stats *dms,
uint64_t *len)
int dm_stats_get_current_area_offset(const struct dm_stats *dms,
uint64_t *offset)
{
return dm_stats_get_area_offset(dms, offset,
dms->cur_region, dms->cur_area);
}
int dm_stats_get_current_area_len(const struct dm_stats *dms,
uint64_t *len)
{
return dm_stats_get_region_area_len(dms, len, dms->cur_region);
}
@@ -1370,3 +1489,15 @@ const char *dm_stats_get_current_region_aux_data(const struct dm_stats *dms)
{
return dm_stats_get_region_aux_data(dms, dms->cur_region);
}
int dm_stats_get_region_precise_timestamps(const struct dm_stats *dms,
uint64_t region_id)
{
struct dm_stats_region *region = &dms->regions[region_id];
return region->timescale == 1;
}
int dm_stats_get_current_region_precise_timestamps(const struct dm_stats *dms)
{
return dm_stats_get_region_precise_timestamps(dms, dms->cur_region);
}

View File

@@ -34,7 +34,6 @@
#ifdef HAVE_REALTIME
#include <time.h>
#include <bits/time.h>
struct dm_timestamp {
struct timespec t;

View File

@@ -54,6 +54,7 @@ LDDEPS += @LDDEPS@
LIB_SUFFIX = @LIB_SUFFIX@
LVMINTERNAL_LIBS = -llvm-internal $(DAEMON_LIBS) $(UDEV_LIBS) $(DL_LIBS) $(BLKID_LIBS)
DL_LIBS = @DL_LIBS@
M_LIBS = @M_LIBS@
PTHREAD_LIBS = @PTHREAD_LIBS@
READLINE_LIBS = @READLINE_LIBS@
SELINUX_LIBS = @SELINUX_LIBS@
@@ -501,10 +502,10 @@ else
set -e;\
R=$$(sort $^ | uniq -u);\
test -z "$$R" || { echo "Mismatch between symbols in shared library and lists in .exported_symbols.* files: $$R"; false; } ;\
for i in $(EXPORTED_SYMBOLS); do\
for i in $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | sort -rnt_ -k5 ); do\
echo "$${i##*.} {"; echo " global:";\
$(SED) "s/^/ /;s/$$/;/" $$i;\
test "$$i" = Base && { echo " local:"; echo " *;"; };\
test "$${i##*.}" = Base && { echo " local:"; echo " *;"; };\
echo "};";\
done > $@
endif

View File

@@ -3,7 +3,7 @@
cmirrord \(em cluster mirror log daemon
.SH SYNOPSIS
.B cmirrord
\fBcmirrord\fR [\fB\-f\fR] [\fB\-h\fR]
.SH DESCRIPTION
cmirrord is the daemon that tracks mirror log information in a cluster.
@@ -24,6 +24,12 @@ there are still active cluster mirrors, however, the signal will be
ignored. Active cluster mirrors should be shutdown before stopping the
cluster mirror log daemon.
.SH OPTIONS
.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4
Do not fork and log to the terminal.
.IP "\fB\-h\fR, \fB\-\-help\fR" 4
Print usage.
.SH SEE ALSO
.BR lvm (8)
.BR clvmd (8)

View File

@@ -27,10 +27,12 @@ dmstats \(em device-mapper statistics management
.br
.B dmstats create
.I device_name
.RB [ \-\-alldevices ]
.RB [[ \-\-areas
.IR nr_areas ]
.RB |[ \-\-areasize
.IR area_size ]]
.RB [ \-\-precise ]
.RB [[ \-\-start
.IR start_sector ]
.RB [ \-\-length
@@ -43,7 +45,7 @@ dmstats \(em device-mapper statistics management
.br
.B dmstats delete
.I device_name
.RB [ \-\-force ]
.RB [ \-\-alldevices ]
.RB [ \-\-allregions
.RB | \-\-regionid
.IR id ]
@@ -62,6 +64,8 @@ dmstats \(em device-mapper statistics management
.RB [ \-\-units
.IR units ]
.RB [ \-\-nosuffix ]
.RB [ \-\-nosuffix ]
.RB [ \-v | \-\-verbose \ [ \-v | \-\-verbose ]
.br
.B dmstats print
.RI [ device_name ]
@@ -115,10 +119,14 @@ when run as 'dmsetup stats'.
When no device argument is given dmstats will by default operate on all
device-mapper devices present. The \fBcreate\fP and \fBdelete\fP
commands require the use of \fB--force\fP when used in this way.
commands require the use of \fB--alldevices\fP when used in this way.
.SH OPTIONS
.TP
.B \-\-alldevices
If no device arguments are given allow operation on all devices when
creating or deleting regions.
.TP
.B \-\-allprograms
Include regions from all program IDs for list and report operations.
.TP
@@ -174,6 +182,10 @@ Specify which report fields to display.
Sort output according to the list of fields given. Precede any
sort_field with - for a reverse sort on that column.
.TP
.BR \-\-precise
Attempt to use nanosecond precision counters when creating new
statistics regions.
.TP
.B \-\-programid \fIid
Specify a program ID string. When creating new statistics regions this
string is stored with the region. Subsequent operations may supply a
@@ -233,6 +245,7 @@ regions (with the exception of in-flight IO counters).
.IR nr_areas ]
.RB [ \-\-areasize
.IR area_size ]
.RB [ \-\-precise ]
.RB [[ \-\-start
.IR start_sector ]
.RB [ \-\-length
@@ -252,6 +265,9 @@ at an arbitrary offset into the device. The \fB\-\-segments\fP option
causes a new region to be created for each target in the corresponding
device-mapper device's table.
If the \fB\-\-precise\fP option is used the command will attempt to
create a region using nanosecond precision counters.
An optional \fBprogram_id\fP or \fBaux_data\fP string may be associated
with the region. A \fBprogram_id\fP may then be used to select regions
for subsequent list, print, and report operations. The \fBaux_data\fP
@@ -259,7 +275,7 @@ stores an arbitrary string and is not used by dmstats or the
device-mapper kernel statistics subsystem.
By default dmstats creates regions with a \fBprogram_id\fP of
"DMSTATS1".
"dmstats".
On success the \fBregion_id\fP of the newly created region is printed to
stdout.
@@ -267,7 +283,7 @@ stdout.
.TP
.B delete
.I [ device_name ]
.RB [ \-\-force ]
.RB [ \-\-alldevices ]
.RB [ \-\-allregions
.RB | \-\-regionid
.IR id ]
@@ -282,7 +298,8 @@ of subsequent list, print, or report operations.
All regions registered on a device may be removed using
\fB\-\-allregions\fP.
To remove all regions on all devices \fB\-\-force\fP must be used.
To remove all regions on all devices both \fB--allregions\fP and
\fB\-\-alldevices\fP must be used.
.br
.TP
.B help
@@ -296,11 +313,15 @@ the list of report fields.
.RI [ device_name ]
.RB [ \-\-allprograms ]
.RB [ \-\-programid
.RB [ \-v | \-\-verbose \ [ \-v | \-\-verbose ]]
.IR id ]
.br
List the statistics regions registered on the device. If the
\fB\-\-allprograms\fP switch is given all regions will be listed
regardless of region program ID values.
If \fB\-v\fP or \fB\-\-verbose\fP is given the report will include
a row of information for each area contained in each region displayed.
.br
.TP
.B print
@@ -495,6 +516,20 @@ The program ID value associated with this region.
.br
The auxiliary data value associated with this region.
.br
.HP
.B interval_ns
.br
The estimated interval over which the current counter values have
accumulated. The vaulue is reported as an interger expressed in units
of nanoseconds.
.br
.HP
.B interval
.br
The estimated interval over which the current counter values have
accumulated. The value is reported as a real number in units of
seconds.
.br
.SS Basic counters
Basic counters provide access to the raw counter data from the kernel,
allowing further processing to be carried out by another program.
@@ -565,7 +600,7 @@ Create a whole-device region with one area on vg00/lvol1
.br
# dmstats create vg00/lvol1
.br
Created region: 0
vg00/lvol1: Created new region with 1 area(s) as region ID 0
.br
.br
@@ -575,7 +610,7 @@ Create a 32M region 1G into device d0
.br
# dmstats create --start 1G --length 32M d0
.br
Created region: 2
d0: Created new region with 1 area(s) as region ID 0
.br
@@ -584,24 +619,24 @@ Create a whole-device region with 8 areas on every device
.br
# dmstats create --areas 8
.br
Created region: 0
vg00/lvol1: Created new region with 8 area(s) as region ID 0
.br
Created region: 0
vg00/lvol2: Created new region with 8 area(s) as region ID 0
.br
Created region: 0
vg00/lvol3: Created new region with 8 area(s) as region ID 0
.br
Created region: 2
vg01/lvol0: Created new region with 8 area(s) as region ID 2
.br
Created region: 0
vg01/lvol1: Created new region with 8 area(s) as region ID 0
.br
Created region: 0
vg00/lvol2: Created new region with 8 area(s) as region ID 1
.br
.br
Delete all regions on all devices
.br
.br
# dmstats delete --allregions --force
# dmstats delete --alldevices --allregions
.br
.br
@@ -611,7 +646,7 @@ using dmsetup
.br
# dmsetup stats create --areasize 10G vg00/lvol1
.br
Created region: 1
vg00/lvol1: Created new region with 5 area(s) as region ID 1
.br
.br
@@ -619,7 +654,7 @@ Create a 1GiB region with 16 areas at the start of vg00/lvol1
.br
# dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
.br
Created region: 2
vg00/lvol1: Created new region with 16 area(s) as region ID 0
.br
.br
@@ -627,13 +662,13 @@ List the statistics regions registered on vg00/lvol1
.br
# dmstats list vg00/lvol1
.br
RegionID RegStart RegLen AreaSize ProgramID AuxData
Name RgID RStart RSize #Areas ASize ProgID
.br
0 0 104857600 20971520 dmstats
vg00-lvol1 0 0 61.00g 1 61.00g dmstats
.br
1 0 104857600 20971520 dmstats
vg00-lvol1 1 61.00g 19.20g 1 19.20g dmstats
.br
2 0 2097152 131072 dmstats
vg00-lvol1 2 80.20g 2.14g 1 2.14g dmstats
.br
.br
@@ -642,19 +677,15 @@ Display five statistics reports for vg00/lvol1 at an interval of one second
.br
# dmstats report --interval 1 --count 5 vg00/lvol1
.br
Name RgID ArID RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize SvcTm Util% AWait
# dmstats report
.br
vg00-lvol1 0 0 0.00 0.00 8.00 0.00 48.00k 0 6.00k 0.00 5.50 4.40 6.62
Name RgID ArID AStart ASize RRqM/s WRqM/s R/s W/s RSz/s WSz/s AvRqSz QSize Util% AWait RdAWa WrAWa
.br
vg00-lvol1 0 1 0.00 0.00 22.00 0.00 624.00k 0 28.00k 0.00 5.23 11.50 5.36
vg_hex-lv_home 0 0 0 61.00g 0.00 0.00 0.00 218.00 0 1.04m 4.50k 2.97 81.70 13.62 0.00 13.62
.br
vg00-lvol1 0 2 0.00 0.00 353.00 0.00 1.84m 0 5.00k 0.00 1.34 47.40 1.33
vg_hex-lv_home 1 0 61.00g 19.20g 0.00 0.00 0.00 5.00 0 548.00k 109.50k 0.14 11.00 27.40 0.00 27.40
.br
vg00-lvol1 0 3 0.00 0.00 73.00 0.00 592.00k 0 8.00k 0.00 2.10 15.30 2.10
.br
vg00-lvol1 0 4 0.00 0.00 5.00 0.00 52.00k 0 10.00k 0.00 4.00 2.00 4.00
.br
[...]
vg_hex-lv_home 2 0 80.20g 2.14g 0.00 0.00 0.00 14.00 0 1.15m 84.00k 0.39 18.70 27.71 0.00 27.71
.br
.br
@@ -663,11 +694,11 @@ Create one region for reach target contained in device vg00/lvol1
.br
# dmstats create --segments vg00/lvol1
.br
Created region: 0
Created new region with 1 area(s) as region ID 0
.br
Created region: 1
Created new region with 1 area(s) as region ID 1
.br
Created region: 2
Created new region with 1 area(s) as region ID 2
.br
.br

View File

@@ -228,7 +228,7 @@ For more information on cache pool LVs and cache LVs, see \fBlvmcache\fP(7).
.TP
.B \-\-cachepolicy \fIpolicy
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
the cache policy. \fImq\fP is the basic policy name. \fIsqm\fP is more advanced
the cache policy. \fImq\fP is the basic policy name. \fIsmq\fP is more advanced
version available in newer kernels.
.TP
.BR \-\-cachepool " " \fICachePoolLV
@@ -326,7 +326,7 @@ operation from its arguments.
Separates \fICacheLogicalVolume\fP from cache pool.
Before the logical volume becomes uncached, cache is flushed.
The cache pool volume is then left unused and
could be used e.g. to caching another volume.
could be used e.g. for caching another volume.
See also the option \fB\-\-uncache\fP for uncaching and removing
cache pool with one command.
.TP

View File

@@ -200,7 +200,7 @@ cache pool LV.
.TP
.B \-\-cachepolicy \fIpolicy
Only applicable to cached LVs; see also \fBlvmcache(7)\fP. Sets
the cache policy. \fImq\fP is the basic policy name. \fIsqm\fP is more advanced
the cache policy. \fImq\fP is the basic policy name. \fIsmq\fP is more advanced
version available in newer kernels.
.TP
.IR \fB\-\-cachepool " " CachePoolLogicalVolume { Name | Path }

View File

@@ -164,6 +164,8 @@ fi
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/metadata_profile_template.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-generic.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-performance.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-mq.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-smq.profile
%dir %{_sysconfdir}/lvm/backup
%dir %{_sysconfdir}/lvm/cache
%dir %{_sysconfdir}/lvm/archive

View File

@@ -308,6 +308,12 @@ lv_field() {
die "lv_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
}
lva_field() {
local actual=$(get lva_field "$1" "$2" "${@:4}")
test "$actual" = "$3" || \
die "lva_field: lv=$1, field=\"$2\", actual=\"$actual\", expected=\"$3\""
}
lv_attr_bit() {
local actual=$(get lv_field "$2" lv_attr "${@:4}")
local offset=$1

View File

@@ -42,6 +42,11 @@ lv_field() {
trim_ "$r"
}
lva_field() {
local r=$(lvs -a --config 'log{prefix=""}' --noheadings -o "$2" "${@:3}" "$1")
trim_ "$r"
}
lv_devices() {
lv_field "$1" devices -a "${@:2}" | sed 's/([^)]*)//g; s/,/\n/g'
}

View File

@@ -15,6 +15,10 @@ test_description='Remove the dlm test setup'
[ -z "$LVM_TEST_LOCK_TYPE_DLM" ] && skip;
# FIXME: collect debug logs (only if a test failed?)
# lvmlockctl -d > lvmlockd-debug.txt
# dlm_tool dump > dlm-debug.txt
systemctl stop dlm
systemctl stop corosync
killall lvmlockd

View File

@@ -0,0 +1,32 @@
#!/bin/sh
# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Exercise conversion of cache and cache pool
. lib/inittest
test -e LOCAL_LVMPOLLD && skip
aux have_cache 1 8 0 || skip
aux prepare_vg 5 80
lvcreate --type cache-pool -an -v -L 2 -n cpool $vg
lvcreate -H --cachepolicy smq -L 4 -n corigin --cachepool $vg/cpool
check lv_field $vg/corigin cache_policy "smq"
lvconvert --splitcache $vg/corigin
lvs -o+cache_policy -a $vg
vgremove -f $vg

View File

@@ -1,5 +1,5 @@
#!/bin/sh
# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
# Copyright (C) 2014-2015 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
@@ -37,11 +37,25 @@ lvcreate -an -Zn -L 8 -n $lv3 $vg
lvcreate -an -Zn -L 8 -n $lv4 $vg
lvcreate -an -Zn -L 16 -n $lv5 $vg
lvconvert --yes --type cache-pool --cachepool $vg/$lv1
# check validation of cachemode arg works
fail lvconvert --yes --type cache-pool --cachemode writethroughX --cachepool $vg/$lv1
# by default no cache settings are attached to converted cache-pool
lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv1
check inactive $vg ${lv1}_cdata
lvconvert --yes --type cache-pool --chunksize 256 $vg/$lv2
check lv_field $vg/$lv1 cache_mode ""
check lv_field $vg/$lv1 cache_policy ""
check lv_field $vg/$lv1 cache_settings ""
check lv_field $vg/$lv1 chunk_size "256.00k"
# but allow to set them when specified explicitely on command line
lvconvert --yes --type cache-pool --cachemode writeback --cachepolicy mq \
--cachesettings sequential_threshold=1234 --cachesettings random_threshold=56 \
--cachepool $vg/$lv2
check inactive $vg ${lv2}_cdata
check lv_field $vg/$lv2 chunk_size "256.00k"
check lv_field $vg/$lv2 cache_mode "writeback"
check lv_field $vg/$lv2 cache_policy "mq"
check lv_field $vg/$lv2 cache_settings "random_threshold=56,sequential_threshold=1234"
# Check swap of cache pool metadata
lvconvert --yes --type cache-pool --poolmetadata $lv4 $vg/$lv3
@@ -58,7 +72,8 @@ lvremove -ff $vg
lvcreate -L 2 -n $lv1 $vg
lvcreate --type cache-pool -l 1 -n ${lv1}_cachepool $vg
lvconvert --cache --cachepool $vg/${lv1}_cachepool $vg/$lv1
lvconvert --cache --cachepool $vg/${lv1}_cachepool --cachemode writeback $vg/$lv1
check lv_field $vg/$lv1 cache_mode "writeback"
dmsetup table ${vg}-$lv1 | grep cache # ensure it is loaded in kernel
#lvconvert --cachepool $vg/${lv1}_cachepool $vg/$lv1

View File

@@ -63,8 +63,9 @@ vgcreate -s 1M $vg $(cat DEVICES)
# Testing dmeventd autoresize
lvcreate -L200M -V500M -n thin -T $vg/pool 2>&1 | tee out
not grep "WARNING: Sum" out
lvcreate -V2M -n thin2 $vg/pool
lvcreate -L2M -n $lv1 $vg
lvchange -an $vg/thin $vg/pool
lvchange -an $vg/thin $vg/thin2 $vg/pool
# Prepare some fake metadata with unmatching id
# Transaction_id is lower by 1 and there are no message -> ERROR
@@ -86,7 +87,7 @@ grep expected out
check inactive $vg pool_tmeta
# Prepare some fake metadata prefilled to ~81% (>70%)
fake_metadata_ 400 1 >data
fake_metadata_ 400 2 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
# Swap volume with restored fake metadata

View File

@@ -0,0 +1,164 @@
#!/bin/sh
# Copyright (C) 2008-2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
test_description='Check lvmlockd lock_args for different LV types'
. lib/inittest
[ -z "$LVM_TEST_LVMLOCKD" ] && skip;
if test -n "$LVM_TEST_LOCK_TYPE_SANLOCK" ; then
LOCKARGS1="1.0.0:70254592"
LOCKARGS2="1.0.0:71303168"
LOCKARGS3="1.0.0:72351744"
fi
if test -n "$LVM_TEST_LOCK_TYPE_DLM" ; then
LOCKARGS1="dlm"
LOCKARGS2="dlm"
LOCKARGS3="dlm"
fi
aux prepare_devs 5
vgcreate --shared $vg "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"
#
# thin pool, thin lv, thin snap
#
lvcreate -L 8M -n pool1 $vg
check lva_field $vg/pool1 lockargs $LOCKARGS1
lvcreate -L 8M -n pool1_meta $vg
check lva_field $vg/pool1_meta lockargs $LOCKARGS2
lvconvert -y --type thin-pool --poolmetadata $vg/pool1_meta $vg/pool1
check lva_field $vg/pool1 lockargs $LOCKARGS3
check lva_field $vg/pool1_tdata lockargs ""
check lva_field $vg/pool1_tmeta lockargs ""
lvcreate -n thin1 -V 1G --thinpool $vg/pool1
check lva_field $vg/thin1 lockargs ""
lvcreate -s -n snap1 $vg/thin1
check lva_field $vg/snap1 lockargs ""
lvchange -ay -K $vg/snap1
lvchange -an $vg/snap1
lvchange -an $vg/thin1
lvchange -an $vg/pool1
lvremove $vg/snap1
lvremove $vg/thin1
lvremove $vg/pool1
# the first sanlock lock should be found and reused
lvcreate -L 8M -n lv1 $vg
check lva_field $vg/lv1 lockargs $LOCKARGS1
lvchange -an $vg/lv1
lvremove $vg/lv1
#
# with automatic metadata lv
#
lvcreate -L 8M -n pool2 $vg
check lva_field $vg/pool2 lockargs $LOCKARGS1
lvconvert -y --type thin-pool $vg/pool2
check lva_field $vg/pool2 lockargs $LOCKARGS2
check lva_field $vg/pool2_tdata lockargs ""
check lva_field $vg/pool2_tmeta lockargs ""
lvcreate -n thin2 -V 1G --thinpool $vg/pool2
check lva_field $vg/thin2 lockargs ""
lvchange -an $vg/thin2
lvchange -an $vg/pool2
lvremove $vg/thin2
lvremove $vg/pool2
#
# cache pool, cache lv
#
lvcreate -L 8M -n cache1 $vg
check lva_field $vg/cache1 lockargs $LOCKARGS1
lvcreate -L 8M -n cache1_meta $vg
check lva_field $vg/cache1_meta lockargs $LOCKARGS2
lvconvert -y --type cache-pool --poolmetadata $vg/cache1_meta $vg/cache1
check lva_field $vg/cache1 lockargs ""
check lva_field $vg/cache1_cdata lockargs ""
check lva_field $vg/cache1_cmeta lockargs ""
lvcreate -n lv1 -L 8M $vg
check lva_field $vg/lv1 lockargs $LOCKARGS1
lvconvert -y --type cache --cachepool $vg/cache1 $vg/lv1
check lva_field $vg/lv1 lockargs $LOCKARGS1
check lva_field $vg/cache1 lockargs ""
check lva_field $vg/cache1_cdata lockargs ""
check lva_field $vg/cache1_cmeta lockargs ""
lvconvert --splitcache $vg/lv1
check lva_field $vg/lv1 lockargs $LOCKARGS1
check lva_field $vg/cache1 lockargs ""
check lva_field $vg/cache1_cdata lockargs ""
check lva_field $vg/cache1_cmeta lockargs ""
lvchange -an $vg/cache1
lvchange -an $vg/lv1
lvremove $vg/cache1
lvremove $vg/lv1
#
# cow snap
#
lvcreate -n lv2 -L 8M $vg
check lva_field $vg/lv2 lockargs $LOCKARGS1
lvcreate -s -n lv2snap -L 8M $vg/lv2
check lva_field $vg/lv2 lockargs $LOCKARGS1
check lva_field $vg/lv2snap lockargs ""
lvchange -y -an $vg/lv2
lvremove $vg/lv2snap
lvremove $vg/lv2
#
# mirror
#
lvcreate --type mirror -m 1 -n lv3 -L 8M $vg
check lva_field $vg/lv3 lockargs $LOCKARGS1
lvchange -an $vg/lv3
lvremove $vg/lv3
#
# raid1
#
lvcreate --type raid1 -m 1 -n lv4 -L 8M $vg
check lva_field $vg/lv4 lockargs $LOCKARGS1
lvchange -an $vg/lv4
lvremove $vg/lv4
vgremove $vg

View File

@@ -13,8 +13,6 @@ test_description='Test process_each_pv with zero mda'
. lib/inittest
test -e LOCAL_LVMPOLLD && skip
aux prepare_devs 14
# for vg1
@@ -41,9 +39,9 @@ pvcreate "$dev14" --metadatacopies 0
# dev12
# dev13
vgcreate $vg1 "$dev10"
vgcreate $vg2 "$dev2" "$dev3" "$dev4" "$dev5"
vgcreate $vg3 "$dev6" "$dev7" "$dev8" "$dev9"
vgcreate $SHARED $vg1 "$dev10"
vgcreate $SHARED $vg2 "$dev2" "$dev3" "$dev4" "$dev5"
vgcreate $SHARED $vg3 "$dev6" "$dev7" "$dev8" "$dev9"
pvs -a | tee err
grep "$dev10" err
@@ -59,3 +57,5 @@ grep "$dev11" err
grep "$dev12" err
grep "$dev13" err
grep "$dev14" err
vgremove $vg1 $vg2 $vg3

View File

@@ -13,15 +13,15 @@ test_description='Test process_each_pv with zero mda'
. lib/inittest
test -e LOCAL_LVMPOLLD && skip
aux prepare_devs 2
pvcreate "$dev1" --metadatacopies 0
pvcreate "$dev2"
vgcreate $vg1 "$dev1" "$dev2"
vgcreate $SHARED $vg1 "$dev1" "$dev2"
pvdisplay -a -C | tee err
grep "$dev1" err
grep "$dev2" err
vgremove $vg1

View File

@@ -73,6 +73,7 @@ prepare_lvmlockd_sanlock() {
GL_DEV="/dev/mapper/GL_DEV"
GL_FILE="$PWD/gl_file.img"
dmsetup remove GL_DEV || true
rm -f "$GL_FILE"
dd if=/dev/zero of="$GL_FILE" bs=$((1024*1024)) count=1024 2> /dev/null
GL_LOOP=$(losetup -f "$GL_FILE" --show)
@@ -80,7 +81,7 @@ echo "0 `blockdev --getsize $GL_LOOP` linear $GL_LOOP 0" | dmsetup create GL_DEV
prepare_lvmlockd_sanlock
vgcreate --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' --lock-type sanlock --lock-gl enable --lock-opt wait glvg $GL_DEV
vgcreate --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' --lock-type sanlock glvg $GL_DEV
vgs --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' -o+locktype,lockargs glvg

View File

@@ -15,14 +15,25 @@ test_description='Remove the sanlock test setup'
[ -z "$LVM_TEST_LOCK_TYPE_SANLOCK" ] && skip;
# FIMXME: get this to run after a test fails
# Removes the VG with the global lock that was created by
# the corresponding create script.
vgremove --config 'devices { global_filter=["a|GL_DEV|", "r|.*|"] filter=["a|GL_DEV|", "r|.*|"]}' glvg
# FIXME: collect debug logs (only if a test failed?)
# lvmlockctl -d > lvmlockd-debug.txt
# sanlock log_dump > sanlock-debug.txt
killall lvmlockd
killall sanlock
dmsetup remove GL_DEV
# dmsetup remove glvg-lvmlock
killall -9 lvmlockd
killall -9 sanlock
# FIXME: dmsetup remove LVMTEST*-lvmlock
dmsetup remove glvg-lvmlock || true
dmsetup remove GL_DEV || true

View File

@@ -29,8 +29,11 @@ lvcreate -T -L8M $vg/pool -V10M -n $lv1
# skip $vg from activation
aux lvmconf "activation/volume_list = [ \"$vg1\" ]"
# We cannot pass - pool volume cannot be manipulated
not lvcreate -V10 -n $lv2 -T $vg/pool
# We still could pass - since pool is still active
lvcreate -V10 -n $lv2 -T $vg/pool
# but $lv2 is not active
check inactive $vg $lv2
vgchange -an $vg

View File

@@ -275,6 +275,8 @@ xx(lvconvert,
"[--type cache[-pool]|-H|--cache]\n"
"\t[--cachepool CacheDataLogicalVolume[Path]]\n"
"\t[--cachemode CacheMode]\n"
"\t[--cachepolicy policy]\n"
"\t[--cachesettings key=value]\n"
"\t[--chunksize size]\n"
"\t[--poolmetadataspare {y|n}]]\n"
"\t[{--poolmetadata CacheMetadataLogicalVolume[Path] |\n"
@@ -282,7 +284,8 @@ xx(lvconvert,
COMMON_OPTS
"\t[Cache|CacheDataPool]LogicalVolume[Path] [PhysicalVolumePath...]\n\n",
alloc_ARG, background_ARG, cache_ARG, cachemode_ARG, cachepool_ARG, chunksize_ARG,
alloc_ARG, background_ARG, cache_ARG, cachemode_ARG,
cachepool_ARG, cachepolicy_ARG, cachesettings_ARG, chunksize_ARG,
corelog_ARG, discards_ARG, force_ARG, interval_ARG, merge_ARG, mirrorlog_ARG,
mirrors_ARG, name_ARG, noudevsync_ARG, originname_ARG, poolmetadata_ARG,
poolmetadatasize_ARG, poolmetadataspare_ARG, readahead_ARG, regionsize_ARG,
@@ -301,6 +304,8 @@ xx(lvcreate,
"\t[--alloc AllocationPolicy]\n"
"\t[-H|--cache\n"
"\t [--cachemode {writeback|writethrough}]\n"
"\t [--cachepolicy policy]\n"
"\t [--cachesettings key=value]\n"
"\t[--cachepool CachePoolLogicalVolume{Name|Path}]\n"
"\t[-c|--chunksize ChunkSize]\n"
"\t[-C|--contiguous {y|n}]\n"

File diff suppressed because it is too large Load Diff

View File

@@ -2002,7 +2002,7 @@ static int _lvconvert_uncache(struct cmd_context *cmd,
return 0;
}
if (!lv_remove_single(cmd, first_seg(lv)->pool_lv, lp->force, 0))
if (!lv_remove_single(cmd, first_seg(lv)->pool_lv, (force_t) lp->force, 0))
return_0;
log_print_unless_silent("Logical volume %s is not cached.", display_lvname(lv));
@@ -2430,7 +2430,7 @@ static int _lvconvert_pool_repair(struct cmd_context *cmd,
* Scan only the 1st. line for transation id.
* Watch out, if the thin_dump format changes
*/
if ((fgets(meta_path, sizeof(meta_path), f) > 0) &&
if (fgets(meta_path, sizeof(meta_path), f) &&
(trans_id_str = strstr(meta_path, "transaction=\"")) &&
(sscanf(trans_id_str + 13, FMTu64, &trans_id) == 1) &&
(trans_id != first_seg(pool_lv)->transaction_id) &&
@@ -2828,7 +2828,7 @@ static int _lvconvert_pool(struct cmd_context *cmd,
if (!metadata_lv) {
if (arg_from_list_is_set(cmd, "is invalid with existing pool",
cachemode_ARG, chunksize_ARG, discards_ARG,
chunksize_ARG, discards_ARG,
zero_ARG, poolmetadatasize_ARG, -1))
return_0;
@@ -3069,6 +3069,10 @@ mda_write:
seg->discards = lp->discards;
seg->zero_new_blocks = lp->zero ? 1 : 0;
if (lp->cache_mode &&
!cache_set_mode(seg, lp->cache_mode))
return_0;
if ((lp->policy_name || lp->policy_settings) &&
!cache_set_policy(seg, lp->policy_name, lp->policy_settings))
return_0;
@@ -3450,7 +3454,8 @@ bad:
unlock_vg(cmd, lp->vg_name);
/* Unlock here so it's not held during polling. */
lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, lp->vg_name, "un", 0, &lockd_state))
stack;
release_vg(vg);
out:

View File

@@ -574,7 +574,7 @@ static int _read_cache_params(struct cmd_context *cmd,
&lp->cache_mode,
&lp->policy_name,
&lp->policy_settings))
return_NULL;
return_0;
return 1;
}

View File

@@ -202,7 +202,8 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
unlock_and_release_vg(cmd, vg, vg->name);
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
/*
* FIXME Sleeping after testing, while preferred, also works around
@@ -225,7 +226,9 @@ int wait_for_single_lv(struct cmd_context *cmd, struct poll_operation_id *id,
out:
if (vg)
unlock_and_release_vg(cmd, vg, vg->name);
lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, id->vg_name, "un", 0, &lockd_state))
stack;
return ret;
}

View File

@@ -712,7 +712,8 @@ out_ret:
* for some time monitoring the progress, and we don not want
* or need the lockd lock held over that.
*/
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
return r;
}
@@ -762,7 +763,8 @@ static int _read_poll_id_from_pvname(struct cmd_context *cmd, const char *pv_nam
unlock_and_release_vg(cmd, vg, vg_name);
out:
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
free_pv_fid(pv);
return ret;
}

View File

@@ -1957,7 +1957,8 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
unlock_vg(cmd, vg_name);
endvg:
release_vg(vg);
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
}
/* the VG is selected if at least one LV is selected */
@@ -2438,7 +2439,8 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
unlock_vg(cmd, vg_name);
endvg:
release_vg(vg);
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
}
return ret_max;
@@ -2942,7 +2944,8 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
unlock_vg(cmd, vg->name);
endvg:
release_vg(vg);
lockd_vg(cmd, vg_name, "un", 0, &lockd_state);
if (!lockd_vg(cmd, vg_name, "un", 0, &lockd_state))
stack;
/* Quit early when possible. */
if (!process_all_pvs && dm_list_empty(arg_tags) && dm_list_empty(arg_devices))

View File

@@ -1227,7 +1227,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, lockstart_ARG)) {
const char *start_opt = arg_str_value(cmd, lockopt_ARG, NULL);
lockd_gl(cmd, "un", 0);
if (!lockd_gl(cmd, "un", 0))
stack;
if (!start_opt || !strcmp(start_opt, "auto")) {
log_print_unless_silent("Starting locking. Waiting until locks are ready...");

View File

@@ -22,8 +22,6 @@ static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
if (arg_count(cmd, activevolumegroups_ARG) && !lvs_in_vg_activated(vg))
return ECMD_PROCESSED;
vg_check_status(vg, EXPORTED_VG);
if (arg_count(cmd, colon_ARG)) {
vgdisplay_colons(vg);
return ECMD_PROCESSED;

View File

@@ -47,7 +47,7 @@ BLKID_RULE=IMPORT{program}=\"${SBIN}\/blkid -o udev -p \$$tempnode\"
endif
ifeq ("@UDEV_SYSTEMD_BACKGROUND_JOBS@", "yes")
PVSCAN_RULE=ACTION\!=\"remove\", ENV{LVM_PV_GONE}==\"1\", RUN\+=\"@bindir@/systemd-run $(LVM_EXEC)\/lvm pvscan --cache \$$major\:\$$minor\", GOTO=\"lvm_end\"\nENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}+=\"lvm2-pvscan@\$$major:\$$minor.service\"
PVSCAN_RULE=ACTION\!=\"remove\", ENV{LVM_PV_GONE}==\"1\", RUN\+=\"@bindir@/systemd-run $(LVM_EXEC)\/lvm pvscan --cache \$$major\:\$$minor\", GOTO=\"lvm_end\"\nENV{SYSTEMD_ALIAS}=\"\/dev\/block\/\$$major:\$$minor\"\nENV{ID_MODEL}=\"LVM PV \$$env{ID_FS_UUID_ENC} on \/dev\/\$$name\"\nENV{SYSTEMD_WANTS}\+=\"lvm2-pvscan@\$$major:\$$minor.service\"
else
PVSCAN_RULE=RUN\+\=\"$(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major \$$major --minor \$$minor\", ENV{LVM_SCANNED}=\"1\"
endif