Home | History | Annotate | Line # | Download | only in tools
vgchange.c revision 1.1
      1 /*	$NetBSD: vgchange.c,v 1.1 2008/12/22 00:19:08 haad Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
      6  *
      7  * This file is part of LVM2.
      8  *
      9  * This copyrighted material is made available to anyone wishing to use,
     10  * modify, copy, or redistribute it subject to the terms and conditions
     11  * of the GNU Lesser General Public License v.2.1.
     12  *
     13  * You should have received a copy of the GNU Lesser General Public License
     14  * along with this program; if not, write to the Free Software Foundation,
     15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16  */
     17 
     18 #include "tools.h"
     19 
     20 static int _monitor_lvs_in_vg(struct cmd_context *cmd,
     21 			       struct volume_group *vg, int reg)
     22 {
     23 	struct lv_list *lvl;
     24 	struct logical_volume *lv;
     25 	struct lvinfo info;
     26 	int lv_active;
     27 	int count = 0;
     28 
     29 	dm_list_iterate_items(lvl, &vg->lvs) {
     30 		lv = lvl->lv;
     31 
     32 		if (!lv_info(cmd, lv, &info, 0, 0))
     33 			lv_active = 0;
     34 		else
     35 			lv_active = info.exists;
     36 
     37 		/*
     38 		 * FIXME: Need to consider all cases... PVMOVE, etc
     39 		 */
     40 		if ((lv->status & PVMOVE) || !lv_active)
     41 			continue;
     42 
     43 		if (!monitor_dev_for_events(cmd, lv, reg)) {
     44 			continue;
     45 		} else
     46 			count++;
     47 	}
     48 
     49 	/*
     50 	 * returns the number of _new_ monitored devices
     51 	 */
     52 
     53 	return count;
     54 }
     55 
     56 static int _activate_lvs_in_vg(struct cmd_context *cmd,
     57 			       struct volume_group *vg, int activate)
     58 {
     59 	struct lv_list *lvl;
     60 	struct logical_volume *lv;
     61 	const char *pvname;
     62 	int count = 0;
     63 
     64 	dm_list_iterate_items(lvl, &vg->lvs) {
     65 		lv = lvl->lv;
     66 
     67 		/* Only request activation of snapshot origin devices */
     68 		if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
     69 			continue;
     70 
     71 		/* Only request activation of mirror LV */
     72 		if ((lv->status & MIRROR_IMAGE) || (lv->status & MIRROR_LOG))
     73 			continue;
     74 
     75 		/* Can't deactivate a pvmove LV */
     76 		/* FIXME There needs to be a controlled way of doing this */
     77 		if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
     78 		    ((lv->status & PVMOVE) ))
     79 			continue;
     80 
     81 		if (activate == CHANGE_AN) {
     82 			if (!deactivate_lv(cmd, lv))
     83 				continue;
     84 		} else if (activate == CHANGE_ALN) {
     85 			if (!deactivate_lv_local(cmd, lv))
     86 				continue;
     87 		} else if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
     88 			if (!activate_lv_excl(cmd, lv))
     89 				continue;
     90 		} else if (activate == CHANGE_ALY) {
     91 			if (!activate_lv_local(cmd, lv))
     92 				continue;
     93 		} else if (!activate_lv(cmd, lv))
     94 			continue;
     95 
     96 		if ((lv->status & PVMOVE) &&
     97 		    (pvname = get_pvmove_pvname_from_lv_mirr(lv))) {
     98 			log_verbose("Spawning background process for %s %s",
     99 				    lv->name, pvname);
    100 			pvmove_poll(cmd, pvname, 1);
    101 			continue;
    102 		}
    103 
    104 		count++;
    105 	}
    106 
    107 	return count;
    108 }
    109 
    110 static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
    111 {
    112 	int active, monitored;
    113 
    114 	if ((active = lvs_in_vg_activated(vg)) &&
    115 	    dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
    116 		monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
    117 		log_print("%d logical volume(s) in volume group "
    118 			    "\"%s\" %smonitored",
    119 			    monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
    120 	}
    121 
    122 	return ECMD_PROCESSED;
    123 }
    124 
    125 static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
    126 {
    127 	int lv_open, active, monitored;
    128 	int available;
    129 	int activate = 1;
    130 
    131 	available = arg_uint_value(cmd, available_ARG, 0);
    132 
    133 	if ((available == CHANGE_AN) || (available == CHANGE_ALN))
    134 		activate = 0;
    135 
    136 	/* FIXME: Force argument to deactivate them? */
    137 	if (!activate && (lv_open = lvs_in_vg_opened(vg))) {
    138 		log_error("Can't deactivate volume group \"%s\" with %d open "
    139 			  "logical volume(s)", vg->name, lv_open);
    140 		return ECMD_FAILED;
    141 	}
    142 
    143 	if (activate && lockingfailed() && (vg_is_clustered(vg))) {
    144 		log_error("Locking inactive: ignoring clustered "
    145 			  "volume group %s", vg->name);
    146 		return ECMD_FAILED;
    147 	}
    148 
    149 	/* FIXME Move into library where clvmd can use it */
    150 	if (activate && !lockingfailed())
    151 		check_current_backup(vg);
    152 
    153 	if (activate && (active = lvs_in_vg_activated(vg))) {
    154 		log_verbose("%d logical volume(s) in volume group \"%s\" "
    155 			    "already active", active, vg->name);
    156 		if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
    157 			monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
    158 			log_verbose("%d existing logical volume(s) in volume "
    159 				    "group \"%s\" %smonitored",
    160 				    monitored, vg->name,
    161 				    dmeventd_monitor_mode() ? "" : "un");
    162 		}
    163 	}
    164 
    165 	if (activate && _activate_lvs_in_vg(cmd, vg, available))
    166 		log_verbose("Activated logical volumes in "
    167 			    "volume group \"%s\"", vg->name);
    168 
    169 	if (!activate && _activate_lvs_in_vg(cmd, vg, available))
    170 		log_verbose("Deactivated logical volumes in "
    171 			    "volume group \"%s\"", vg->name);
    172 
    173 	log_print("%d logical volume(s) in volume group \"%s\" now active",
    174 		  lvs_in_vg_activated(vg), vg->name);
    175 	return ECMD_PROCESSED;
    176 }
    177 
    178 static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg)
    179 {
    180 	alloc_policy_t alloc;
    181 
    182 	alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);
    183 
    184 	if (alloc == ALLOC_INHERIT) {
    185 		log_error("Volume Group allocation policy cannot inherit "
    186 			  "from anything");
    187 		return EINVALID_CMD_LINE;
    188 	}
    189 
    190 	if (alloc == vg->alloc) {
    191 		log_error("Volume group allocation policy is already %s",
    192 			  get_alloc_string(vg->alloc));
    193 		return ECMD_FAILED;
    194 	}
    195 
    196 	if (!archive(vg))
    197 		return ECMD_FAILED;
    198 
    199 	vg->alloc = alloc;
    200 
    201 	if (!vg_write(vg) || !vg_commit(vg))
    202 		return ECMD_FAILED;
    203 
    204 	backup(vg);
    205 
    206 	log_print("Volume group \"%s\" successfully changed", vg->name);
    207 
    208 	return ECMD_PROCESSED;
    209 }
    210 
    211 static int _vgchange_resizeable(struct cmd_context *cmd,
    212 				struct volume_group *vg)
    213 {
    214 	int resizeable = !strcmp(arg_str_value(cmd, resizeable_ARG, "n"), "y");
    215 
    216 	if (resizeable && (vg_status(vg) & RESIZEABLE_VG)) {
    217 		log_error("Volume group \"%s\" is already resizeable",
    218 			  vg->name);
    219 		return ECMD_FAILED;
    220 	}
    221 
    222 	if (!resizeable && !(vg_status(vg) & RESIZEABLE_VG)) {
    223 		log_error("Volume group \"%s\" is already not resizeable",
    224 			  vg->name);
    225 		return ECMD_FAILED;
    226 	}
    227 
    228 	if (!archive(vg))
    229 		return ECMD_FAILED;
    230 
    231 	if (resizeable)
    232 		vg->status |= RESIZEABLE_VG;
    233 	else
    234 		vg->status &= ~RESIZEABLE_VG;
    235 
    236 	if (!vg_write(vg) || !vg_commit(vg))
    237 		return ECMD_FAILED;
    238 
    239 	backup(vg);
    240 
    241 	log_print("Volume group \"%s\" successfully changed", vg->name);
    242 
    243 	return ECMD_PROCESSED;
    244 }
    245 
    246 static int _vgchange_clustered(struct cmd_context *cmd,
    247 			       struct volume_group *vg)
    248 {
    249 	int clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
    250 	struct lv_list *lvl;
    251 
    252 	if (clustered && (vg_is_clustered(vg))) {
    253 		log_error("Volume group \"%s\" is already clustered",
    254 			  vg->name);
    255 		return ECMD_FAILED;
    256 	}
    257 
    258 	if (!clustered && !(vg_is_clustered(vg))) {
    259 		log_error("Volume group \"%s\" is already not clustered",
    260 			  vg->name);
    261 		return ECMD_FAILED;
    262 	}
    263 
    264 	if (clustered) {
    265 		dm_list_iterate_items(lvl, &vg->lvs) {
    266 			if (lv_is_origin(lvl->lv) || lv_is_cow(lvl->lv)) {
    267 				log_error("Volume group %s contains snapshots "
    268 					  "that are not yet supported.",
    269 					  vg->name);
    270 				return ECMD_FAILED;
    271 			}
    272 		}
    273 	}
    274 
    275 	if (!archive(vg))
    276 		return ECMD_FAILED;
    277 
    278 	if (clustered)
    279 		vg->status |= CLUSTERED;
    280 	else
    281 		vg->status &= ~CLUSTERED;
    282 
    283 	if (!vg_write(vg) || !vg_commit(vg))
    284 		return ECMD_FAILED;
    285 
    286 	backup(vg);
    287 
    288 	log_print("Volume group \"%s\" successfully changed", vg->name);
    289 
    290 	return ECMD_PROCESSED;
    291 }
    292 
    293 static int _vgchange_logicalvolume(struct cmd_context *cmd,
    294 				   struct volume_group *vg)
    295 {
    296 	uint32_t max_lv = arg_uint_value(cmd, logicalvolume_ARG, 0);
    297 
    298 	if (!(vg_status(vg) & RESIZEABLE_VG)) {
    299 		log_error("Volume group \"%s\" must be resizeable "
    300 			  "to change MaxLogicalVolume", vg->name);
    301 		return ECMD_FAILED;
    302 	}
    303 
    304 	if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS)) {
    305 		if (!max_lv)
    306 			max_lv = 255;
    307 		else if (max_lv > 255) {
    308 			log_error("MaxLogicalVolume limit is 255");
    309 			return ECMD_FAILED;
    310 		}
    311 	}
    312 
    313 	if (max_lv && max_lv < vg->lv_count) {
    314 		log_error("MaxLogicalVolume is less than the current number "
    315 			  "%d of LVs for \"%s\"", vg->lv_count,
    316 			  vg->name);
    317 		return ECMD_FAILED;
    318 	}
    319 
    320 	if (!archive(vg))
    321 		return ECMD_FAILED;
    322 
    323 	vg->max_lv = max_lv;
    324 
    325 	if (!vg_write(vg) || !vg_commit(vg))
    326 		return ECMD_FAILED;
    327 
    328 	backup(vg);
    329 
    330 	log_print("Volume group \"%s\" successfully changed", vg->name);
    331 
    332 	return ECMD_PROCESSED;
    333 }
    334 
    335 static int _vgchange_physicalvolumes(struct cmd_context *cmd,
    336 				     struct volume_group *vg)
    337 {
    338 	uint32_t max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
    339 
    340 	if (!(vg_status(vg) & RESIZEABLE_VG)) {
    341 		log_error("Volume group \"%s\" must be resizeable "
    342 			  "to change MaxPhysicalVolumes", vg->name);
    343 		return ECMD_FAILED;
    344 	}
    345 
    346 	if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
    347 		log_error("MaxPhysicalVolumes may not be negative");
    348 		return EINVALID_CMD_LINE;
    349 	}
    350 
    351 	if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS)) {
    352 		if (!max_pv)
    353 			max_pv = 255;
    354 		else if (max_pv > 255) {
    355 			log_error("MaxPhysicalVolume limit is 255");
    356 			return ECMD_FAILED;
    357 		}
    358 	}
    359 
    360 	if (max_pv && max_pv < vg->pv_count) {
    361 		log_error("MaxPhysicalVolumes is less than the current number "
    362 			  "%d of PVs for \"%s\"", vg->pv_count,
    363 			  vg->name);
    364 		return ECMD_FAILED;
    365 	}
    366 
    367 	if (!archive(vg))
    368 		return ECMD_FAILED;
    369 
    370 	vg->max_pv = max_pv;
    371 
    372 	if (!vg_write(vg) || !vg_commit(vg))
    373 		return ECMD_FAILED;
    374 
    375 	backup(vg);
    376 
    377 	log_print("Volume group \"%s\" successfully changed", vg->name);
    378 
    379 	return ECMD_PROCESSED;
    380 }
    381 
    382 static int _vgchange_pesize(struct cmd_context *cmd, struct volume_group *vg)
    383 {
    384 	uint32_t extent_size;
    385 
    386 	if (!(vg_status(vg) & RESIZEABLE_VG)) {
    387 		log_error("Volume group \"%s\" must be resizeable "
    388 			  "to change PE size", vg->name);
    389 		return ECMD_FAILED;
    390 	}
    391 
    392 	if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
    393 		log_error("Physical extent size may not be negative");
    394 		return EINVALID_CMD_LINE;
    395 	}
    396 
    397 	extent_size = arg_uint_value(cmd, physicalextentsize_ARG, 0);
    398 	if (!extent_size) {
    399 		log_error("Physical extent size may not be zero");
    400 		return EINVALID_CMD_LINE;
    401 	}
    402 
    403 	if (extent_size == vg->extent_size) {
    404 		log_error("Physical extent size of VG %s is already %s",
    405 			  vg->name, display_size(cmd, (uint64_t) extent_size));
    406 		return ECMD_PROCESSED;
    407 	}
    408 
    409 	if (extent_size & (extent_size - 1)) {
    410 		log_error("Physical extent size must be a power of 2.");
    411 		return EINVALID_CMD_LINE;
    412 	}
    413 
    414 	if (extent_size > vg->extent_size) {
    415 		if ((uint64_t) vg->extent_size * vg->extent_count % extent_size) {
    416 			/* FIXME Adjust used PV sizes instead */
    417 			log_error("New extent size is not a perfect fit");
    418 			return EINVALID_CMD_LINE;
    419 		}
    420 	}
    421 
    422 	if (!archive(vg))
    423 		return ECMD_FAILED;
    424 
    425 	if (!vg_change_pesize(cmd, vg, extent_size)) {
    426 		stack;
    427 		return ECMD_FAILED;
    428 	}
    429 
    430 	if (!vg_write(vg) || !vg_commit(vg))
    431 		return ECMD_FAILED;
    432 
    433 	backup(vg);
    434 
    435 	log_print("Volume group \"%s\" successfully changed", vg->name);
    436 
    437 	return ECMD_PROCESSED;
    438 }
    439 
    440 static int _vgchange_tag(struct cmd_context *cmd, struct volume_group *vg,
    441 			 int arg)
    442 {
    443 	const char *tag;
    444 
    445 	if (!(tag = arg_str_value(cmd, arg, NULL))) {
    446 		log_error("Failed to get tag");
    447 		return ECMD_FAILED;
    448 	}
    449 
    450 	if (!(vg->fid->fmt->features & FMT_TAGS)) {
    451 		log_error("Volume group %s does not support tags", vg->name);
    452 		return ECMD_FAILED;
    453 	}
    454 
    455 	if (!archive(vg))
    456 		return ECMD_FAILED;
    457 
    458 	if ((arg == addtag_ARG)) {
    459 		if (!str_list_add(cmd->mem, &vg->tags, tag)) {
    460 			log_error("Failed to add tag %s to volume group %s",
    461 				  tag, vg->name);
    462 			return ECMD_FAILED;
    463 		}
    464 	} else {
    465 		if (!str_list_del(&vg->tags, tag)) {
    466 			log_error("Failed to remove tag %s from volume group "
    467 				  "%s", tag, vg->name);
    468 			return ECMD_FAILED;
    469 		}
    470 	}
    471 
    472 	if (!vg_write(vg) || !vg_commit(vg))
    473 		return ECMD_FAILED;
    474 
    475 	backup(vg);
    476 
    477 	log_print("Volume group \"%s\" successfully changed", vg->name);
    478 
    479 	return ECMD_PROCESSED;
    480 }
    481 
    482 static int _vgchange_uuid(struct cmd_context *cmd __attribute((unused)),
    483 			  struct volume_group *vg)
    484 {
    485 	struct lv_list *lvl;
    486 
    487 	if (lvs_in_vg_activated(vg)) {
    488 		log_error("Volume group has active logical volumes");
    489 		return ECMD_FAILED;
    490 	}
    491 
    492 	if (!archive(vg))
    493 		return ECMD_FAILED;
    494 
    495 	if (!id_create(&vg->id)) {
    496 		log_error("Failed to generate new random UUID for VG %s.",
    497 			  vg->name);
    498 		return ECMD_FAILED;
    499 	}
    500 
    501 	dm_list_iterate_items(lvl, &vg->lvs) {
    502 		memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
    503 	}
    504 
    505 	if (!vg_write(vg) || !vg_commit(vg))
    506 		return ECMD_FAILED;
    507 
    508 	backup(vg);
    509 
    510 	log_print("Volume group \"%s\" successfully changed", vg->name);
    511 
    512 	return ECMD_PROCESSED;
    513 }
    514 
    515 static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
    516 			   struct volume_group *vg, int consistent,
    517 			   void *handle __attribute((unused)))
    518 {
    519 	int r = ECMD_FAILED;
    520 
    521 	if (!vg) {
    522 		log_error("Unable to find volume group \"%s\"", vg_name);
    523 		return ECMD_FAILED;
    524 	}
    525 
    526 	if (!consistent) {
    527 		unlock_vg(cmd, vg_name);
    528 		dev_close_all();
    529 		log_error("Volume group \"%s\" inconsistent", vg_name);
    530 		if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
    531 			return ECMD_FAILED;
    532 	}
    533 
    534 	if (!(vg_status(vg) & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
    535 		log_error("Volume group \"%s\" is read-only", vg->name);
    536 		return ECMD_FAILED;
    537 	}
    538 
    539 	if (vg_status(vg) & EXPORTED_VG) {
    540 		log_error("Volume group \"%s\" is exported", vg_name);
    541 		return ECMD_FAILED;
    542 	}
    543 
    544 	init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
    545 					    (cmd->is_static || arg_count(cmd, ignoremonitoring_ARG)) ?
    546 					    DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
    547 
    548 	if (arg_count(cmd, available_ARG))
    549 		r = _vgchange_available(cmd, vg);
    550 
    551 	else if (arg_count(cmd, monitor_ARG))
    552 		r = _vgchange_monitoring(cmd, vg);
    553 
    554 	else if (arg_count(cmd, resizeable_ARG))
    555 		r = _vgchange_resizeable(cmd, vg);
    556 
    557 	else if (arg_count(cmd, logicalvolume_ARG))
    558 		r = _vgchange_logicalvolume(cmd, vg);
    559 
    560 	else if (arg_count(cmd, maxphysicalvolumes_ARG))
    561 		r = _vgchange_physicalvolumes(cmd, vg);
    562 
    563 	else if (arg_count(cmd, addtag_ARG))
    564 		r = _vgchange_tag(cmd, vg, addtag_ARG);
    565 
    566 	else if (arg_count(cmd, deltag_ARG))
    567 		r = _vgchange_tag(cmd, vg, deltag_ARG);
    568 
    569 	else if (arg_count(cmd, physicalextentsize_ARG))
    570 		r = _vgchange_pesize(cmd, vg);
    571 
    572 	else if (arg_count(cmd, uuid_ARG))
    573 		r = _vgchange_uuid(cmd, vg);
    574 
    575 	else if (arg_count(cmd, alloc_ARG))
    576 		r = _vgchange_alloc(cmd, vg);
    577 
    578 	else if (arg_count(cmd, clustered_ARG))
    579 		r = _vgchange_clustered(cmd, vg);
    580 
    581 	return r;
    582 }
    583 
    584 int vgchange(struct cmd_context *cmd, int argc, char **argv)
    585 {
    586 	if (!
    587 	    (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
    588 	     arg_count(cmd, maxphysicalvolumes_ARG) +
    589 	     arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
    590 	     arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
    591 	     arg_count(cmd, physicalextentsize_ARG) +
    592 	     arg_count(cmd, clustered_ARG) + arg_count(cmd, alloc_ARG) +
    593 	     arg_count(cmd, monitor_ARG))) {
    594 		log_error("One of -a, -c, -l, -p, -s, -x, --uuid, --alloc, "
    595 			  "--addtag or --deltag required");
    596 		return EINVALID_CMD_LINE;
    597 	}
    598 
    599 	/* FIXME Cope with several changes at once! */
    600 	if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
    601 	    arg_count(cmd, maxphysicalvolumes_ARG) +
    602 	    arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
    603 	    arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
    604 	    arg_count(cmd, uuid_ARG) + arg_count(cmd, clustered_ARG) +
    605 	    arg_count(cmd, physicalextentsize_ARG) > 1) {
    606 		log_error("Only one of -a, -c, -l, -p, -s, -x, --uuid, "
    607 			  "--alloc, --addtag or --deltag allowed");
    608 		return EINVALID_CMD_LINE;
    609 	}
    610 
    611 	if (arg_count(cmd, ignorelockingfailure_ARG) &&
    612 	    !arg_count(cmd, available_ARG)) {
    613 		log_error("--ignorelockingfailure only available with -a");
    614 		return EINVALID_CMD_LINE;
    615 	}
    616 
    617 	if (arg_count(cmd, available_ARG) == 1
    618 	    && arg_count(cmd, autobackup_ARG)) {
    619 		log_error("-A option not necessary with -a option");
    620 		return EINVALID_CMD_LINE;
    621 	}
    622 
    623 	return process_each_vg(cmd, argc, argv,
    624 			       (arg_count(cmd, available_ARG)) ?
    625 			       LCK_VG_READ : LCK_VG_WRITE, 0, NULL,
    626 			       &vgchange_single);
    627 }
    628