diff options
author | Zdenek Kabelac <zkabelac@redhat.com> | 2014-02-25 19:43:07 +0100 |
---|---|---|
committer | Zdenek Kabelac <zkabelac@redhat.com> | 2014-02-26 14:25:09 +0100 |
commit | 40e6176d251b68f5be8ca7925a2f073982de6cec (patch) | |
tree | 242b7de295036a3893fa0b1a956621ed50ff058d /lib/snapshot | |
parent | 014ba37cb19c9172b1b81af3f31897939f72b1d2 (diff) | |
download | lvm2-40e6176d251b68f5be8ca7925a2f073982de6cec.tar.gz |
snapshots: fix incorrect calculation of cow size
Code uses target driver version for better estimation of
max size of COW device for snapshot.
The bug can be tested with this script:
VG=vg1
lvremove -f $VG/origin
set -e
lvcreate -L 2143289344b -n origin $VG
lvcreate -n snap -c 8k -L 2304M -s $VG/origin
dd if=/dev/zero of=/dev/$VG/snap bs=1M count=2044 oflag=direct
The bug happens when these two conditions are met
* origin size is divisible by (chunk_size/16) - so that the last
metadata area is filled completely
* the miscalculated snapshot metadata size is divisible by extent size -
so that there is no padding to extent boundary which would otherwise
save us
Signed-off-by:Mikulas Patocka <mpatocka@redhat.com>
Diffstat (limited to 'lib/snapshot')
-rw-r--r-- | lib/snapshot/snapshot.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c index 91e778f6d..0b7b84568 100644 --- a/lib/snapshot/snapshot.c +++ b/lib/snapshot/snapshot.c @@ -142,19 +142,30 @@ static int _snap_target_percent(void **target_state __attribute__((unused)), static int _snap_target_present(struct cmd_context *cmd, const struct lv_segment *seg, - unsigned *attributes __attribute__((unused))) + unsigned *attributes) { static int _snap_checked = 0; static int _snap_merge_checked = 0; static int _snap_present = 0; static int _snap_merge_present = 0; + static unsigned _snap_attrs = 0; + uint32_t maj, min, patchlevel; if (!_snap_checked) { + _snap_checked = 1; _snap_present = target_present(cmd, "snapshot", 1) && target_present(cmd, "snapshot-origin", 0); - _snap_checked = 1; + + if (_snap_present && + target_version("snapshot", &maj, &min, &patchlevel) && + (maj > 1 || + (maj == 1 && (min >= 12 || (min == 10 && patchlevel >= 2))))) + _snap_attrs |= SNAPSHOT_FEATURE_FIXED_LEAK; + else + log_very_verbose("Target snapshot may leak metadata."); } + /* TODO: test everything at once */ if (seg && (seg->status & MERGING)) { if (!_snap_merge_checked) { _snap_merge_present = target_present(cmd, "snapshot-merge", 0); |