summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/format1/disk-rep.h3
-rw-r--r--lib/format1/import-export.c16
-rw-r--r--lib/format_text/export.c16
-rw-r--r--lib/format_text/flags.c4
-rw-r--r--lib/format_text/import_vsn1.c25
-rw-r--r--lib/locking/lvmlockd.c3
-rw-r--r--lib/metadata/lv_manip.c6
-rw-r--r--lib/metadata/metadata-exported.h7
-rw-r--r--lib/metadata/metadata.c27
-rw-r--r--lib/metadata/vg.c8
-rw-r--r--lib/misc/lvm-string.c3
-rw-r--r--lib/report/report.c4
-rw-r--r--tools/commands.h3
-rw-r--r--tools/lvchange.c2
-rw-r--r--tools/lvconvert.c2
-rw-r--r--tools/vgchange.c1
-rw-r--r--tools/vgconvert.c5
-rw-r--r--tools/vgreduce.c5
18 files changed, 110 insertions, 30 deletions
diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h
index 94d27894f..8da77f635 100644
--- a/lib/format1/disk-rep.h
+++ b/lib/format1/disk-rep.h
@@ -41,7 +41,7 @@
#define VG_WRITE 0x02 /* " */
#define VG_CLUSTERED 0x04 /* " */
#define VG_SHARED 0x08 /* " */
-#define VG_LOCK_TYPE 0x10 /* " */
+#define VG_WRITE_LOCKD 0x10 /* " */
/* logical volume */
#define LV_ACTIVE 0x01 /* lv_status */
@@ -52,6 +52,7 @@
#define LV_WRITE 0x02 /* " */
#define LV_SNAPSHOT 0x04 /* " */
#define LV_SNAPSHOT_ORG 0x08 /* " */
+#define LV_WRITE_LOCKD 0x10 /* " */
#define LV_BADBLOCK_ON 0x01 /* lv_badblock */
diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c
index 855c04273..f3c840450 100644
--- a/lib/format1/import-export.c
+++ b/lib/format1/import-export.c
@@ -243,8 +243,8 @@ int import_vg(struct dm_pool *mem,
if (vgd->vg_access & VG_CLUSTERED)
vg->status |= CLUSTERED;
- if (vgd->vg_access & VG_LOCK_TYPE)
- vg->status |= LOCK_TYPE;
+ if (vgd->vg_access & VG_WRITE_LOCKD)
+ vg->status |= LVM_WRITE_LOCKD;
if (vgd->vg_access & VG_SHARED)
vg->status |= SHARED;
@@ -273,8 +273,8 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg)
if (vg_is_clustered(vg))
vgd->vg_access |= VG_CLUSTERED;
- if (vg->status & LOCK_TYPE)
- vgd->vg_access |= VG_LOCK_TYPE;
+ if (vg->status & LVM_WRITE_LOCKD)
+ vgd->vg_access |= VG_WRITE_LOCKD;
if (vg->status & SHARED)
vgd->vg_access |= VG_SHARED;
@@ -324,6 +324,9 @@ int import_lv(struct cmd_context *cmd, struct dm_pool *mem,
if (lvd->lv_access & LV_WRITE)
lv->status |= LVM_WRITE;
+ if (lvd->lv_access & LV_WRITE_LOCKD)
+ lv->status |= LVM_WRITE;
+
if (lvd->lv_badblock)
lv->status |= BADBLOCK_ON;
@@ -356,9 +359,12 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
if (lv->status & LVM_READ)
lvd->lv_access |= LV_READ;
- if (lv->status & LVM_WRITE)
+ if ((lv->status & LVM_WRITE) && !(vg->status & LVM_WRITE_LOCKD))
lvd->lv_access |= LV_WRITE;
+ if ((lv->status & LVM_WRITE) && (vg->status & LVM_WRITE_LOCKD))
+ lvd->lv_access |= LV_WRITE_LOCKD;
+
if (lv->status & SPINDOWN_LV)
lvd->lv_status |= LV_SPINDOWN;
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index 3439f9218..63bd9ed75 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -614,9 +614,25 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
outf(f, "id = \"%s\"", buffer);
+ /*
+ * A writable LV in a lockd VG is written to disk with WRITE_LOCKD
+ * replacing WRITE, so that pre-lockd lvm versions will not think the
+ * LV is writable. In memory, only the WRITE lv status flag is used.
+ */
+
+ if ((lv->status & LVM_WRITE) && (lv->vg->status & LVM_WRITE_LOCKD)) {
+ lv->status &= ~LVM_WRITE;
+ lv->status |= LVM_WRITE_LOCKD;
+ }
+
if (!_print_flag_config(f, lv->status, LV_FLAGS))
return_0;
+ if (lv->status & LVM_WRITE_LOCKD) {
+ lv->status |= LVM_WRITE;
+ lv->status &= ~LVM_WRITE_LOCKD;
+ }
+
if (!_out_tags(f, &lv->tags))
return_0;
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index a933013cf..dbef2839b 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -34,8 +34,8 @@ static const struct flag _vg_flags[] = {
{PVMOVE, "PVMOVE", STATUS_FLAG},
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
+ {LVM_WRITE_LOCKD, "WRITE_LOCKD", COMPATIBLE_FLAG},
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
- {LOCK_TYPE, "LOCK_TYPE", STATUS_FLAG},
{SHARED, "SHARED", STATUS_FLAG},
{PARTIAL_VG, NULL, 0},
{PRECOMMITTED, NULL, 0},
@@ -54,6 +54,7 @@ static const struct flag _pv_flags[] = {
static const struct flag _lv_flags[] = {
{LVM_READ, "READ", STATUS_FLAG},
{LVM_WRITE, "WRITE", STATUS_FLAG},
+ {LVM_WRITE_LOCKD, "WRITE_LOCKD", COMPATIBLE_FLAG},
{FIXED_MINOR, "FIXED_MINOR", STATUS_FLAG},
{VISIBLE_LV, "VISIBLE", STATUS_FLAG},
{PVMOVE, "PVMOVE", STATUS_FLAG},
@@ -91,6 +92,7 @@ static const struct flag _lv_flags[] = {
{CACHE_POOL_DATA, NULL, 0},
{CACHE_POOL_METADATA, NULL, 0},
{LV_PENDING_DELETE, NULL, 0}, /* FIXME Display like COMPATIBLE_FLAG */
+ {LVMLOCK, NULL, 0},
{0, NULL, 0}
};
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 7fb4a5590..9993b150d 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -550,6 +550,28 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
return 0;
}
+ /*
+ * A lockd VG is represented both on disk and in memory with
+ * status WRITE_LOCKD. A non-lockd VG is represented on disk
+ * and in memory with status WRITE.
+ *
+ * An LV in a lockd VG is represented on disk with status WRITE_LOCKD,
+ * BUT in memory with status WRITE. So, when a lockd LV is written to
+ * disk, WRITE is changed to WRITE_LOCKD, and when a lockd LV is read
+ * from disk, WRITE_LOCKD is changed to WRITE.
+ *
+ * This is done to prevent pre-lockd versions of lvm from being able
+ * to write to lockd LVs. Old versions of lvm will not see WRITE on
+ * disk for the LV, and think the LV is read only, and the old version
+ * will not look for the WRITE_LOCKD flag. New versions of lvm will
+ * recognize either the WRITE or WRITE_LOCKD flag.
+ */
+
+ if (lv->status & LVM_WRITE_LOCKD) {
+ lv->status &= ~LVM_WRITE_LOCKD;
+ lv->status |= LVM_WRITE;
+ }
+
if (dm_config_has_node(lvn, "creation_time")) {
if (!_read_uint64(lvn, "creation_time", &timestamp)) {
log_error("Invalid creation_time for logical volume %s.",
@@ -642,6 +664,9 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)),
vg->pool_metadata_spare_lv = lv;
}
+ if (!lv_is_visible(lv) && !strcmp(lv->name, "lvmlock"))
+ lv->status |= LVMLOCK;
+
return 1;
}
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index d11725575..15af3a796 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -371,7 +371,8 @@ static int _create_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
- lv_set_hidden(lv);
+ lv_set_hidden(lv); /* FIXME: should this be done before vg is written? */
+ lv->status |= LVMLOCK; /* flag not written to metadata */
return 1;
}
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 485c55d92..5546421f5 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4442,9 +4442,7 @@ static int _lvresize_check_lv(struct cmd_context *cmd, struct logical_volume *lv
return 0;
}
- /* FIXME: use a status flag instead of the name "lvmlock". */
-
- if (!lv_is_visible(lv) && !lv_is_thin_pool_metadata(lv) && strcmp(lv->name, "lvmlock")) {
+ if (!lv_is_visible(lv) && !lv_is_thin_pool_metadata(lv) && !lv_is_lvmlock(lv)) {
log_error("Can't resize internal logical volume %s", lv->name);
return 0;
}
@@ -5466,7 +5464,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
vg = lv->vg;
- if (!vg_check_status(vg, LVM_WRITE))
+ if (!vg_status_writable(vg))
return_0;
if (lv_is_origin(lv)) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d544ed8bc..ed3967dcf 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -61,7 +61,6 @@
#define CLUSTERED UINT64_C(0x0000000000000400) /* VG */
//#define SHARED UINT64_C(0x0000000000000800) /* VG */
-#define LOCK_TYPE UINT64_C(0x0000000000001000) /* VG */
/* FIXME Remove when metadata restructuring is completed */
#define SNAPSHOT UINT64_C(0x0000000000001000) /* LV - internal use only */
@@ -123,7 +122,9 @@
#define PV_ALLOCATION_PROHIBITED UINT64_C(0x0010000000000000) /* PV - internal use only - allocation prohibited
e.g. to prohibit allocation of a RAID image
on a PV already holing an image of the RAID set */
-/* Next unused flag: UINT64_C(0x0020000000000000) */
+#define LVMLOCK UINT64_C(0x0020000000000000) /* LV - Internal use only */
+#define LVM_WRITE_LOCKD UINT64_C(0x0040000000000000) /* LV, VG */
+/* Next unused flag: UINT64_C(0x0080000000000000) */
/* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
@@ -219,6 +220,7 @@
#define lv_is_pool_data(lv) (((lv)->status & (CACHE_POOL_DATA | THIN_POOL_DATA)) ? 1 : 0)
#define lv_is_pool_metadata(lv) (((lv)->status & (CACHE_POOL_METADATA | THIN_POOL_METADATA)) ? 1 : 0)
#define lv_is_pool_metadata_spare(lv) (((lv)->status & POOL_METADATA_SPARE) ? 1 : 0)
+#define lv_is_lvmlock(lv) (((lv)->status & LVMLOCK) ? 1 : 0)
#define lv_is_rlog(lv) (((lv)->status & REPLICATOR_LOG) ? 1 : 0)
@@ -1010,6 +1012,7 @@ int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
int vg_remove_snapshot(struct logical_volume *cow);
int vg_check_status(const struct volume_group *vg, uint64_t status);
+int vg_status_writable(const struct volume_group *vg);
int vg_check_pv_dev_block_sizes(const struct volume_group *vg);
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index a2208a355..8b540ba50 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1047,6 +1047,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name)
goto bad;
}
+ /* vg_set_lock_type() may clear LVM_WRITE and set LVM_WRITE_LOCKD */
vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
vg->system_id = NULL;
if (!(vg->lvm1_system_id = dm_pool_zalloc(vg->vgmem, NAME_LEN + 1)))
@@ -4288,8 +4289,8 @@ static uint32_t _vg_bad_status_bits(const struct volume_group *vg,
failure |= FAILED_EXPORTED;
}
- if ((status & LVM_WRITE) &&
- !(vg->status & LVM_WRITE)) {
+ if ((status & (LVM_WRITE | LVM_WRITE_LOCKD)) &&
+ (!(vg->status & (LVM_WRITE | LVM_WRITE_LOCKD)))) {
log_error("Volume group %s is read-only", vg->name);
failure |= FAILED_READ_ONLY;
}
@@ -4314,6 +4315,22 @@ int vg_check_status(const struct volume_group *vg, uint64_t status)
}
/*
+ * Return 1 if writeable.
+ * Return 0 if not writeable.
+ *
+ * The VG or LV is writable if either LVM_WRITE or LVM_WRITE_LOCKD are set.
+ */
+
+int vg_status_writable(const struct volume_group *vg)
+{
+ if (vg->status & LVM_WRITE)
+ return 1;
+ if (vg->status & LVM_WRITE_LOCKD)
+ return 1;
+ return 0;
+}
+
+/*
* VG is left unlocked on failure
*/
static struct volume_group *_recover_vg(struct cmd_context *cmd,
@@ -4542,8 +4559,10 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
return _vg_make_handle(cmd, vg, FAILED_LOCKING);
}
- if (is_orphan_vg(vg_name))
+ if (is_orphan_vg(vg_name)) {
status_flags &= ~LVM_WRITE;
+ status_flags &= ~LVM_WRITE_LOCKD;
+ }
consistent_in = consistent;
@@ -4644,7 +4663,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
uint32_t lock_flags = LCK_VG_READ;
if (flags & READ_FOR_UPDATE) {
- status |= EXPORTED_VG | LVM_WRITE;
+ status |= EXPORTED_VG | LVM_WRITE | LVM_WRITE_LOCKD;
lock_flags = LCK_VG_WRITE;
}
diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c
index d50a88ebc..a23b4b6b9 100644
--- a/lib/metadata/vg.c
+++ b/lib/metadata/vg.c
@@ -635,8 +635,10 @@ int vg_set_lock_type(struct volume_group *vg, const char *lock_type)
return 0;
}
- if (is_lockd_type(lock_type))
- vg->status |= LOCK_TYPE;
+ if (is_lockd_type(lock_type)) {
+ vg->status |= LVM_WRITE_LOCKD;
+ vg->status &= ~LVM_WRITE;
+ }
return 1;
}
@@ -650,7 +652,7 @@ char *vg_attr_dup(struct dm_pool *mem, const struct volume_group *vg)
return NULL;
}
- repstr[0] = (vg->status & LVM_WRITE) ? 'w' : 'r';
+ repstr[0] = ((vg->status & LVM_WRITE) || (vg->status & LVM_WRITE_LOCKD)) ? 'w' : 'r';
repstr[1] = (vg_is_resizeable(vg)) ? 'z' : '-';
repstr[2] = (vg_is_exported(vg)) ? 'x' : '-';
repstr[3] = (vg_missing_pv_count(vg)) ? 'p' : '-';
diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
index 5d6385817..163fb67e5 100644
--- a/lib/misc/lvm-string.c
+++ b/lib/misc/lvm-string.c
@@ -162,7 +162,8 @@ static const char *_lvname_has_reserved_string(const char *lvname)
"_rmeta",
"_tdata",
"_tmeta",
- "_vorigin"
+ "_vorigin",
+ "lvmlock"
};
unsigned i;
diff --git a/lib/report/report.c b/lib/report/report.c
index b5418e55b..6dce65b83 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1424,8 +1424,8 @@ static int _vgpermissions_disp(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field,
const void *data, void *private)
{
- const char *perms = ((const struct volume_group *) data)->status & LVM_WRITE ? GET_FIRST_RESERVED_NAME(vg_permissions_rw)
- : GET_FIRST_RESERVED_NAME(vg_permissions_r);
+ const char *perms = ((const struct volume_group *) data)->status & (LVM_WRITE | LVM_WRITE_LOCKD) ? GET_FIRST_RESERVED_NAME(vg_permissions_rw)
+ : GET_FIRST_RESERVED_NAME(vg_permissions_r);
return _string_disp(rh, mem, field, &perms, private);
}
diff --git a/tools/commands.h b/tools/commands.h
index 08d4b4eee..0894284d3 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -988,7 +988,8 @@ xx(vgchange,
metadataprofile_ARG, monitor_ARG, noudevsync_ARG, metadatacopies_ARG,
vgmetadatacopies_ARG, partial_ARG, physicalextentsize_ARG, poll_ARG,
refresh_ARG, resizeable_ARG, resizable_ARG, select_ARG, sysinit_ARG,
- systemid_ARG, test_ARG, uuid_ARG, lockstart_ARG, lockstop_ARG, locktype_ARG, lockopt_ARG)
+ systemid_ARG, test_ARG, uuid_ARG, lockstart_ARG, lockstop_ARG, locktype_ARG, lockopt_ARG,
+ force_ARG)
xx(vgck,
"Check the consistency of volume group(s)",
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 203af364c..b97190493 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -885,7 +885,7 @@ static int _lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
struct logical_volume *origin;
char snaps_msg[128];
- if (!(lv->vg->status & LVM_WRITE) &&
+ if (!vg_status_writable(lv->vg) &&
(arg_count(cmd, contiguous_ARG) || arg_count(cmd, permission_ARG) ||
arg_count(cmd, readahead_ARG) || arg_count(cmd, persistent_ARG) ||
arg_count(cmd, discards_ARG) || arg_count(cmd, zero_ARG) ||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 6ef0fe1f3..ec40852db 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2003,7 +2003,7 @@ static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volu
return 0;
}
- if (!vg_check_status(vg, LVM_WRITE))
+ if (!vg_status_writable(vg))
return_0;
if (lv_is_pvmove(cow) || lv_is_mirror_type(cow) || lv_is_raid_type(cow) || lv_is_thin_type(cow)) {
diff --git a/tools/vgchange.c b/tools/vgchange.c
index a35c32ea0..3228ec4e5 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -538,7 +538,6 @@ static int _vgchange_locktype(struct cmd_context *cmd,
}
vg->status &= ~CLUSTERED;
- vg->status &= ~LOCK_TYPE;
vg->lock_type = "none";
vg->lock_args = NULL;
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 50b3e44a9..b7b1f8e96 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -30,7 +30,10 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
struct lvinfo info;
int active = 0;
- if (!vg_check_status(vg, LVM_WRITE | EXPORTED_VG))
+ if (!vg_status_writable(vg))
+ return_ECMD_FAILED;
+
+ if (!vg_check_status(vg, EXPORTED_VG))
return_ECMD_FAILED;
if (vg->fid->fmt == cmd->fmt) {
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index fda8fb6d1..f634c604c 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -127,7 +127,10 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
{
int r;
- if (!vg_check_status(vg, EXPORTED_VG | LVM_WRITE | RESIZEABLE_VG))
+ if (!vg_status_writable(vg))
+ return_ECMD_FAILED;
+
+ if (!vg_check_status(vg, EXPORTED_VG | RESIZEABLE_VG))
return ECMD_FAILED;
r = vgreduce_single(cmd, vg, pv, 1);