* [PATCH 00/11] Pool locking
@ 2011-06-03 19:13 Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 01/11] Introduce laopts structure Zdenek Kabelac
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Patchset tries to optimize creation of VG structure from config_tree.
When the config_tree is unchange and we know VG structure is not modified
we could reuse this structure multiple times.
Patchset currently has few limitation and is not the optimal solution,
but it present relatively very small set of changes with good improvements.
Patchset tries to avoid modification of VG structure for read-only operations.
And then introducion pool locking - debugging uses mprotect to generate
segfault in the moment of memory write access.
Normal code currently uses simple CRC checksum - could be later disabled,
once we are sure there could be no write operation.
Few things are left for the future:
vg_mark_partial is in wrong layer currentl.
clvmd would greatly benefit from 'smarter' cache flushing - VG structure
could be the reused more extensively.
Patch is splited in way to allow easier review.
Zdenek Kabelac (11):
Introduce laopts structure
Add laopts
Replace ACTIVATE
Replace MERGING in activation
FIXME
FIXME - remove test for status flag
Remove ACTIVATE_EXCL appearance from the code
Code move vg_mark_partial up in stack
Pool locking code
Share VG multiple times
lv_postorder unlock and lock
lib/activate/activate.c | 114 ++++++++++++++++++++----------------
lib/activate/activate.h | 10 +++-
lib/activate/dev_manager.c | 120 +++++++++++++++++++++-----------------
lib/activate/dev_manager.h | 10 ++-
lib/cache/lvmcache.c | 73 +++++++++++++++++++++++-
lib/cache/lvmcache.h | 5 ++
lib/error/errseg.c | 1 +
lib/format_text/flags.c | 1 -
lib/format_text/import.c | 6 ++
lib/metadata/metadata-exported.h | 1 -
lib/metadata/metadata.c | 45 ++++++++++++--
lib/metadata/metadata.h | 1 -
lib/metadata/mirror.c | 4 +-
lib/metadata/segtype.h | 13 +++--
lib/metadata/vg.h | 2 +
lib/mirror/mirrored.c | 15 +++--
lib/replicator/replicator.c | 2 +
lib/snapshot/snapshot.c | 5 +-
lib/striped/striped.c | 1 +
lib/unknown/unknown.c | 1 +
lib/zero/zero.c | 1 +
libdm/libdevmapper.h | 7 ++
libdm/mm/pool-debug.c | 27 +++++++++
libdm/mm/pool-fast.c | 70 +++++++++++++++++++++-
libdm/mm/pool.c | 106 +++++++++++++++++++++++++++++++++-
make.tmpl.in | 2 +
26 files changed, 503 insertions(+), 140 deletions(-)
--
1.7.5.2
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/11] Introduce laopts structure
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 02/11] Add laopts Zdenek Kabelac
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
To avoid modification of 'read-only' volume group structure
add a new structure to pass local data around the code for LV
activation.
As origin_only is one such flag - replace this parameter with new
struct lv_activate_opts.
More parameters might eventually become part of lv_activate_opts.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/activate.c | 80 ++++++++++++++++++++++++----------------
lib/activate/activate.h | 8 +++-
lib/activate/dev_manager.c | 88 ++++++++++++++++++++++++-------------------
lib/activate/dev_manager.h | 10 +++--
4 files changed, 110 insertions(+), 76 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 1ec518d..47d27be 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -626,7 +626,7 @@ static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
return info.open_count;
}
-static int _lv_activate_lv(struct logical_volume *lv, unsigned origin_only)
+static int _lv_activate_lv(struct logical_volume *lv, struct lv_activate_opts *laopts)
{
int r;
struct dev_manager *dm;
@@ -634,14 +634,15 @@ static int _lv_activate_lv(struct logical_volume *lv, unsigned origin_only)
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
- if (!(r = dev_manager_activate(dm, lv, origin_only)))
+ if (!(r = dev_manager_activate(dm, lv, laopts)))
stack;
dev_manager_destroy(dm);
return r;
}
-static int _lv_preload(struct logical_volume *lv, unsigned origin_only, int *flush_required)
+static int _lv_preload(struct logical_volume *lv, struct lv_activate_opts *laopts,
+ int *flush_required)
{
int r;
struct dev_manager *dm;
@@ -649,7 +650,7 @@ static int _lv_preload(struct logical_volume *lv, unsigned origin_only, int *flu
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
- if (!(r = dev_manager_preload(dm, lv, origin_only, flush_required)))
+ if (!(r = dev_manager_preload(dm, lv, laopts, flush_required)))
stack;
dev_manager_destroy(dm);
@@ -671,7 +672,8 @@ static int _lv_deactivate(struct logical_volume *lv)
return r;
}
-static int _lv_suspend_lv(struct logical_volume *lv, unsigned origin_only, int lockfs, int flush_required)
+static int _lv_suspend_lv(struct logical_volume *lv, struct lv_activate_opts *laopts,
+ int lockfs, int flush_required)
{
int r;
struct dev_manager *dm;
@@ -679,7 +681,7 @@ static int _lv_suspend_lv(struct logical_volume *lv, unsigned origin_only, int l
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
return_0;
- if (!(r = dev_manager_suspend(dm, lv, origin_only, lockfs, flush_required)))
+ if (!(r = dev_manager_suspend(dm, lv, laopts, lockfs, flush_required)))
stack;
dev_manager_destroy(dm);
@@ -1078,7 +1080,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
}
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
- unsigned origin_only, int error_if_not_suspended)
+ struct lv_activate_opts *laopts, int error_if_not_suspended)
{
struct logical_volume *lv = NULL, *lv_pre = NULL;
struct lvinfo info;
@@ -1096,15 +1098,15 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/* Ignore origin_only unless LV is origin in both old and new metadata */
if (!lv_is_origin(lv) || !lv_is_origin(lv_pre))
- origin_only = 0;
+ laopts->origin_only = 0;
if (test_mode()) {
- _skip("Suspending %s%s.", lv->name, origin_only ? " origin without snapshots" : "");
+ _skip("Suspending %s%s.", lv->name, laopts->origin_only ? " origin without snapshots" : "");
r = 1;
goto out;
}
- if (!lv_info(cmd, lv, origin_only, &info, 0, 0))
+ if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
goto_out;
if (!info.exists || info.suspended) {
@@ -1123,23 +1125,23 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/* If VG was precommitted, preload devices for the LV */
if ((lv_pre->vg->status & PRECOMMITTED)) {
- if (!_lv_preload(lv_pre, origin_only, &flush_required)) {
+ if (!_lv_preload(lv_pre, laopts, &flush_required)) {
/* FIXME Revert preloading */
goto_out;
}
}
- if (!monitor_dev_for_events(cmd, lv, origin_only, 0))
+ if (!monitor_dev_for_events(cmd, lv, laopts->origin_only, 0))
/* FIXME Consider aborting here */
stack;
critical_section_inc(cmd);
- if (!origin_only &&
+ if (!laopts->origin_only &&
(lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
lockfs = 1;
- if (!_lv_suspend_lv(lv, origin_only, lockfs, flush_required)) {
+ if (!_lv_suspend_lv(lv, laopts, lockfs, flush_required)) {
critical_section_dec(cmd);
goto out;
}
@@ -1159,7 +1161,9 @@ out:
/* Returns success if the device is not active */
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only)
{
- return _lv_suspend(cmd, lvid_s, origin_only, 0);
+ struct lv_activate_opts laopts = { .origin_only = origin_only };
+
+ return _lv_suspend(cmd, lvid_s, &laopts, 0);
}
/* No longer used */
@@ -1181,8 +1185,7 @@ int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
* @error_if_not_active
*/
static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
- unsigned origin_only, unsigned exclusive,
- int error_if_not_active)
+ struct lv_activate_opts *laopts, int error_if_not_active)
{
struct logical_volume *lv;
struct lvinfo info;
@@ -1195,15 +1198,15 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
goto_out;
if (!lv_is_origin(lv))
- origin_only = 0;
+ laopts->origin_only = 0;
if (test_mode()) {
- _skip("Resuming %s%s.", lv->name, origin_only ? " without snapshots" : "");
+ _skip("Resuming %s%s.", lv->name, laopts->origin_only ? " without snapshots" : "");
r = 1;
goto out;
}
- if (!lv_info(cmd, lv, origin_only, &info, 0, 0))
+ if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
goto_out;
if (!info.exists || !info.suspended) {
@@ -1218,15 +1221,15 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
* non-clustered target should be used. This only happens
* if ACTIVATE_EXCL is set in lv->status.
*/
- if (exclusive)
+ if (laopts->exclusive)
lv->status |= ACTIVATE_EXCL;
- if (!_lv_activate_lv(lv, origin_only))
+ if (!_lv_activate_lv(lv, laopts))
goto_out;
critical_section_dec(cmd);
- if (!monitor_dev_for_events(cmd, lv, origin_only, 1))
+ if (!monitor_dev_for_events(cmd, lv, laopts->origin_only, 1))
stack;
r = 1;
@@ -1241,12 +1244,24 @@ out:
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
unsigned origin_only, unsigned exclusive)
{
- return _lv_resume(cmd, lvid_s, origin_only, exclusive, 0);
+ struct lv_activate_opts laopts = {
+ .origin_only = origin_only,
+ /*
+ * When targets are activated exclusively in a cluster, the
+ * non-clustered target should be used. This only happens
+ * if exclusive is set.
+ */
+ .exclusive = exclusive
+ };
+
+ return _lv_resume(cmd, lvid_s, &laopts, 0);
}
int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only)
{
- return _lv_resume(cmd, lvid_s, origin_only, 0, 1);
+ struct lv_activate_opts laopts = { .origin_only = origin_only, };
+
+ return _lv_resume(cmd, lvid_s, &laopts, 1);
}
static int _lv_has_open_snapshots(struct logical_volume *lv)
@@ -1361,7 +1376,7 @@ out:
}
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
- int exclusive, int filter)
+ struct lv_activate_opts *laopts, int filter)
{
struct logical_volume *lv;
struct lvinfo info;
@@ -1410,11 +1425,8 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
lv_calculate_readahead(lv, NULL);
- if (exclusive)
- lv->status |= ACTIVATE_EXCL;
-
critical_section_inc(cmd);
- if (!(r = _lv_activate_lv(lv, 0)))
+ if (!(r = _lv_activate_lv(lv, laopts)))
stack;
critical_section_dec(cmd);
@@ -1433,7 +1445,9 @@ out:
/* Activate LV */
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
- if (!_lv_activate(cmd, lvid_s, exclusive, 0))
+ struct lv_activate_opts laopts = { .exclusive = exclusive };
+
+ if (!_lv_activate(cmd, lvid_s, &laopts, 0))
return_0;
return 1;
@@ -1442,7 +1456,9 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
/* Activate LV only if it passes filter */
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
{
- if (!_lv_activate(cmd, lvid_s, exclusive, 1))
+ struct lv_activate_opts laopts = { .exclusive = exclusive };
+
+ if (!_lv_activate(cmd, lvid_s, &laopts, 1))
return_0;
return 1;
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index 145fefb..b136d59 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -30,6 +30,12 @@ struct lvinfo {
uint32_t read_ahead;
};
+struct lv_activate_opts {
+ int exclusive;
+ int origin_only;
+ int no_merging;
+};
+
/* target attribute flags */
#define MIRROR_LOG_CLUSTERED 0x00000001U
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 9f4b2da..b07030a 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -1037,7 +1037,7 @@ static int _add_partial_replicator_to_dtree(struct dev_manager *dm,
/*
* Add LV and any known dependencies
*/
-static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv, unsigned origin_only)
+static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv, int origin_only)
{
if (!origin_only && !_add_dev_to_dtree(dm, dtree, lv, NULL))
return_0;
@@ -1061,7 +1061,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
return 1;
}
-static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv, unsigned origin_only)
+static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv, int origin_only)
{
struct dm_tree *dtree;
struct dm_list *snh, *snht;
@@ -1291,41 +1291,46 @@ static int _add_target_to_dtree(struct dev_manager *dm,
}
static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- struct logical_volume *lv, const char *layer);
+ struct logical_volume *lv,
+ struct lv_activate_opts *laopts,
+ const char *layer);
/* Add all replicators' LVs */
static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
struct dm_tree *dtree,
- struct lv_segment *seg)
+ struct lv_segment *seg,
+ struct lv_activate_opts *laopts)
{
struct replicator_device *rdev;
struct replicator_site *rsite;
/* For inactive replicator add linear mapping */
if (!lv_is_active_replicator_dev(seg->lv)) {
- if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, NULL))
+ if (!_add_new_lv_to_dtree(dm, dtree, seg->lv->rdevice->lv, laopts, NULL))
return_0;
return 1;
}
/* Add rlog and replicator nodes */
if (!seg->replicator ||
- !first_seg(seg->replicator)->rlog_lv ||
+ !first_seg(seg->replicator)->rlog_lv ||
!_add_new_lv_to_dtree(dm, dtree,
- first_seg(seg->replicator)->rlog_lv, NULL) ||
- !_add_new_lv_to_dtree(dm, dtree, seg->replicator, NULL))
+ first_seg(seg->replicator)->rlog_lv,
+ laopts, NULL) ||
+ !_add_new_lv_to_dtree(dm, dtree, seg->replicator, laopts, NULL))
return_0;
/* Activation of one replicator_dev node activates all other nodes */
dm_list_iterate_items(rsite, &seg->replicator->rsites) {
dm_list_iterate_items(rdev, &rsite->rdevices) {
if (rdev->lv &&
- !_add_new_lv_to_dtree(dm, dtree, rdev->lv, NULL))
+ !_add_new_lv_to_dtree(dm, dtree, rdev->lv,
+ laopts, NULL))
return_0;
if (rdev->slog &&
- !_add_new_lv_to_dtree(dm, dtree,
- rdev->slog, NULL))
+ !_add_new_lv_to_dtree(dm, dtree, rdev->slog,
+ laopts, NULL))
return_0;
}
}
@@ -1340,7 +1345,7 @@ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
if (!rdev->replicator_dev->lv ||
!_add_new_lv_to_dtree(dm, dtree,
rdev->replicator_dev->lv,
- NULL))
+ laopts, NULL))
return_0;
}
}
@@ -1349,10 +1354,11 @@ static int _add_replicator_dev_target_to_dtree(struct dev_manager *dm,
}
static int _add_segment_to_dtree(struct dev_manager *dm,
- struct dm_tree *dtree,
- struct dm_tree_node *dnode,
- struct lv_segment *seg,
- const char *layer)
+ struct dm_tree *dtree,
+ struct dm_tree_node *dnode,
+ struct lv_segment *seg,
+ struct lv_activate_opts *laopts,
+ const char *layer)
{
uint32_t s;
struct dm_list *snh;
@@ -1379,35 +1385,35 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Add mirror log */
if (seg->log_lv &&
- !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, NULL))
+ !_add_new_lv_to_dtree(dm, dtree, seg->log_lv, laopts, NULL))
return_0;
if (seg_is_replicator_dev(seg)) {
- if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg))
+ if (!_add_replicator_dev_target_to_dtree(dm, dtree, seg, laopts))
return_0;
/* If this is a snapshot origin, add real LV */
/* If this is a snapshot origin + merging snapshot, add cow + real LV */
} else if (lv_is_origin(seg->lv) && !layer) {
if (lv_is_merging_origin(seg->lv)) {
if (!_add_new_lv_to_dtree(dm, dtree,
- find_merging_cow(seg->lv)->cow, "cow"))
+ find_merging_cow(seg->lv)->cow, laopts, "cow"))
return_0;
/*
* Must also add "real" LV for use when
* snapshot-merge target is added
*/
}
- if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real"))
+ if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "real"))
return_0;
} else if (lv_is_cow(seg->lv) && !layer) {
- if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "cow"))
+ if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "cow"))
return_0;
} else {
/* Add any LVs used by this segment */
for (s = 0; s < seg->area_count; s++)
if ((seg_type(seg, s) == AREA_LV) &&
(!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
- NULL)))
+ laopts, NULL)))
return_0;
}
@@ -1429,14 +1435,16 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
if (lv_is_origin(seg->lv) && !layer)
/* Add any snapshots of this LV */
dm_list_iterate(snh, &seg->lv->snapshot_segs)
- if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
+ if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
+ laopts, NULL))
return_0;
return 1;
}
static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
- struct logical_volume *lv, const char *layer)
+ struct logical_volume *lv, struct lv_activate_opts *laopts,
+ const char *layer)
{
struct lv_segment *seg;
struct lv_layer *lvlayer;
@@ -1507,7 +1515,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* Create table */
dm->pvmove_mirror_count = 0u;
dm_list_iterate_items(seg, &lv->segments) {
- if (!_add_segment_to_dtree(dm, dtree, dnode, seg, layer))
+ if (!_add_segment_to_dtree(dm, dtree, dnode, seg, laopts, layer))
return_0;
/* These aren't real segments in the LVM2 metadata */
if (lv_is_origin(lv) && !layer)
@@ -1645,14 +1653,14 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root, char *
}
static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
- unsigned origin_only, action_t action)
+ struct lv_activate_opts *laopts, action_t action)
{
struct dm_tree *dtree;
struct dm_tree_node *root;
char *dlid;
int r = 0;
- if (!(dtree = _create_partial_dtree(dm, lv, origin_only)))
+ if (!(dtree = _create_partial_dtree(dm, lv, laopts->origin_only)))
return_0;
if (!(root = dm_tree_find_node(dtree, 0, 0))) {
@@ -1663,14 +1671,14 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
/* Restore fs cookie */
dm_tree_set_cookie(root, fs_get_cookie());
- if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, origin_only ? "real" : NULL)))
+ if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, laopts->origin_only ? "real" : NULL)))
goto_out;
/* Only process nodes with uuid of "LVM-" plus VG id. */
switch(action) {
case CLEAN:
/* Deactivate any unused non-toplevel nodes */
- if (!_clean_tree(dm, root, origin_only ? dlid : NULL))
+ if (!_clean_tree(dm, root, laopts->origin_only ? dlid : NULL))
goto_out;
break;
case DEACTIVATE:
@@ -1693,7 +1701,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
case PRELOAD:
case ACTIVATE:
/* Add all required new devices to tree */
- if (!_add_new_lv_to_dtree(dm, dtree, lv, origin_only ? "real" : NULL))
+ if (!_add_new_lv_to_dtree(dm, dtree, lv, laopts, laopts->origin_only ? "real" : NULL))
goto_out;
/* Preload any devices required before any suspensions */
@@ -1732,23 +1740,24 @@ out_no_root:
}
/* origin_only may only be set if we are resuming (not activating) an origin LV */
-int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv, unsigned origin_only)
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv,
+ struct lv_activate_opts *laopts)
{
- if (!_tree_action(dm, lv, origin_only, ACTIVATE))
+ if (!_tree_action(dm, lv, laopts, ACTIVATE))
return_0;
- return _tree_action(dm, lv, origin_only, CLEAN);
+ return _tree_action(dm, lv, laopts, CLEAN);
}
/* origin_only may only be set if we are resuming (not activating) an origin LV */
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
- unsigned origin_only, int *flush_required)
+ struct lv_activate_opts *laopts, int *flush_required)
{
/* FIXME Update the pvmove implementation! */
if ((lv->status & PVMOVE) || (lv->status & LOCKED))
return 1;
- if (!_tree_action(dm, lv, origin_only, PRELOAD))
+ if (!_tree_action(dm, lv, laopts, PRELOAD))
return 0;
*flush_required = dm->flush_required;
@@ -1758,19 +1767,20 @@ int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
{
+ struct lv_activate_opts laopts = { 0 };
int r;
- r = _tree_action(dm, lv, 0, DEACTIVATE);
+ r = _tree_action(dm, lv, &laopts, DEACTIVATE);
return r;
}
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
- unsigned origin_only, int lockfs, int flush_required)
+ struct lv_activate_opts *laopts, int lockfs, int flush_required)
{
dm->flush_required = flush_required;
- return _tree_action(dm, lv, origin_only, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
+ return _tree_action(dm, lv, laopts, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
}
/*
diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h
index b0bb275..4d7a7ee 100644
--- a/lib/activate/dev_manager.h
+++ b/lib/activate/dev_manager.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -19,6 +19,7 @@
#include "metadata-exported.h"
struct logical_volume;
+struct lv_activate_opts;
struct volume_group;
struct cmd_context;
struct dev_manager;
@@ -51,10 +52,11 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
const struct logical_volume *lv, int wait,
percent_t *percent, uint32_t *event_nr);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
- unsigned origin_only, int lockfs, int flush_required);
-int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv, unsigned origin_only);
+ struct lv_activate_opts *laopts, int lockfs, int flush_required);
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv,
+ struct lv_activate_opts *laopts);
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
- unsigned origin_only, int *flush_required);
+ struct lv_activate_opts *laopts, int *flush_required);
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_transient(struct dev_manager *dm, struct logical_volume *lv) __attribute__((nonnull(1, 2)));
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/11] Add laopts
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 01/11] Introduce laopts structure Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 03/11] Replace ACTIVATE Zdenek Kabelac
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/activate.c | 24 ++++++++++++++----------
lib/activate/activate.h | 2 +-
lib/activate/dev_manager.c | 18 ++++++++++--------
lib/error/errseg.c | 1 +
lib/metadata/segtype.h | 13 ++++++++-----
lib/mirror/mirrored.c | 12 +++++++-----
lib/replicator/replicator.c | 2 ++
lib/snapshot/snapshot.c | 3 ++-
lib/striped/striped.c | 1 +
lib/unknown/unknown.c | 1 +
lib/zero/zero.c | 1 +
11 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 47d27be..49fa3e1 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -243,7 +243,7 @@ int lv_check_transient(struct logical_volume *lv)
return 1;
}
int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
- unsigned origin_only, int monitor)
+ struct lv_activate_opts *laopts, int monitor)
{
return 1;
}
@@ -943,7 +943,7 @@ int target_register_events(struct cmd_context *cmd, const char *dso, struct logi
* Returns 1 otherwise.
*/
int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
- unsigned origin_only, int monitor)
+ const struct lv_activate_opts *laopts, int monitor)
{
#ifdef DMEVENTD
int i, pending = 0, monitored;
@@ -953,6 +953,10 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_segment *log_seg;
int (*monitor_fn) (struct lv_segment *s, int e);
uint32_t s;
+ static const struct lv_activate_opts zlaopts = { 0 };
+
+ if (!laopts)
+ laopts = &zlaopts;
/* skip dmeventd code altogether */
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
@@ -976,10 +980,10 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
* each of its respective snapshots. The origin itself may
* also need to be monitored if it is a mirror, for example.
*/
- if (!origin_only && lv_is_origin(lv))
+ if (!laopts->origin_only && lv_is_origin(lv))
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
if (!monitor_dev_for_events(cmd, dm_list_struct_base(snh,
- struct lv_segment, origin_list)->cow, 0, monitor))
+ struct lv_segment, origin_list)->cow, NULL, monitor))
r = 0;
/*
@@ -989,7 +993,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
if ((seg = first_seg(lv)) != NULL && seg->log_lv != NULL &&
(log_seg = first_seg(seg->log_lv)) != NULL &&
seg_is_mirrored(log_seg))
- if (!monitor_dev_for_events(cmd, seg->log_lv, 0, monitor))
+ if (!monitor_dev_for_events(cmd, seg->log_lv, NULL, monitor))
r = 0;
dm_list_iterate(tmp, &lv->segments) {
@@ -999,7 +1003,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) != AREA_LV)
continue;
- if (!monitor_dev_for_events(cmd, seg_lv(seg, s), 0,
+ if (!monitor_dev_for_events(cmd, seg_lv(seg, s), NULL,
monitor)) {
log_error("Failed to %smonitor %s",
monitor ? "" : "un",
@@ -1131,7 +1135,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
}
- if (!monitor_dev_for_events(cmd, lv, laopts->origin_only, 0))
+ if (!monitor_dev_for_events(cmd, lv, laopts, 0))
/* FIXME Consider aborting here */
stack;
@@ -1229,7 +1233,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
critical_section_dec(cmd);
- if (!monitor_dev_for_events(cmd, lv, laopts->origin_only, 1))
+ if (!monitor_dev_for_events(cmd, lv, laopts, 1))
stack;
r = 1;
@@ -1328,7 +1332,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
lv_calculate_readahead(lv, NULL);
- if (!monitor_dev_for_events(cmd, lv, 0, 0))
+ if (!monitor_dev_for_events(cmd, lv, NULL, 0))
stack;
critical_section_inc(cmd);
@@ -1430,7 +1434,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
stack;
critical_section_dec(cmd);
- if (r && !monitor_dev_for_events(cmd, lv, 0, 1))
+ if (r && !monitor_dev_for_events(cmd, lv, laopts, 1))
stack;
out:
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index b136d59..022b797 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -108,7 +108,7 @@ int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv,
const char *layer, const char *target_type);
int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
- unsigned origin_only, int do_reg);
+ const struct lv_activate_opts *laopts, int do_reg);
#ifdef DMEVENTD
# include "libdevmapper-event.h"
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index b07030a..fe5e1da 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1238,8 +1238,9 @@ static int _add_snapshot_merge_target_to_dtree(struct dev_manager *dm,
}
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
- struct dm_tree_node *dnode,
- struct logical_volume *lv)
+ struct dm_tree_node *dnode,
+ struct logical_volume *lv,
+ struct lv_activate_opts *laopts)
{
const char *origin_dlid;
const char *cow_dlid;
@@ -1272,8 +1273,9 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
}
static int _add_target_to_dtree(struct dev_manager *dm,
- struct dm_tree_node *dnode,
- struct lv_segment *seg)
+ struct dm_tree_node *dnode,
+ struct lv_segment *seg,
+ struct lv_activate_opts *laopts)
{
uint64_t extent_size = seg->lv->vg->extent_size;
@@ -1285,7 +1287,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
return seg->segtype->ops->add_target_line(dm, dm->mem, dm->cmd,
&dm->target_state, seg,
- dnode,
+ laopts, dnode,
extent_size * seg->len,
&dm-> pvmove_mirror_count);
}
@@ -1368,7 +1370,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Ensure required device-mapper targets are loaded */
seg_present = find_cow(seg->lv) ? : seg;
target_name = (seg_present->segtype->ops->target_name ?
- seg_present->segtype->ops->target_name(seg_present) :
+ seg_present->segtype->ops->target_name(seg_present, laopts) :
seg_present->segtype->name);
log_debug("Checking kernel supports %s segment type for %s%s%s",
@@ -1427,9 +1429,9 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
return_0;
}
} else if (lv_is_cow(seg->lv) && !layer) {
- if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
+ if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv, laopts))
return_0;
- } else if (!_add_target_to_dtree(dm, dnode, seg))
+ } else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
return_0;
if (lv_is_origin(seg->lv) && !layer)
diff --git a/lib/error/errseg.c b/lib/error/errseg.c
index 41e451b..a2fbc4d 100644
--- a/lib/error/errseg.c
+++ b/lib/error/errseg.c
@@ -45,6 +45,7 @@ static int _errseg_add_target_line(struct dev_manager *dm __attribute__((unused)
struct cmd_context *cmd __attribute__((unused)),
void **target_state __attribute__((unused)),
struct lv_segment *seg __attribute__((unused)),
+ const struct lv_activate_opts *laopts __attribute__((unused)),
struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 6d50746..a914aac 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -22,6 +22,7 @@ struct segtype_handler;
struct cmd_context;
struct config_tree;
struct lv_segment;
+struct lv_activate_opts;
struct formatter;
struct config_node;
struct dev_manager;
@@ -66,7 +67,8 @@ struct segment_type {
struct segtype_handler {
const char *(*name) (const struct lv_segment * seg);
- const char *(*target_name) (const struct lv_segment * seg);
+ const char *(*target_name) (const struct lv_segment *seg,
+ const struct lv_activate_opts *laopts);
void (*display) (const struct lv_segment * seg);
int (*text_export) (const struct lv_segment * seg,
struct formatter * f);
@@ -78,10 +80,11 @@ struct segtype_handler {
int (*merge_segments) (struct lv_segment * seg1,
struct lv_segment * seg2);
int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
- struct cmd_context *cmd, void **target_state,
- struct lv_segment *seg,
- struct dm_tree_node *node, uint64_t len,
- uint32_t *pvmove_mirror_count);
+ struct cmd_context *cmd, void **target_state,
+ struct lv_segment *seg,
+ const struct lv_activate_opts *laopts,
+ struct dm_tree_node *node, uint64_t len,
+ uint32_t *pvmove_mirror_count);
int (*target_status_compatible) (const char *type);
int (*check_transient_status) (struct lv_segment *seg, char *params);
int (*target_percent) (void **target_state,
diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
index 4c74a44..50e79c3 100644
--- a/lib/mirror/mirrored.c
+++ b/lib/mirror/mirrored.c
@@ -349,6 +349,7 @@ static int _mirrored_transient_status(struct lv_segment *seg, char *params)
}
static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
+ const struct lv_activate_opts *laopts,
struct dm_tree_node *node, uint32_t area_count, uint32_t region_size)
{
unsigned clustered = 0;
@@ -390,10 +391,11 @@ static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
}
static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
- struct cmd_context *cmd, void **target_state,
- struct lv_segment *seg,
- struct dm_tree_node *node, uint64_t len,
- uint32_t *pvmove_mirror_count)
+ struct cmd_context *cmd, void **target_state,
+ struct lv_segment *seg,
+ const struct lv_activate_opts *laopts,
+ struct dm_tree_node *node, uint64_t len,
+ uint32_t *pvmove_mirror_count)
{
struct mirror_state *mirr_state;
uint32_t area_count = seg->area_count;
@@ -451,7 +453,7 @@ static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem
if (!dm_tree_node_add_mirror_target(node, len))
return_0;
- if ((r = _add_log(mem, seg, node, area_count, region_size)) <= 0) {
+ if ((r = _add_log(mem, seg, laopts, node, area_count, region_size)) <= 0) {
stack;
return r;
}
diff --git a/lib/replicator/replicator.c b/lib/replicator/replicator.c
index 2be49c2..9bfc0a2 100644
--- a/lib/replicator/replicator.c
+++ b/lib/replicator/replicator.c
@@ -327,6 +327,7 @@ static int _replicator_add_target_line(struct dev_manager *dm,
struct cmd_context *cmd,
void **target_state,
struct lv_segment *seg,
+ const struct lv_activate_opts *laopts,
struct dm_tree_node *node,
uint64_t len,
uint32_t *pvmove_mirror_count)
@@ -609,6 +610,7 @@ static int _replicator_dev_add_target_line(struct dev_manager *dm,
struct cmd_context *cmd,
void **target_state,
struct lv_segment *seg,
+ const struct lv_activate_opts *laopts,
struct dm_tree_node *node,
uint64_t len,
uint32_t *pvmove_mirror_count)
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
index a2851b4..3555f36 100644
--- a/lib/snapshot/snapshot.c
+++ b/lib/snapshot/snapshot.c
@@ -28,7 +28,8 @@ static const char *_snap_name(const struct lv_segment *seg)
return seg->segtype->name;
}
-static const char *_snap_target_name(const struct lv_segment *seg)
+static const char *_snap_target_name(const struct lv_segment *seg,
+ const struct lv_activate_opts *laopts)
{
if (seg->status & MERGING)
return "snapshot-merge";
diff --git a/lib/striped/striped.c b/lib/striped/striped.c
index 4de4a18..6fa49e3 100644
--- a/lib/striped/striped.c
+++ b/lib/striped/striped.c
@@ -164,6 +164,7 @@ static int _striped_add_target_line(struct dev_manager *dm,
struct cmd_context *cmd __attribute__((unused)),
void **target_state __attribute__((unused)),
struct lv_segment *seg,
+ const struct lv_activate_opts *laopts __attribute__((unused)),
struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
diff --git a/lib/unknown/unknown.c b/lib/unknown/unknown.c
index b218371..2fbd11c 100644
--- a/lib/unknown/unknown.c
+++ b/lib/unknown/unknown.c
@@ -67,6 +67,7 @@ static int _unknown_add_target_line(struct dev_manager *dm __attribute__((unused
struct cmd_context *cmd __attribute__((unused)),
void **target_state __attribute__((unused)),
struct lv_segment *seg __attribute__((unused)),
+ const struct lv_activate_opts *laopts __attribute__((unused)),
struct dm_tree_node *node, uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
diff --git a/lib/zero/zero.c b/lib/zero/zero.c
index 471bc11..9611e9b 100644
--- a/lib/zero/zero.c
+++ b/lib/zero/zero.c
@@ -44,6 +44,7 @@ static int _zero_add_target_line(struct dev_manager *dm __attribute__((unused)),
struct cmd_context *cmd __attribute__((unused)),
void **target_state __attribute__((unused)),
struct lv_segment *seg __attribute__((unused)),
+ const struct lv_activate_opts *laopts __attribute__((unused)),
struct dm_tree_node *node,uint64_t len,
uint32_t *pvmove_mirror_count __attribute__((unused)))
{
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/11] Replace ACTIVATE
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 01/11] Introduce laopts structure Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 02/11] Add laopts Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 04/11] Replace MERGING in activation Zdenek Kabelac
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/mirror/mirrored.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
index 50e79c3..49b39e7 100644
--- a/lib/mirror/mirrored.c
+++ b/lib/mirror/mirrored.c
@@ -360,8 +360,7 @@ static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
* Use clustered mirror log for non-exclusive activation
* in clustered VG.
*/
- if ((!(seg->lv->status & ACTIVATE_EXCL) &&
- (vg_is_clustered(seg->lv->vg))))
+ if (!laopts->exclusive && vg_is_clustered(seg->lv->vg))
clustered = 1;
if (seg->log_lv) {
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/11] Replace MERGING in activation
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (2 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 03/11] Replace ACTIVATE Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 05/11] FIXME Zdenek Kabelac
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Careful review is needed here.
Our test-suite passed correctly - but I might have missed some
code path - code is a bit tricky.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/activate.c | 4 ++--
lib/activate/dev_manager.c | 14 +++++++-------
lib/snapshot/snapshot.c | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 49fa3e1..4fd9c6a 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -972,8 +972,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
* In case of a snapshot device, we monitor lv->snapshot->lv,
* not the actual LV itself.
*/
- if (lv_is_cow(lv) && !lv_is_merging_cow(lv))
- return monitor_dev_for_events(cmd, lv->snapshot->lv, 0, monitor);
+ if (lv_is_cow(lv) && (laopts->no_merging || !lv_is_merging_cow(lv)))
+ return monitor_dev_for_events(cmd, lv->snapshot->lv, NULL, monitor);
/*
* In case this LV is a snapshot origin, we instead monitor
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index fe5e1da..53c8ac3 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1260,7 +1260,7 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
size = (uint64_t) snap_seg->len * snap_seg->origin->vg->extent_size;
- if (lv_is_merging_cow(lv)) {
+ if (!laopts->no_merging && lv_is_merging_cow(lv)) {
/* cow is to be merged so load the error target */
if (!dm_tree_node_add_error_target(dnode, size))
return_0;
@@ -1396,7 +1396,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* If this is a snapshot origin, add real LV */
/* If this is a snapshot origin + merging snapshot, add cow + real LV */
} else if (lv_is_origin(seg->lv) && !layer) {
- if (lv_is_merging_origin(seg->lv)) {
+ if (!laopts->no_merging && lv_is_merging_origin(seg->lv)) {
if (!_add_new_lv_to_dtree(dm, dtree,
find_merging_cow(seg->lv)->cow, laopts, "cow"))
return_0;
@@ -1407,7 +1407,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
}
if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "real"))
return_0;
- } else if (lv_is_cow(seg->lv) && !layer) {
+ } else if (!laopts->no_merging && lv_is_cow(seg->lv) && !layer) {
if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, laopts, "cow"))
return_0;
} else {
@@ -1421,14 +1421,14 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Now we've added its dependencies, we can add the target itself */
if (lv_is_origin(seg->lv) && !layer) {
- if (!lv_is_merging_origin(seg->lv)) {
+ if (laopts->no_merging || !lv_is_merging_origin(seg->lv)) {
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
return_0;
} else {
if (!_add_snapshot_merge_target_to_dtree(dm, dnode, seg->lv))
return_0;
}
- } else if (lv_is_cow(seg->lv) && !layer) {
+ } else if (!laopts->no_merging && lv_is_cow(seg->lv) && !layer) {
if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv, laopts))
return_0;
} else if (!_add_target_to_dtree(dm, dnode, seg, laopts))
@@ -1473,7 +1473,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
dtree)) && dinfo->open_count)) {
/* FIXME Is there anything simpler to check for instead? */
if (!lv_has_target_type(dm->mem, lv, NULL, "snapshot-merge"))
- clear_snapshot_merge(lv);
+ laopts->no_merging = 1;
}
}
@@ -1522,7 +1522,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
/* These aren't real segments in the LVM2 metadata */
if (lv_is_origin(lv) && !layer)
break;
- if (lv_is_cow(lv) && !layer)
+ if (!laopts->no_merging && lv_is_cow(lv) && !layer)
break;
if (max_stripe_size < seg->stripe_size * seg->area_count)
max_stripe_size = seg->stripe_size * seg->area_count;
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c
index 3555f36..8c48308 100644
--- a/lib/snapshot/snapshot.c
+++ b/lib/snapshot/snapshot.c
@@ -31,7 +31,7 @@ static const char *_snap_name(const struct lv_segment *seg)
static const char *_snap_target_name(const struct lv_segment *seg,
const struct lv_activate_opts *laopts)
{
- if (seg->status & MERGING)
+ if (!laopts->no_merging && (seg->status & MERGING))
return "snapshot-merge";
return _snap_name(seg);
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/11] FIXME
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (3 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 04/11] Replace MERGING in activation Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 06/11] FIXME - remove test for status flag Zdenek Kabelac
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/activate.c | 4 +++-
lib/metadata/mirror.c | 1 +
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 4fd9c6a..58f623e 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -783,12 +783,14 @@ static int _lv_is_active(struct logical_volume *lv,
goto out;
}
+ /* FIXME: Is this fallback alright? */
if (activate_lv_excl(lv->vg->cmd, lv)) {
if (!deactivate_lv(lv->vg->cmd, lv))
stack;
+ /* FIXME: locally & exclusive are undefined. */
return 0;
}
-
+ /* FIXME: Check exclusive value here. */
out:
if (locally)
*locally = l;
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index b02c7bb..21a10bf 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -2004,6 +2004,7 @@ int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
}
if (vg_is_clustered(lv->vg)) {
+ /* FIXME: review check of lv_is_active_remotely */
if (!(lv->status & ACTIVATE_EXCL) &&
!cluster_mirror_is_available(lv)) {
log_error("Shared cluster mirrors are not available.");
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/11] FIXME - remove test for status flag
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (4 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 05/11] FIXME Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 07/11] Remove ACTIVATE_EXCL appearance from the code Zdenek Kabelac
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
As the ACTIVATE_EXCL could be set only in clvmd code - there is no
use for this test in lv_add_mirrors() function only called from
tools context.
FIXME: Add cluster test case for this.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/mirror.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index 21a10bf..4e9f254 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -2005,8 +2005,7 @@ int lv_add_mirrors(struct cmd_context *cmd, struct logical_volume *lv,
if (vg_is_clustered(lv->vg)) {
/* FIXME: review check of lv_is_active_remotely */
- if (!(lv->status & ACTIVATE_EXCL) &&
- !cluster_mirror_is_available(lv)) {
+ if (!cluster_mirror_is_available(lv)) {
log_error("Shared cluster mirrors are not available.");
return 0;
}
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/11] Remove ACTIVATE_EXCL appearance from the code
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (5 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 06/11] FIXME - remove test for status flag Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 08/11] Code move vg_mark_partial up in stack Zdenek Kabelac
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/activate/activate.c | 8 --------
lib/format_text/flags.c | 1 -
lib/metadata/metadata-exported.h | 1 -
lib/metadata/metadata.h | 1 -
4 files changed, 0 insertions(+), 11 deletions(-)
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 58f623e..327cfa3 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -1222,14 +1222,6 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
- /*
- * When targets are activated exclusively in a cluster, the
- * non-clustered target should be used. This only happens
- * if ACTIVATE_EXCL is set in lv->status.
- */
- if (laopts->exclusive)
- lv->status |= ACTIVATE_EXCL;
-
if (!_lv_activate_lv(lv, laopts))
goto_out;
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 0af4c89..7846ada 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -62,7 +62,6 @@ static const struct flag _lv_flags[] = {
{VIRTUAL, NULL, 0},
{SNAPSHOT, NULL, 0},
{MERGING, NULL, 0},
- {ACTIVATE_EXCL, NULL, 0},
{CONVERTING, NULL, 0},
{PARTIAL_LV, NULL, 0},
{POSTORDER_FLAG, NULL, 0},
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 950a81d..cad1719 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -62,7 +62,6 @@
#define MIRROR_LOG 0x00020000U /* LV */
#define MIRROR_IMAGE 0x00040000U /* LV */
#define LV_NOTSYNCED 0x00080000U /* LV */
-//#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */
//#define PRECOMMITTED 0x00200000U /* VG - internal use only */
#define CONVERTING 0x00400000U /* LV */
diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h
index c348979..8a3ff1a 100644
--- a/lib/metadata/metadata.h
+++ b/lib/metadata/metadata.h
@@ -71,7 +71,6 @@
//#define MIRROR_LOG 0x00020000U /* LV */
//#define MIRROR_IMAGE 0x00040000U /* LV */
//#define MIRROR_NOTSYNCED 0x00080000U /* LV */
-#define ACTIVATE_EXCL 0x00100000U /* LV - internal use only */
#define PRECOMMITTED 0x00200000U /* VG - internal use only */
//#define CONVERTING 0x00400000U /* LV */
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/11] Code move vg_mark_partial up in stack
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (6 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 07/11] Remove ACTIVATE_EXCL appearance from the code Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 09/11] Pool locking code Zdenek Kabelac
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
It's useful to keep the partial flag cached - so just move the call
for vg_mark_partil_lvs() into import_vg_from_config_tree().
This patch should not present any functional change.
Note: It is rather temporal solution - proper place is inside the
'read' call back - but needs some more discussion.
For now using this minor hack.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/format_text/import.c | 6 ++++++
lib/metadata/metadata.c | 5 -----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/format_text/import.c b/lib/format_text/import.c
index aa8c807..83e781b 100644
--- a/lib/format_text/import.c
+++ b/lib/format_text/import.c
@@ -136,6 +136,7 @@ struct volume_group *import_vg_from_config_tree(const struct config_tree *cft,
{
struct volume_group *vg = NULL;
struct text_vg_version_ops **vsn;
+ int vg_missing;
_init_text_import();
@@ -148,6 +149,11 @@ struct volume_group *import_vg_from_config_tree(const struct config_tree *cft,
*/
if (!(vg = (*vsn)->read_vg(fid, cft, 1)))
stack;
+ else if ((vg_missing = vg_missing_pv_count(vg))) {
+ log_verbose("There are %d physical volumes missing.",
+ vg_missing);
+ vg_mark_partial_lvs(vg, 1);
+ }
break;
}
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index dc00579..9e235a1 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2867,11 +2867,6 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
else /* Inconsistent but we can't repair it */
correct_vg->status &= ~INCONSISTENT_VG;
- if (vg_missing_pv_count(correct_vg)) {
- log_verbose("There are %d physical volumes missing.",
- vg_missing_pv_count(correct_vg));
- vg_mark_partial_lvs(correct_vg, 1);
- }
return correct_vg;
} else {
free_vg(correct_vg);
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/11] Pool locking code
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (7 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 08/11] Code move vg_mark_partial up in stack Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 10/11] Share VG multiple times Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 11/11] lv_postorder unlock and lock Zdenek Kabelac
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Adding specific functions to lock and unlock memory pool.
To avoid some more rewrites in case this API would still require some
changes - only pool-fast is currently fully updated for this API.
2 ways to debug code:
mprotect - quite fast all the time - but requires more memory and
currently it is using posix_memalign - this would be
later modified to use dm_malloc() and align internally.
Tool segfault when locked memory is modified.
crc - checksum of locked pool - implemented via quick simple hash.
But even this gets quite slow when the pool it larger -
so the check is only made only VG is finaly released and
it has been used more then once.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
libdm/libdevmapper.h | 7 +++
libdm/mm/pool-debug.c | 27 ++++++++++++
libdm/mm/pool-fast.c | 70 +++++++++++++++++++++++++++++++-
libdm/mm/pool.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++-
make.tmpl.in | 2 +
5 files changed, 209 insertions(+), 3 deletions(-)
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 88bddb1..2915860 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -594,6 +594,13 @@ void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment);
void dm_pool_empty(struct dm_pool *p);
void dm_pool_free(struct dm_pool *p, void *ptr);
+/* pool locking routines */
+int dm_pool_locked(struct dm_pool *p);
+int dm_pool_lock(struct dm_pool *p, int crc)
+ __attribute__((__warn_unused_result__));
+int dm_pool_unlock(struct dm_pool *p, int crc)
+ __attribute__((__warn_unused_result__));
+
/*
* Object building routines:
*
diff --git a/libdm/mm/pool-debug.c b/libdm/mm/pool-debug.c
index af1a912..d8c19d4 100644
--- a/libdm/mm/pool-debug.c
+++ b/libdm/mm/pool-debug.c
@@ -33,6 +33,8 @@ struct dm_pool {
struct dm_list list;
const char *name;
void *orig_pool; /* to pair it with first allocation call */
+ unsigned locked;
+ long crc;
int begun;
struct block *object;
@@ -71,6 +73,8 @@ static void _free_blocks(struct dm_pool *p, struct block *b)
{
struct block *n;
+ assert(!p->locked);
+
while (b) {
p->stats.bytes -= b->size;
p->stats.blocks_allocated--;
@@ -84,6 +88,8 @@ static void _free_blocks(struct dm_pool *p, struct block *b)
static void _pool_stats(struct dm_pool *p, const char *action)
{
+ assert(!p->locked);
+
#ifdef DEBUG_POOL
log_debug("%s mempool %s: %u/%u bytes, %u/%u blocks, "
"%u allocations)", action, p->name, p->stats.bytes,
@@ -99,6 +105,7 @@ void dm_pool_destroy(struct dm_pool *p)
_pool_stats(p, "Destroying");
_free_blocks(p, p->blocks);
dm_list_del(&p->list);
+ dm_free(p->volatile_mem);
dm_free(p);
}
@@ -109,6 +116,8 @@ void *dm_pool_alloc(struct dm_pool *p, size_t s)
static void _append_block(struct dm_pool *p, struct block *b)
{
+ assert(!p->locked);
+
if (p->tail) {
p->tail->next = b;
p->tail = b;
@@ -216,6 +225,8 @@ int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
struct block *new;
size_t new_size;
+ assert(!p->locked);
+
if (!delta)
delta = strlen(extra);
@@ -260,3 +271,19 @@ void dm_pool_abandon_object(struct dm_pool *p)
p->begun = 0;
p->object = NULL;
}
+
+static long _pool_crc(const struct dm_pool *p)
+{
+#ifndef DEBUG_USE_MPROTECT
+#warning pool crc not implemented with pool debug
+#endif
+ return 0;
+}
+
+static int _pool_protect(struct dm_pool *p, int prot)
+{
+#ifdef DEBUG_USE_MPROTECT
+#warning pool mprotect not implemented with pool debug
+#endif
+ return 1;
+}
diff --git a/libdm/mm/pool-fast.c b/libdm/mm/pool-fast.c
index 29d61a4..75d7f24 100644
--- a/libdm/mm/pool-fast.c
+++ b/libdm/mm/pool-fast.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -18,6 +18,7 @@
#endif
#include "dmlib.h"
+#include <malloc.h>
struct chunk {
char *begin, *end;
@@ -32,6 +33,8 @@ struct dm_pool {
size_t chunk_size;
size_t object_len;
unsigned object_alignment;
+ int locked;
+ long crc;
};
static void _align_chunk(struct chunk *c, unsigned alignment);
@@ -254,17 +257,36 @@ static struct chunk *_new_chunk(struct dm_pool *p, size_t s)
{
struct chunk *c;
+#ifdef DEBUG_USE_MPROTECT
+ if (!pagesize) {
+ pagesize = getpagesize(); // lvm_pagesize();
+ pagesize_mask = pagesize - 1;
+ }
+#endif
if (p->spare_chunk &&
((p->spare_chunk->end - p->spare_chunk->begin) >= s)) {
/* reuse old chunk */
c = p->spare_chunk;
p->spare_chunk = 0;
} else {
- if (!(c = dm_malloc(s))) {
+#ifdef DEBUG_USE_MPROTECT
+ /*
+ * Allocate page aligned size so malloc could work.
+ * Otherwise page fault would happen from pool unrelated
+ * memory writes of internal malloc pointers.
+ */
+#define aligned_malloc(s) (posix_memalign((void**)&c, pagesize, \
+ ALIGN_ON_PAGE(s)) == 0)
+#else
+#define aligned_malloc(s) (c = dm_malloc(s))
+#endif
+ if (!aligned_malloc(s)) {
+#undef aligned_malloc
log_error("Out of memory. Requested %" PRIsize_t
" bytes.", s);
return NULL;
}
+ //log_debug("RESET %p %p %d a:%d", c, c + s, (int)s, (int)ALIGN_ON_PAGE(s));
c->begin = (char *) (c + 1);
c->end = (char *) c + s;
@@ -283,3 +305,47 @@ static void _free_chunk(struct chunk *c)
{
dm_free(c);
}
+
+
+/**
+ * Calc crc/hash from pools' memory chunks with internal pointers
+ */
+static long _pool_crc(const struct dm_pool *p)
+{
+ long crc_hash = 0;
+#ifndef DEBUG_USE_MPROTECT
+ const struct chunk *c;
+ const long *ptr, *end;
+
+ for (c = p->chunk; c; c = c->prev) {
+ end = (const long *) (c->begin < c->end ? (long) c->begin & ~7: (long) c->end);
+ ptr = (const long *) c;
+#ifdef VALGRIND_POOL
+ VALGRIND_MAKE_MEM_DEFINED(ptr, (end - ptr) * sizeof(*end));
+#endif
+ while (ptr < end) {
+ crc_hash += *ptr++;
+ crc_hash += (crc_hash << 10);
+ crc_hash ^= (crc_hash >> 6);
+ }
+ }
+#endif
+
+ return crc_hash;
+}
+
+static int _pool_protect(struct dm_pool *p, int prot)
+{
+#ifdef DEBUG_USE_MPROTECT
+ struct chunk *c;
+
+ for (c = p->chunk; c; c = c->prev) {
+ //log_debug("protecting %d %p 0x%x", prot, c, (int) ((char*)c->end - (char*)c) - 1);
+ if (mprotect(c, (size_t) ((c->end - (char *) c) - 1), prot) != 0) {
+ log_sys_error("mprotect", "");
+ return 0;
+ }
+ }
+#endif
+ return 1;
+}
diff --git a/libdm/mm/pool.c b/libdm/mm/pool.c
index 3df6071..48740bc 100644
--- a/libdm/mm/pool.c
+++ b/libdm/mm/pool.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -14,11 +14,30 @@
*/
#include "dmlib.h"
+#include <sys/mman.h>
/* FIXME: thread unsafe */
static DM_LIST_INIT(_dm_pools);
void dm_pools_check_leaks(void);
+#ifdef DEBUG_USE_MPROTECT
+/*
+ * Use mprotect system call to ensure all locked pages are not writeable
+ * Generates segmentation fault with write access to the locked pool.
+ *
+ * - Implementation is using posix_memalign() to get page aligned
+ * memory blocks (could be implemented also through malloc).
+ * - Only pool-fast is properly handled for now.
+ * - As all pools could be locked now - using this aligned malloc for
+ * each pool - this is not memory efficient.
+ * - Checksum is quite slow compared to mprotect.
+ */
+
+static size_t pagesize = 0;
+static size_t pagesize_mask = 0;
+#define ALIGN_ON_PAGE(size) (((size) + (pagesize_mask)) & ~(pagesize_mask))
+#endif
+
#ifdef DEBUG_POOL
#include "pool-debug.c"
#else
@@ -76,3 +95,88 @@ void dm_pools_check_leaks(void)
}
log_error(INTERNAL_ERROR "Unreleased memory pool(s) found.");
}
+
+/**
+ * Status of locked pool.
+ *
+ * \param p
+ * Pool to be tested for lock status.
+ *
+ * \return
+ * 1 when the pool is locked, 0 otherwise.
+ */
+int dm_pool_locked(struct dm_pool *p)
+{
+ return p->locked;
+}
+
+/**
+ * Lock memory pool.
+ *
+ * \param p
+ * Pool to be locked.
+ *
+ * \param crc
+ * Specifies whether to save crc/hash checksum.
+ *
+ * \return
+ * 1 (success) when the pool was preperly locked, 0 otherwise.
+ */
+int dm_pool_lock(struct dm_pool *p, int crc)
+{
+ if (p->locked) {
+ log_error(INTERNAL_ERROR "Pool %s is already locked.",
+ p->name);
+ return 0;
+ }
+
+ if (crc)
+ p->crc = _pool_crc(p); /* Get crc for pool */
+
+ if (!_pool_protect(p, PROT_READ)) {
+ _pool_protect(p, PROT_READ | PROT_WRITE);
+ return_0;
+ }
+
+ p->locked = 1;
+
+ log_debug("Pool %s locked.", p->name);
+
+ return 1;
+}
+
+/**
+ * Unlock memory pool.
+ *
+ * \param p
+ * Pool to be unlocked.
+ *
+ * \param crc
+ * Compare crc/hash with saved value. If there is mismatch,
+ * pool is not properly unlocked.
+ *
+ * \return
+ * 1 (success) when the pool was properly unlocked, 0 otherwise.
+ */
+int dm_pool_unlock(struct dm_pool *p, int crc)
+{
+ if (!p->locked) {
+ log_error(INTERNAL_ERROR "Pool %s is already unlocked.",
+ p->name);
+ return 0;
+ }
+
+ p->locked = 0;
+
+ if (!_pool_protect(p, PROT_READ | PROT_WRITE))
+ return_0;
+
+ log_debug("Pool %s is unlocked.", p->name);
+
+ if (crc && (p->crc != _pool_crc(p))) {
+ log_error(INTERNAL_ERROR "Pool %s crc mismatch.", p->name);
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/make.tmpl.in b/make.tmpl.in
index cd8ae35..d52f7ca 100644
--- a/make.tmpl.in
+++ b/make.tmpl.in
@@ -149,6 +149,8 @@ ifeq ("@DM_IOCTLS@", "yes")
endif
#DEFS += -DDEBUG_POOL
+# do not use DEBUG_POOL and DEBUG_USE_MPROTECT at the same time
+#DEFS += -DDEBUG_USE_MPROTECT
#DEFS += -DBOUNDS_CHECK
#CFLAGS += -pg
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/11] Share VG multiple times
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (8 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 09/11] Pool locking code Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 11/11] lv_postorder unlock and lock Zdenek Kabelac
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Saves CPU by skipping creation of the same volume_group structure.
Structure vginfo is extended vg_cache and counters.
It tracks the number of reuses of every cached VG.
For lv_suspend we occasionaly need to reference the same VG more then
once - it's the reason for reference counter.
Caching is not used when VG is opened RW recover mode.
As there is far more case when sharing is possible - use rather specific
code to drop VG from lvmcache in this case - such VG is then unlocked.
and it is fully modifiable.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/cache/lvmcache.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++-
lib/cache/lvmcache.h | 5 +++
lib/metadata/metadata.c | 24 ++++++++++++++-
lib/metadata/vg.h | 2 +
4 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 0e92fa3..b19d963 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -89,6 +89,11 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
vginfo->cft = NULL;
}
+ free_vg(vginfo->vg_cache);
+ if (!lvmcache_release_vg(vginfo->vg_cache) &&
+ vginfo->vg_ref_count > 1)
+ log_error(INTERNAL_ERROR "Cache releases referenced multi VGs.");
+
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
}
@@ -662,6 +667,17 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
(!precommitted && vginfo->precommitted && !critical_section()))
return NULL;
+ /* Check whether we have already cached VG */
+ if (vginfo->vg_cache) {
+ if (vginfo->vg_ref_count > 2)
+ /* For lv_suspend we need lv and lv_precommit */
+ log_error(INTERNAL_ERROR "More then one shared VG.");
+ vg = vginfo->vg_cache;
+ vginfo->vg_ref_count++;
+ vginfo->vg_use_count++;
+ goto out;
+ }
+
fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
fic.context.vg_ref.vg_name = vginfo->vgname;
fic.context.vg_ref.vg_id = vgid;
@@ -678,6 +694,15 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
if (!(vg = import_vg_from_config_tree(vginfo->cft, fid)))
goto_bad;
+ /* Put VG into lvmcache */
+ vg->vginfo = vginfo;
+ vginfo->vg_cache = vg;
+ vginfo->vg_ref_count = 2; /* Keep 1 reference for lvmcache */
+ vginfo->vg_use_count = 1;
+
+ if (!dm_pool_lock(vg->vgmem, 1))
+ goto_bad;
+out:
log_debug("Using cached %smetadata for VG %s.",
vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
@@ -689,6 +714,52 @@ bad:
return NULL;
}
+/**
+ * Release a referenced VG in lvmcache
+ * and with the last reference unlock memory pool.
+ */
+int lvmcache_release_vg(struct volume_group *vg)
+{
+ if (!vg || !vg->vginfo)
+ return 1;
+
+ if (--vg->vginfo->vg_ref_count)
+ return 0;
+
+ log_debug("Released VG:%p %s from cache (used:%d).",
+ vg, vg->name, vg->vginfo->vg_use_count);
+
+ /* Debug perform crc check only when it's been used more then once */
+ if (!dm_pool_unlock(vg->vgmem, vg->vginfo->vg_use_count > 1))
+ log_error(INTERNAL_ERROR "VG mempool.");
+
+ vg->vginfo->vg_cache = NULL;
+ vg->vginfo = NULL;
+
+ return 1;
+}
+
+/**
+ * Drop VG from lvmcache.
+ *
+ * This is used for 'write' operations.
+ * Note: VG must not be shared in this moment.
+ */
+int lvmcache_drop_vg(struct volume_group *vg)
+{
+ if (!vg || !vg->vginfo)
+ return 1; /* Already dropped */
+
+ free_vg(vg);
+
+ if (!lvmcache_release_vg(vg)) {
+ log_error(INTERNAL_ERROR "Dropping referenced VG.");
+ return 0;
+ }
+
+ return 1;
+}
+
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal)
{
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 9aafff5..f5c1131 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -50,6 +50,9 @@ struct lvmcache_vginfo {
char *vgmetadata; /* Copy of VG metadata as format_text string */
struct config_tree *cft; /* Config tree created from vgmetadata */
/* Lifetime is directly tied to vgmetadata */
+ struct volume_group *vg_cache; /* Cached VG */
+ unsigned vg_ref_count; /* Cached VG ref counter */
+ unsigned vg_use_count; /* Cached VG usage */
unsigned precommitted; /* Is vgmetadata live or precommitted? */
};
@@ -122,6 +125,8 @@ struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
/* Returns cached volume group metadata. */
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
+int lvmcache_release_vg(struct volume_group *vg);
+int lvmcache_drop_vg(struct volume_group *vg);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 9e235a1..1cd1e6c 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -866,6 +866,12 @@ static struct volume_group *_vg_make_handle(struct cmd_context *cmd,
struct volume_group *vg,
uint32_t failure)
{
+ if (vg && vg->vginfo && (failure != SUCCESS)) {
+ /* Avoid overwrite of cached VG */
+ free_vg(vg);
+ vg = NULL;
+ }
+
if (!vg && !(vg = alloc_vg("vg_make_handle", cmd, NULL)))
return_NULL;
@@ -2864,8 +2870,13 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
(use_precommitted || !*consistent || !(correct_vg->status & INCONSISTENT_VG))) {
if (!(correct_vg->status & INCONSISTENT_VG))
*consistent = 1;
- else /* Inconsistent but we can't repair it */
+ else {
+ /* Do not keep such VG in cache */
+ if (!lvmcache_drop_vg(correct_vg))
+ return_NULL;
+ /* Inconsistent but we can't repair it */
correct_vg->status &= ~INCONSISTENT_VG;
+ }
return correct_vg;
} else {
@@ -3289,6 +3300,11 @@ void free_vg(struct volume_group *vg)
if (!vg)
return;
+ log_debug("Releasing VG %s (vg:%p, info:%p).", vg->name, vg, vg->vginfo);
+
+ if (!lvmcache_release_vg(vg))
+ return; /* Still referenced, do not destroy mempool */
+
vg_set_fid(vg, NULL);
if (vg->cmd && vg->vgmem == vg->cmd->mem) {
@@ -3827,7 +3843,11 @@ static struct volume_group *_recover_vg(struct cmd_context *cmd,
return_NULL;
}
- return (struct volume_group *)vg;
+ /* RW access is needed here -> remove from cache */
+ if (!lvmcache_drop_vg(vg))
+ return_NULL;
+
+ return vg;
}
/*
diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h
index bebe6cf..2cda69b 100644
--- a/lib/metadata/vg.h
+++ b/lib/metadata/vg.h
@@ -20,6 +20,7 @@ struct dm_pool;
struct format_instance;
struct dm_list;
struct id;
+struct lvmcache_vginfo;
typedef enum {
ALLOC_INVALID,
@@ -41,6 +42,7 @@ struct volume_group {
struct cmd_context *cmd;
struct dm_pool *vgmem;
struct format_instance *fid;
+ struct lvmcache_vginfo *vginfo; /* Backward reference to lvmcache */
struct dm_list *cmd_vgs;/* List of wanted/locked and opened VGs */
uint32_t cmd_missing_vgs;/* Flag marks missing VG */
uint32_t seqno; /* Metadata sequence number */
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 11/11] lv_postorder unlock and lock
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
` (9 preceding siblings ...)
2011-06-03 19:13 ` [PATCH 10/11] Share VG multiple times Zdenek Kabelac
@ 2011-06-03 19:13 ` Zdenek Kabelac
10 siblings, 0 replies; 12+ messages in thread
From: Zdenek Kabelac @ 2011-06-03 19:13 UTC (permalink / raw)
To: lvm-devel
Instead of unlocking and locking for every changed struct member
do it once when entering and leaving function.
Currently lv_postoder() does not modify other part of vg structure
then status flags of each LV with flags that are also removed.
After the function execution the structure should remain unmodified.
Signed-off-by: Zdenek Kabelac <zkabelac@redhat.com>
---
lib/metadata/metadata.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 1cd1e6c..f4cee5a 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2107,8 +2107,17 @@ static int _lv_postorder(struct logical_volume *lv,
void *data)
{
int r;
+ int lck = dm_pool_locked(lv->vg->vgmem);
+
+ if (lck && !dm_pool_unlock(lv->vg->vgmem, 0))
+ return_0;
+
r = _lv_postorder_visit(lv, fn, data);
_lv_postorder_cleanup(lv, 0);
+
+ if (lck && !dm_pool_lock(lv->vg->vgmem, 0))
+ return_0;
+
return r;
}
@@ -2122,6 +2131,10 @@ static int _lv_postorder_vg(struct volume_group *vg,
{
struct lv_list *lvl;
int r = 1;
+ int lck = dm_pool_locked(vg->vgmem);
+
+ if (lck && !dm_pool_unlock(vg->vgmem, 0))
+ return_0;
dm_list_iterate_items(lvl, &vg->lvs)
if (!_lv_postorder_visit(lvl->lv, fn, data)) {
@@ -2132,6 +2145,9 @@ static int _lv_postorder_vg(struct volume_group *vg,
dm_list_iterate_items(lvl, &vg->lvs)
_lv_postorder_cleanup(lvl->lv, 0);
+ if (lck && !dm_pool_lock(vg->vgmem, 0))
+ return_0;
+
return r;
}
--
1.7.5.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-06-03 19:13 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-03 19:13 [PATCH 00/11] Pool locking Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 01/11] Introduce laopts structure Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 02/11] Add laopts Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 03/11] Replace ACTIVATE Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 04/11] Replace MERGING in activation Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 05/11] FIXME Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 06/11] FIXME - remove test for status flag Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 07/11] Remove ACTIVATE_EXCL appearance from the code Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 08/11] Code move vg_mark_partial up in stack Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 09/11] Pool locking code Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 10/11] Share VG multiple times Zdenek Kabelac
2011-06-03 19:13 ` [PATCH 11/11] lv_postorder unlock and lock Zdenek Kabelac
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.