master - metadata: Detect internal use of LVM_WRITE_LOCKED.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a8545462349c56...
Commit: a8545462349c560cf66362cb3d25b44b7b0e819b
Parent: faccdeda83ee8c04546a2224fa2dee82a55413fe
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Mon Mar 9 18:56:24 2015 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Mon Mar 9 18:56:24 2015 +0000
metadata: Detect internal use of LVM_WRITE_LOCKED.
Generate internal error if LVM_WRITE_LOCKED ever appears
in struct volume_group: it's only used in external
metadata.
---
lib/metadata/metadata.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index ab23d25..21066fb 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2495,6 +2495,12 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
+ if (vg->status & LVM_WRITE_LOCKED) {
+ log_error(INTERNAL_ERROR "VG %s has external flag LVM_WRITE_LOCKED set internally.",
+ vg->name);
+ r = 0;
+ }
+
/* FIXME Also check there's no data/metadata overlap */
if (!(vhash.pvid = dm_hash_create(vg->pv_count))) {
log_error("Failed to allocate pvid hash.");
@@ -2568,6 +2574,12 @@ int vg_validate(struct volume_group *vg)
dm_list_iterate_items(lvl, &vg->lvs) {
lv_count++;
+ if (lvl->lv->status & LVM_WRITE_LOCKED) {
+ log_error(INTERNAL_ERROR "LV %s has external flag LVM_WRITE_LOCKED set internally.",
+ vg->name);
+ r = 0;
+ }
+
dev_name_len = strlen(lvl->lv->name) + vg_name_len + 3;
if (dev_name_len >= NAME_LEN) {
log_error(INTERNAL_ERROR "LV name \"%s/%s\" length %"
8 years, 3 months
master - comments: Use full flag names.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=faccdeda83ee8c...
Commit: faccdeda83ee8c04546a2224fa2dee82a55413fe
Parent: e9a233ee8ef362fccc5537125a19c28e5d596168
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Mon Mar 9 18:53:22 2015 +0000
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Mon Mar 9 18:53:22 2015 +0000
comments: Use full flag names.
---
lib/format_text/export.c | 8 ++++----
lib/metadata/metadata-exported.h | 2 +-
lib/metadata/metadata.c | 14 +++++++-------
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 2d985b4..018772e 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -411,8 +411,8 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
outfc(f, "# informational", "format = \"%s\"", fmt->name);
/*
- * Removing WRITE and adding WRITE_LOCKED makes it read-only
- * to old versions of lvm that only look for WRITE.
+ * Removing WRITE and adding LVM_WRITE_LOCKED makes it read-only
+ * to old versions of lvm that only look for LVM_WRITE.
*/
if ((status & LVM_WRITE) && vg_flag_write_locked(vg)) {
status &= ~LVM_WRITE;
@@ -630,8 +630,8 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
outf(f, "id = \"%s\"", buffer);
/*
- * Removing WRITE and adding WRITE_LOCKED makes it read-only
- * to old versions of lvm that only look for WRITE.
+ * Removing WRITE and adding LVM_WRITE_LOCKED makes it read-only
+ * to old versions of lvm that only look for LVM_WRITE.
*/
if ((status & LVM_WRITE) && vg_flag_write_locked(lv->vg)) {
status &= ~LVM_WRITE;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b5ab1f2..414216a 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -58,6 +58,7 @@
#define LVM_READ UINT64_C(0x0000000000000100) /* LV, VG */
#define LVM_WRITE UINT64_C(0x0000000000000200) /* LV, VG */
+#define LVM_WRITE_LOCKED UINT64_C(0x0020000000000000) /* LV, VG */
#define CLUSTERED UINT64_C(0x0000000000000400) /* VG */
//#define SHARED UINT64_C(0x0000000000000800) /* VG */
@@ -122,7 +123,6 @@
#define PV_ALLOCATION_PROHIBITED UINT64_C(0x0010000000000000) /* PV - internal use only - allocation prohibited
e.g. to prohibit allocation of a RAID image
on a PV already holing an image of the RAID set */
-#define LVM_WRITE_LOCKED UINT64_C(0x0020000000000000) /* VG, LV */
/* Next unused flag: UINT64_C(0x0040000000000000) */
/* Format features flags */
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index f495bdd..ab23d25 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -4249,22 +4249,22 @@ int vg_check_write_mode(struct volume_group *vg)
/*
* Return 1 if the VG metadata should be written
- * *without* the WRITE flag in the status line, and
- * *with* the WRITE_LOCKED flag in the flags line.
+ * *without* the LVM_WRITE flag in the status line, and
+ * *with* the LVM_WRITE_LOCKED flag in the flags line.
*
* If this is done for a VG, it forces previous versions
- * of lvm (before the WRITE_LOCKED flag was added), to view
- * the VG and its LVs as read-only (because the WRITE flag
+ * of lvm (before the LVM_WRITE_LOCKED flag was added), to view
+ * the VG and its LVs as read-only (because the LVM_WRITE flag
* is missing). Versions of lvm that understand the
- * WRITE_LOCKED flag know to check the other methods of
+ * LVM_WRITE_LOCKED flag know to check the other methods of
* access control for the VG, specifically system_id and lock_type.
*
* So, if a VG has a system_id or lock_type, then the
* system_id and lock_type control access to the VG in
* addition to its basic writable status. Because previous
* lvm versions do not know about system_id or lock_type,
- * VGs depending on either of these should have WRITE_LOCKED
- * instead of WRITE to prevent the previous lvm versions from
+ * VGs depending on either of these should have LVM_WRITE_LOCKED
+ * instead of LVM_WRITE to prevent the previous lvm versions from
* assuming they can write the VG and its LVs.
*/
int vg_flag_write_locked(struct volume_group *vg)
8 years, 3 months
master - system_id: detect an lvm1 system id
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=e9a233ee8ef362...
Commit: e9a233ee8ef362fccc5537125a19c28e5d596168
Parent: 08371a8b8031b43394d80612d24029cfd4c710d4
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Mar 9 13:27:34 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon Mar 9 13:27:34 2015 -0500
system_id: detect an lvm1 system id
Detect an lvm1 system id by looking at the WRITE_LOCKED flag.
Don't copy this lvm1 system id into vg->system_id so that the
restrictions associated with the new system id are not applied
to the old VG with the inherited lvm1 system id.
---
lib/format_text/import_vsn1.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 6afe71d..837af6b 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -812,6 +812,14 @@ static struct volume_group *_read_vg(struct format_instance *fid,
goto bad;
}
+ /*
+ * A system id without WRITE_LOCKED is an old lvm1 system id.
+ */
+ if (!(vg->status & LVM_WRITE_LOCKED) && system_id[0]) {
+ memcpy(vg->lvm1_system_id, system_id, NAME_LEN + 1);
+ memset(system_id, 0, NAME_LEN + 1);
+ }
+
if (vg->status & LVM_WRITE_LOCKED) {
vg->status |= LVM_WRITE;
vg->status &= ~LVM_WRITE_LOCKED;
8 years, 3 months
master - tests: fix systemid uname test
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=08371a8b8031b4...
Commit: 08371a8b8031b43394d80612d24029cfd4c710d4
Parent: 588b3bd7a16b19423f9c4d06b27a3cbe7ac9d623
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Mar 6 09:55:24 2015 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Mar 6 09:57:37 2015 -0600
tests: fix systemid uname test
The string reported by uname -n may include characters
that lvm omits from the system id (like parens, as seen
on a test machine.) Check against the final system id
string that lvm uses.
---
test/shell/system_id.sh | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/shell/system_id.sh b/test/shell/system_id.sh
index 6e80c1a..6aa367b 100644
--- a/test/shell/system_id.sh
+++ b/test/shell/system_id.sh
@@ -38,12 +38,13 @@ fi
## uname
-SID=$(uname -n)
-if [ -n $SID ]; then
+SID1=$(uname -n)
+if [ -n $SID1 ]; then
aux lvmconf "global/system_id_source = uname"
+SID2=$(lvm systemid | awk '{ print $3 }')
vgcreate $vg1 "$dev1"
vgs -o+systemid $vg1
-check vg_field $vg1 systemid $SID
+check vg_field $vg1 systemid $SID2
vgremove $vg1
fi
8 years, 3 months
master - tests: speed of many PVS in a VG
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=588b3bd7a16b19...
Commit: 588b3bd7a16b19423f9c4d06b27a3cbe7ac9d623
Parent: 85ef614b37bafd3c91c9fb6e6cfb6c40d6f80f99
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Mar 6 14:29:26 2015 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 14:29:26 2015 +0100
tests: speed of many PVS in a VG
---
test/shell/vgcreate-many-pvs.sh | 62 +++++++++++++++++++++++++++++++++++++++
1 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/test/shell/vgcreate-many-pvs.sh b/test/shell/vgcreate-many-pvs.sh
new file mode 100644
index 0000000..c6d3852
--- /dev/null
+++ b/test/shell/vgcreate-many-pvs.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Copyright (C) 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
+# 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
+
+. lib/inittest
+
+#
+# Test to exercise larger number of PVs in a VG
+# Related to https://bugzilla.redhat.com/show_bug.cgi?id=736027
+#
+# Original measured times of the whole test case before
+# and with the acceleration patch from my bare metal hw
+# (Lenovo T61, 2.2GHz, 4G RAM, rawhide 2015-03-06 with ndebug kernel):
+#
+# export LVM_TEST_PVS=300
+#
+# make check_local ~52sec (U:29s, S:13s)
+# make check_lvmetad ~20sec (U: 4s, S: 5s)
+#
+# With patch from 2015-03-06:
+#
+# make check_local ~30sec (U:10s, S:12s)
+# make check_lvmetad ~20sec (U: 4s, S: 5s)
+#
+
+# TODO: extend test suite to monitor performance and report regressions...
+
+# Use just 100 to get 'decent' speed on slow boxes
+LVM_TEST_PVS=${LVM_TEST_PVS:-100}
+
+#aux prepare_devs $LVM_TEST_PVS 8
+#vgcreate $vg $(< DEVICES)
+
+# prepare_vg is now directly using steps above
+aux prepare_vg $LVM_TEST_PVS
+
+# Check we have decent speed with typical commands
+vgs
+
+lvs
+
+pvs
+
+lvcreate -l1 -n $lv1 $vg
+
+lvremove -f $vg/$lv1
+
+vgremove -ff $vg
+
+#
+# TODO Turn this into another test case:
+#
+#for i in $(seq 1 $LVM_TEST_PVS); do
+# vgcreate ${vg}$i "$DM_DEV_DIR/mapper/${PREFIX}pv$i"
+#done
8 years, 3 months
master - tests: slightly more efficient vgcreate
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=85ef614b37bafd...
Commit: 85ef614b37bafd3c91c9fb6e6cfb6c40d6f80f99
Parent: 04101bc4307e14f71f6ca3a1d253761f82e6a76e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Mar 6 13:29:35 2015 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 14:05:06 2015 +0100
tests: slightly more efficient vgcreate
With larger set of devices it's faster to directly call
vgcreate on empty set of devices then going though separate
pvcreate call first.
---
test/lib/aux.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/test/lib/aux.sh b/test/lib/aux.sh
index d3a3382..339da31 100644
--- a/test/lib/aux.sh
+++ b/test/lib/aux.sh
@@ -576,7 +576,7 @@ prepare_pvs() {
prepare_vg() {
teardown_devs
- prepare_pvs "$@"
+ prepare_devs "$@"
vgcreate -s 512K $vg "${DEVICES[@]}"
}
8 years, 3 months
master - lib: drop unneeded vg_read call
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=04101bc4307e14...
Commit: 04101bc4307e14f71f6ca3a1d253761f82e6a76e
Parent: a9b28a4f2105b92fdfc9f3915859e0deec4004a0
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Mar 6 10:22:33 2015 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 14:05:06 2015 +0100
lib: drop unneeded vg_read call
Since we take a lock inside vg_lock_newname() and we do a full
detection of presence of vgname inside all scanned labels,
there is no point to do this for second time to be sure
there is no such vg.
The only side-effect of such call would be a full validation of
some already exising VG metadata - but that's not the task for
vgcreate when create a new VG.
This call noticable reduces number of scans during 'vgcreate'.
---
WHATS_NEW | 1 +
lib/metadata/metadata.c | 10 ----------
2 files changed, 1 insertions(+), 10 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 9bf8699..680879d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.118 -
=================================
+ Don't do a full read of VG when creating a new VG with an existing name.
Reduce number of VG metadata parsing when looking for vgname on a PV.
Avoid reparsing same metadata when reading same metadata from multiple PVs.
Save extra device open/close when scanning device for size.
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 57066a5..f495bdd 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1009,7 +1009,6 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
.context.vg_ref.vg_name = vg_name
};
struct format_instance *fid;
- int consistent = 0;
uint32_t rc;
if (!validate_name(vg_name)) {
@@ -1023,15 +1022,6 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
/* NOTE: let caller decide - this may be check for existence */
return _vg_make_handle(cmd, NULL, rc);
- /* FIXME: Is this vg_read_internal necessary? Move it inside
- vg_lock_newname? */
- /* is this vg name already in use ? */
- if ((vg = vg_read_internal(cmd, vg_name, NULL, WARN_PV_READ, &consistent))) {
- log_error("A volume group called '%s' already exists.", vg_name);
- unlock_and_release_vg(cmd, vg, vg_name);
- return _vg_make_handle(cmd, NULL, FAILED_EXIST);
- }
-
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, cmd->dev_dir);
8 years, 3 months
master - lib: reduce parsing in vgname_from_mda
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a9b28a4f2105b9...
Commit: a9b28a4f2105b92fdfc9f3915859e0deec4004a0
Parent: 7e7411966afc4309cdd91bfed4846720b308c84d
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Mar 6 10:24:26 2015 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 13:53:13 2015 +0100
lib: reduce parsing in vgname_from_mda
Use similar logic as with text_vg_import_fd() and avoid repeated
parsing of same mda and its config tree for vgname_from_mda().
Remember last parsed vgname, vgid and creation_host in labeller
structure and if the metadata have the same size and checksum,
return this stored info.
TODO: The reuse of labeller struct is not ideal, some lvmcache API for
this functionality would be nicer.
---
WHATS_NEW | 1 +
lib/format_text/format-text.c | 23 ++++++++++++++++++-----
lib/format_text/import-export.h | 9 +++++----
lib/format_text/import.c | 13 +++++++++++--
lib/format_text/layout.h | 4 +++-
lib/format_text/text_label.c | 27 ++++++++++++++++-----------
lib/label/label.h | 8 ++++++++
7 files changed, 62 insertions(+), 23 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index ef5abcd..9bf8699 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.118 -
=================================
+ Reduce number of VG metadata parsing when looking for vgname on a PV.
Avoid reparsing same metadata when reading same metadata from multiple PVs.
Save extra device open/close when scanning device for size.
Fix seg_monitor field to report status also for mirrors and thick snapshots.
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 375a793..d80ebf6 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -1124,14 +1124,14 @@ static int _scan_file(const struct format_type *fmt, const char *vgname)
}
const char *vgname_from_mda(const struct format_type *fmt,
- struct mda_header *mdah,
- struct device_area *dev_area, struct id *vgid,
+ struct mda_header *mdah, struct device_area *dev_area,
+ uint32_t *mda_checksum, size_t *mda_size,
+ const char *vgname, struct id *vgid,
uint64_t *vgstatus, char **creation_host,
uint64_t *mda_free_sectors)
{
struct raw_locn *rlocn;
uint32_t wrap = 0;
- const char *vgname = NULL;
unsigned int len = 0;
char buf[NAME_LEN + 1] __attribute__((aligned(8)));
char uuid[64] __attribute__((aligned(8)));
@@ -1182,6 +1182,10 @@ const char *vgname_from_mda(const struct format_type *fmt,
return NULL;
}
+ /* Check if it could be the same VG */
+ if ((rlocn->checksum != *mda_checksum) || (rlocn->size != *mda_size))
+ vgname = NULL; /* nope, reset to NULL */
+
/* FIXME 64-bit */
if (!(vgname = text_vgname_import(fmt, dev_area->dev,
(off_t) (dev_area->start +
@@ -1190,6 +1194,7 @@ const char *vgname_from_mda(const struct format_type *fmt,
(off_t) (dev_area->start +
MDA_HEADER_SIZE),
wrap, calc_crc, rlocn->checksum,
+ vgname,
vgid, vgstatus, creation_host)))
return_NULL;
@@ -1217,6 +1222,9 @@ const char *vgname_from_mda(const struct format_type *fmt,
*mda_free_sectors = ((buffer_size - 2 * current_usage) / 2) >> SECTOR_SHIFT;
}
+ *mda_checksum = rlocn->checksum;
+ *mda_size = rlocn->size;
+
return vgname;
}
@@ -1230,6 +1238,8 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
struct id vgid;
uint64_t vgstatus;
struct mda_header *mdah;
+ uint32_t mda_checksum = 0;
+ size_t mda_size = 0;
raw_list = &((struct mda_lists *) fmt->private)->raws;
@@ -1249,9 +1259,12 @@ static int _scan_raw(const struct format_type *fmt, const char *vgname __attribu
goto close_dev;
}
+ /* TODO: caching as in vgname_from_mda() (trigger this code?) */
if ((scanned_vgname = vgname_from_mda(fmt, mdah,
- &rl->dev_area, &vgid, &vgstatus,
- NULL, NULL))) {
+ &rl->dev_area,
+ &mda_checksum, &mda_size, NULL,
+ &vgid, &vgstatus,
+ NULL, NULL))) {
vg = _vg_read_raw_area(&fid, scanned_vgname, &rl->dev_area, 0, 0);
if (vg)
lvmcache_update_vg(vg, 0);
diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h
index d4e25f0..4b2756d 100644
--- a/lib/format_text/import-export.h
+++ b/lib/format_text/import-export.h
@@ -79,10 +79,11 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
time_t *when, char **desc);
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
- off_t offset, uint32_t size,
- off_t offset2, uint32_t size2,
- checksum_fn_t checksum_fn, uint32_t checksum,
- struct id *vgid, uint64_t *vgstatus,
+ off_t offset, uint32_t size,
+ off_t offset2, uint32_t size2,
+ checksum_fn_t checksum_fn, uint32_t checksum,
+ const char *vgname,
+ struct id *vgid, uint64_t *vgstatus,
char **creation_host);
#endif
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index 8a1771a..c8ba5ce 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -32,17 +32,22 @@ static void _init_text_import(void)
_text_import_initialised = 1;
}
+/*
+ * Find out vgname on a given device.
+ * If the checksum and metadata size is matching the vgname discovered in last read
+ * (multi PVs VG) could be passed back and it may skip parsing of such metadata.
+ */
const char *text_vgname_import(const struct format_type *fmt,
struct device *dev,
off_t offset, uint32_t size,
off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, uint32_t checksum,
+ const char *vgname,
struct id *vgid, uint64_t *vgstatus,
char **creation_host)
{
struct dm_config_tree *cft;
struct text_vg_version_ops **vsn;
- const char *vgname = NULL;
_init_text_import();
@@ -51,11 +56,15 @@ const char *text_vgname_import(const struct format_type *fmt,
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
- offset2, size2, checksum_fn, checksum, 0))) {
+ offset2, size2, checksum_fn, checksum,
+ (vgname != NULL)))) {
log_error("Couldn't read volume group metadata.");
goto out;
}
+ if (vgname)
+ goto out; /* Everything is matching from the last call */
+
/*
* Find a set of version functions that can read this file
*/
diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h
index 4753fde..5f6b549 100644
--- a/lib/format_text/layout.h
+++ b/lib/format_text/layout.h
@@ -100,7 +100,9 @@ struct mda_context {
const char *vgname_from_mda(const struct format_type *fmt,
struct mda_header *mdah,
- struct device_area *dev_area, struct id *vgid,
+ struct device_area *dev_area,
+ uint32_t *mda_checksum, size_t *mda_size,
+ const char *vgname, struct id *vgid,
uint64_t *vgstatus, char **creation_host,
uint64_t *mda_free_sectors);
diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c
index e451be4..3a4835c 100644
--- a/lib/format_text/text_label.c
+++ b/lib/format_text/text_label.c
@@ -319,10 +319,14 @@ static int _update_mda(struct metadata_area *mda, void *baton)
const struct format_type *fmt = p->label->labeller->fmt;
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
- const char *vgname = NULL;
- struct id vgid;
- uint64_t vgstatus;
- char *creation_host;
+ struct labeller *l = p->label->labeller;
+
+ /*
+ * Using the labeller struct to preserve info about
+ * the last parsed vgname, vgid, creation host
+ *
+ * TODO: make lvmcache smarter and move this cache logic there
+ */
if (!dev_open_readonly(mdac->area.dev)) {
mda_set_ignored(mda, 1);
@@ -346,17 +350,18 @@ static int _update_mda(struct metadata_area *mda, void *baton)
return 1;
}
- if ((vgname = vgname_from_mda(fmt, mdah,
- &mdac->area,
- &vgid, &vgstatus, &creation_host,
- &mdac->free_sectors)) &&
- !lvmcache_update_vgname_and_id(p->info, vgname,
- (char *) &vgid, vgstatus,
- creation_host)) {
+ if ((l->vgname = vgname_from_mda(fmt, mdah, &mdac->area,
+ &l->mda_checksum, &l->mda_size, l->vgname,
+ &l->vgid, &l->vgstatus, &l->creation_host,
+ &mdac->free_sectors)) &&
+ !lvmcache_update_vgname_and_id(p->info, l->vgname,
+ (char *) &l->vgid, l->vgstatus,
+ l->creation_host)) {
if (!dev_close(mdac->area.dev))
stack;
return_0;
}
+
close_dev:
if (!dev_close(mdac->area.dev))
stack;
diff --git a/lib/label/label.h b/lib/label/label.h
index 253e1e8..831977f 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -89,6 +89,14 @@ struct label_ops {
struct labeller {
struct label_ops *ops;
const struct format_type *fmt;
+
+ /* Caching info */
+ const char *vgname;
+ struct id vgid;
+ uint64_t vgstatus;
+ char *creation_host;
+ uint32_t mda_checksum;
+ size_t mda_size;
};
int label_init(void);
8 years, 3 months
master - lib: avoid reparsing same metadata
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7e7411966afc43...
Commit: 7e7411966afc4309cdd91bfed4846720b308c84d
Parent: 6a2ae250ffc52c7620ec837cb10eb7b9ca44a121
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Mar 26 13:35:26 2012 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 13:53:12 2015 +0100
lib: avoid reparsing same metadata
When reading VG mda from multiple PVs - do all the validation only
when mda is seen for the first time and when mda checksum and length
is same just return already existing VG pointer.
(i.e. using 300PVs for a VG would lead to create and destroy 300 config trees....)
---
WHATS_NEW | 1 +
lib/config/config.c | 18 +++++++++++++-----
lib/config/config.h | 3 ++-
lib/format_text/import.c | 24 ++++++++++++++++++++++--
lib/metadata/metadata-exported.h | 5 +++++
lib/metadata/metadata.c | 1 +
6 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index b62a632..ef5abcd 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.118 -
=================================
+ Avoid reparsing same metadata when reading same metadata from multiple PVs.
Save extra device open/close when scanning device for size.
Fix seg_monitor field to report status also for mirrors and thick snapshots.
diff --git a/lib/config/config.c b/lib/config/config.c
index effe93d..5de6df6 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -478,9 +478,15 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
return 0;
}
+/*
+ * When skip_parse is set, the checksum of buffer is only matched
+ * and function avoids parsing of mda into config tree which
+ * remains unmodified and should not be used.
+ */
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
- checksum_fn_t checksum_fn, uint32_t checksum)
+ checksum_fn_t checksum_fn, uint32_t checksum,
+ int skip_parse)
{
char *fb, *fe;
int r = 0;
@@ -529,9 +535,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
goto out;
}
- fe = fb + size + size2;
- if (!dm_config_parse(cft, fb, fe))
- goto_out;
+ if (!skip_parse) {
+ fe = fb + size + size2;
+ if (!dm_config_parse(cft, fb, fe))
+ goto_out;
+ }
r = 1;
@@ -575,7 +583,7 @@ int config_file_read(struct dm_config_tree *cft)
}
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
- (checksum_fn_t) NULL, 0);
+ (checksum_fn_t) NULL, 0, 0);
if (!cf->keep_open) {
if (!dev_close(cf->dev))
diff --git a/lib/config/config.h b/lib/config/config.h
index ba34354..50ea361 100644
--- a/lib/config/config.h
+++ b/lib/config/config.h
@@ -205,7 +205,8 @@ typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_
struct dm_config_tree *config_open(config_source_t source, const char *filename, int keep_open);
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2,
- checksum_fn_t checksum_fn, uint32_t checksum);
+ checksum_fn_t checksum_fn, uint32_t checksum,
+ int skip_parse);
int config_file_read(struct dm_config_tree *cft);
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
struct cmd_context *cmd);
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index fe19dd7..8a1771a 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -51,7 +51,7 @@ const char *text_vgname_import(const struct format_type *fmt,
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
- offset2, size2, checksum_fn, checksum))) {
+ offset2, size2, checksum_fn, checksum, 0))) {
log_error("Couldn't read volume group metadata.");
goto out;
}
@@ -88,6 +88,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
struct volume_group *vg = NULL;
struct dm_config_tree *cft;
struct text_vg_version_ops **vsn;
+ int skip_parse;
_init_text_import();
@@ -97,11 +98,20 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
if (!(cft = config_open(CONFIG_FILE_SPECIAL, file, 0)))
return_NULL;
+ skip_parse = fid->vg && (fid->mda_checksum == checksum) &&
+ (fid->mda_size == (size + size2));
+
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
- offset2, size2, checksum_fn, checksum)))
+ offset2, size2, checksum_fn, checksum,
+ skip_parse)))
goto_out;
+ if (skip_parse) {
+ vg = fid->vg;
+ goto out;
+ }
+
/*
* Find a set of version functions that can read this file
*/
@@ -116,6 +126,16 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
break;
}
+ if (vg && (!fid->vg || (vg->seqno > fid->vg->seqno))) {
+ /*
+ * Remember vg pointer to newest VG for reuse.
+ * NOTE: _vg_read() will not release same VG
+ */
+ fid->vg = vg;
+ fid->mda_size = (size + size2);
+ fid->mda_checksum = checksum;
+ }
+
out:
config_destroy(cft);
return vg;
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 8c081d9..b5ab1f2 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -324,6 +324,11 @@ struct format_instance {
struct dm_list metadata_areas_ignored;
struct dm_hash_table *metadata_areas_index;
+ /* Remember last vg to avoid parsing same mda content for multiple PVs */
+ struct volume_group *vg;
+ uint32_t mda_checksum;
+ size_t mda_size;
+
void *private;
};
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 7e440a4..57066a5 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -3365,6 +3365,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if (vg != correct_vg)
+ /* NOTE: tied to fid->vg logic in text_vg_import_fd() */
release_vg(vg);
}
fid->ref_count--;
8 years, 3 months
master - cleanup: add stack trace
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6a2ae250ffc52c...
Commit: 6a2ae250ffc52c7620ec837cb10eb7b9ca44a121
Parent: 60427d5d429b88d1c6cd13f90794f9b50dc366e6
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Mar 6 11:12:16 2015 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Mar 6 13:51:54 2015 +0100
cleanup: add stack trace
Missed stack in error path.
---
lib/format_text/import.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index 4b02264..fe19dd7 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -100,7 +100,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
if ((!dev && !config_file_read(cft)) ||
(dev && !config_file_read_fd(cft, dev, offset, size,
offset2, size2, checksum_fn, checksum)))
- goto out;
+ goto_out;
/*
* Find a set of version functions that can read this file
8 years, 3 months