* [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