diff options
-rw-r--r-- | lib/format1/disk-rep.h | 3 | ||||
-rw-r--r-- | lib/format1/import-export.c | 16 | ||||
-rw-r--r-- | lib/format_text/export.c | 16 | ||||
-rw-r--r-- | lib/format_text/flags.c | 4 | ||||
-rw-r--r-- | lib/format_text/import_vsn1.c | 25 | ||||
-rw-r--r-- | lib/locking/lvmlockd.c | 3 | ||||
-rw-r--r-- | lib/metadata/lv_manip.c | 6 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 7 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 27 | ||||
-rw-r--r-- | lib/metadata/vg.c | 8 | ||||
-rw-r--r-- | lib/misc/lvm-string.c | 3 | ||||
-rw-r--r-- | lib/report/report.c | 4 | ||||
-rw-r--r-- | tools/commands.h | 3 | ||||
-rw-r--r-- | tools/lvchange.c | 2 | ||||
-rw-r--r-- | tools/lvconvert.c | 2 | ||||
-rw-r--r-- | tools/vgchange.c | 1 | ||||
-rw-r--r-- | tools/vgconvert.c | 5 | ||||
-rw-r--r-- | tools/vgreduce.c | 5 |
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", ×tamp)) { 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); |