From b83af516681bebcd8f28efadb1bd1c9f232ee1cc Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Mon, 25 Oct 2010 11:20:54 +0000 Subject: [PATCH] Add global/metadata_read_only to use unrepaired metadata in read-only cmds. --- WHATS_NEW | 1 + doc/example.conf.in | 7 +++++++ lib/commands/toolcontext.c | 3 +++ lib/commands/toolcontext.h | 1 + lib/config/defaults.h | 1 + lib/locking/locking.c | 7 +++++++ lib/metadata/metadata.c | 25 +++++++++++++++++++------ tools/commands.h | 36 ++++++++++++++++++------------------ tools/lvmcmdline.c | 7 +++++++ tools/tools.h | 3 ++- 10 files changed, 66 insertions(+), 25 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 05acc3bd4..0ca1047c5 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.75 - ===================================== + Add global/metadata_read_only to use unrepaired metadata in read-only cmds. Don't take write lock in vgchange --refresh, --poll or --monitor. Skip dm devices in scan if they contain only error targets or are empty. Fix strict-aliasing compile warning in partition table scanning. diff --git a/doc/example.conf.in b/doc/example.conf.in index e71672be0..ac9aae707 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -334,6 +334,13 @@ global { # Treat any internal errors as fatal errors, aborting the process that # encountered the internal error. Please only enable for debugging. abort_on_internal_errors = 0 + + # If set to 1, no operations that change on-disk metadata will be permitted. + # Additionally, read-only commands that encounter metadata in need of repair + # will still be allowed to proceed exactly as if the repair had been + # performed (except for the unchanged vg_seqno). + # Inappropriate use could mess up your system, so seek advice first! + metadata_read_only = 0 } activation { diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index a9f5bd681..09a37f2de 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -314,6 +314,9 @@ static int _process_config(struct cmd_context *cmd) if ((cv->type != CFG_STRING) || !cv->v.str[0]) log_error("Ignoring invalid activation/mlock_filter entry in config file"); + cmd->metadata_read_only = find_config_tree_int(cmd, "global/metadata_read_only", + DEFAULT_METADATA_READ_ONLY); + return 1; } diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index d0ff12ac1..e9dcf3a69 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -73,6 +73,7 @@ struct cmd_context { unsigned handles_unknown_segments:1; unsigned partial_activation:1; unsigned si_unit_consistency:1; + unsigned metadata_read_only:1; struct dev_filter *filter; int dump_filter; /* Dump filter when exiting? */ diff --git a/lib/config/defaults.h b/lib/config/defaults.h index 584692f2e..a640112c3 100644 --- a/lib/config/defaults.h +++ b/lib/config/defaults.h @@ -44,6 +44,7 @@ #define DEFAULT_WAIT_FOR_LOCKS 1 #define DEFAULT_PRIORITISE_WRITE_LOCKS 1 #define DEFAULT_USE_MLOCKALL 0 +#define DEFAULT_METADATA_READ_ONLY 0 #define DEFAULT_MIRRORLOG "disk" #define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate" diff --git a/lib/locking/locking.c b/lib/locking/locking.c index 94c8e8bab..60eaab3ec 100644 --- a/lib/locking/locking.c +++ b/lib/locking/locking.c @@ -374,6 +374,13 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, return 0; } + if (cmd->metadata_read_only && + ((flags & LCK_TYPE_MASK) == LCK_WRITE) && + strcmp(resource, VG_GLOBAL)) { + log_error("Operation prohibited while global/metadata_read_only is set."); + return 0; + } + if ((ret = _locking.lock_resource(cmd, resource, flags))) { if ((flags & LCK_SCOPE_MASK) == LCK_VG && !(flags & LCK_CACHE)) { diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 4d11ac4c7..9a84ae82f 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -2729,8 +2729,14 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, /* FIXME Also ensure contents same - checksum compare? */ if (correct_vg->seqno != vg->seqno) { - inconsistent = 1; - inconsistent_seqno = 1; + if (cmd->metadata_read_only) + log_very_verbose("Not repairing VG %s metadata seqno (%d != %d) " + "as global/metadata_read_only is set.", + vgname, vg->seqno, correct_vg->seqno); + else { + inconsistent = 1; + inconsistent_seqno = 1; + } if (vg->seqno > correct_vg->seqno) { vg_release(correct_vg); correct_vg = vg; @@ -2805,8 +2811,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, } } - if (dm_list_size(&correct_vg->pvs) != dm_list_size(pvids) - + vg_missing_pv_count(correct_vg)) { + if (dm_list_size(&correct_vg->pvs) != + dm_list_size(pvids) + vg_missing_pv_count(correct_vg)) { log_debug("Cached VG %s had incorrect PV list", vgname); @@ -2882,8 +2888,15 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, /* FIXME Also ensure contents same - checksums same? */ if (correct_vg->seqno != vg->seqno) { - inconsistent = 1; - inconsistent_seqno = 1; + /* Ignore inconsistent seqno if told to skip repair logic */ + if (cmd->metadata_read_only) + log_very_verbose("Not repairing VG %s metadata seqno (%d != %d) " + "as global/metadata_read_only is set.", + vgname, vg->seqno, correct_vg->seqno); + else { + inconsistent = 1; + inconsistent_seqno = 1; + } if (!_update_pv_list(cmd->mem, &all_pvs, vg)) { vg_release(vg); vg_release(correct_vg); diff --git a/tools/commands.h b/tools/commands.h index 761083250..fa177cd39 100644 --- a/tools/commands.h +++ b/tools/commands.h @@ -30,7 +30,7 @@ xx(e2fsadm, xx(dumpconfig, "Dump active configuration", - 0, + PERMITTED_READ_ONLY, "dumpconfig " "\t[-f|--file filename] " "\n" "[ConfigurationVariable...]\n", @@ -38,12 +38,12 @@ xx(dumpconfig, xx(formats, "List available metadata formats", - 0, + PERMITTED_READ_ONLY, "formats\n") xx(help, "Display help for commands", - 0, + PERMITTED_READ_ONLY, "help " "\n") /********* @@ -58,7 +58,7 @@ xx(lvactivate, xx(lvchange, "Change the attributes of logical volume(s)", - CACHE_VGMETADATA, + CACHE_VGMETADATA | PERMITTED_READ_ONLY, "lvchange\n" "\t[-A|--autobackup y|n]\n" "\t[-a|--available [e|l]y|n]\n" @@ -207,7 +207,7 @@ xx(lvcreate, xx(lvdisplay, "Display information about a logical volume", - 0, + PERMITTED_READ_ONLY, "lvdisplay\n" "\t[-a|--all]\n" "\t[-c|--colon]\n" @@ -287,7 +287,7 @@ xx(lvmchange, xx(lvmdiskscan, "List devices that may be used as physical volumes", - 0, + PERMITTED_READ_ONLY, "lvmdiskscan\n" "\t[-d|--debug]\n" "\t[-h|--help]\n" @@ -401,7 +401,7 @@ xx(lvresize, xx(lvs, "Display information about logical volumes", - 0, + PERMITTED_READ_ONLY, "lvs" "\n" "\t[-a|--all]\n" "\t[--aligned]\n" @@ -432,7 +432,7 @@ xx(lvs, xx(lvscan, "List all logical volumes in all volume groups", - 0, + PERMITTED_READ_ONLY, "lvscan " "\n" "\t[-a|--all]\n" "\t[-b|--blockdevice] " "\n" @@ -545,7 +545,7 @@ xx(pvdata, xx(pvdisplay, "Display various attributes of physical volume(s)", - CACHE_VGMETADATA, + CACHE_VGMETADATA | PERMITTED_READ_ONLY, "pvdisplay\n" "\t[-c|--colon]\n" "\t[-d|--debug]\n" @@ -620,7 +620,7 @@ xx(pvremove, xx(pvs, "Display information about physical volumes", - CACHE_VGMETADATA, + CACHE_VGMETADATA | PERMITTED_READ_ONLY, "pvs" "\n" "\t[-a|--all]\n" "\t[--aligned]\n" @@ -651,7 +651,7 @@ xx(pvs, xx(pvscan, "List all physical volumes", - 0, + PERMITTED_READ_ONLY, "pvscan " "\n" "\t[-d|--debug] " "\n" "\t{-e|--exported | -n|--novolumegroup} " "\n" @@ -668,12 +668,12 @@ xx(pvscan, xx(segtypes, "List available segment types", - 0, + PERMITTED_READ_ONLY, "segtypes\n") xx(vgcfgbackup, "Backup volume group configuration(s)", - 0, + PERMITTED_READ_ONLY, "vgcfgbackup " "\n" "\t[-d|--debug] " "\n" "\t[-f|--file filename] " "\n" @@ -704,7 +704,7 @@ xx(vgcfgrestore, xx(vgchange, "Change volume group attributes", - CACHE_VGMETADATA, + CACHE_VGMETADATA | PERMITTED_READ_ONLY, "vgchange" "\n" "\t[-A|--autobackup {y|n}] " "\n" "\t[--alloc AllocationPolicy] " "\n" @@ -797,7 +797,7 @@ xx(vgcreate, xx(vgdisplay, "Display volume group information", - 0, + PERMITTED_READ_ONLY, "vgdisplay " "\n" "\t[-A|--activevolumegroups]" "\n" "\t[-c|--colon | -s|--short | -v|--verbose]" "\n" @@ -961,7 +961,7 @@ xx(vgrename, xx(vgs, "Display information about volume groups", - 0, + PERMITTED_READ_ONLY, "vgs" "\n" "\t[--aligned]\n" "\t[-a|--all]\n" @@ -991,7 +991,7 @@ xx(vgs, xx(vgscan, "Search for all volume groups", - 0, + PERMITTED_READ_ONLY, "vgscan " "\t[-d|--debug]\n" "\t[-h|--help]\n" @@ -1029,6 +1029,6 @@ xx(vgsplit, xx(version, "Display software and driver version information", - 0, + PERMITTED_READ_ONLY, "version\n" ) diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index b29acfbb2..be5169306 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -1073,6 +1073,13 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) if ((ret = _process_common_commands(cmd))) goto_out; + if (cmd->metadata_read_only && + !(cmd->command->flags & PERMITTED_READ_ONLY)) { + log_error("%s: Command not permitted while global/metadata_read_only " + "is set.", cmd->cmd_line); + goto out; + } + if (arg_count(cmd, nolocking_ARG)) locking_type = 0; else diff --git a/tools/tools.h b/tools/tools.h index e9bc85023..80d3e9bdd 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -117,7 +117,8 @@ struct arg { /* void *ptr; // Currently not used. */ }; -#define CACHE_VGMETADATA 0x00000001 +#define CACHE_VGMETADATA 0x00000001 +#define PERMITTED_READ_ONLY 0x00000002 /* a register of the lvm commands */ struct command {