Example #1
0
/* Allow /dev/vgname/lvname, vgname/lvname or lvname */
static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
				   const char *arg)
{
	const char *lvname;

	/* Is an lvname supplied directly? */
	if (!strchr(arg, '/'))
		return arg;

	lvname = skip_dev_dir(cmd, arg, NULL);
	while (*lvname == '/')
		lvname++;
	if (!strchr(lvname, '/')) {
		log_error("--name takes a logical volume name");
		return NULL;
	}
	if (strncmp(vgname, lvname, strlen(vgname)) ||
	    (lvname += strlen(vgname), *lvname != '/')) {
		log_error("Named LV and old PV must be in the same VG");
		return NULL;
	}
	while (*lvname == '/')
		lvname++;
	if (!*lvname) {
		log_error("Incomplete LV name supplied with --name");
		return NULL;
	}
	return lvname;
}
Example #2
0
int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
{
	const char *vg_name = NULL;

	if (argc == 1) {
		vg_name = skip_dev_dir(cmd, argv[0], NULL);
		if (!validate_name(vg_name)) {
			log_error("Volume group name \"%s\" is invalid", vg_name);
			return ECMD_FAILED;
		}
	} else if (!(arg_count(cmd, list_ARG) && arg_count(cmd, file_ARG))) {
		log_error("Please specify a *single* volume group to restore.");
		return ECMD_FAILED;
	}

	/*
	 * FIXME: overloading the -l arg for now to display a
	 * list of archive files for a particular vg
	 */
	if (arg_count(cmd, list_ARG)) {
		if (!(arg_count(cmd,file_ARG) ?
			    archive_display_file(cmd,
				arg_str_value(cmd, file_ARG, "")) :
			    archive_display(cmd, vg_name))) {
			stack;
			return ECMD_FAILED;
		}
		return ECMD_PROCESSED;
	}

	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
		log_error("Unable to lock volume group %s", vg_name);
		return ECMD_FAILED;
	}

	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
		log_error("Unable to lock orphans");
		unlock_vg(cmd, vg_name);
		return ECMD_FAILED;
	}

	cmd->handles_unknown_segments = 1;

	if (!(arg_count(cmd, file_ARG) ?
	      backup_restore_from_file(cmd, vg_name,
				       arg_str_value(cmd, file_ARG, "")) :
	      backup_restore(cmd, vg_name))) {
		unlock_vg(cmd, VG_ORPHANS);
		unlock_vg(cmd, vg_name);
		log_error("Restore failed.");
		return ECMD_FAILED;
	}

	log_print("Restored volume group %s", vg_name);

	unlock_vg(cmd, VG_ORPHANS);
	unlock_vg(cmd, vg_name);
	return ECMD_PROCESSED;
}
Example #3
0
static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
			  const char *new_vg_path)
{
	char *dev_dir;
	struct id id;
	int match = 0;
	int found_id = 0;
	struct dm_list *vgids;
	struct str_list *sl;
	const char *vg_name_new;
	const char *vgid = NULL, *vg_name, *vg_name_old;
	char old_path[NAME_LEN], new_path[NAME_LEN];
	struct volume_group *vg = NULL;
	int lock_vg_old_first = 1;

	vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL);
	vg_name_new = skip_dev_dir(cmd, new_vg_path, NULL);

	dev_dir = cmd->dev_dir;

	if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new))
		return_0;

	log_verbose("Checking for existing volume group \"%s\"", vg_name_old);

	/* Avoid duplicates */
	if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
		log_error("No complete volume groups found");
		return 0;
	}

	dm_list_iterate_items(sl, vgids) {
		vgid = sl->str;
		if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
			continue;
		if (!strcmp(vg_name, vg_name_old)) {
			if (match) {
				log_error("Found more than one VG called %s. "
					  "Please supply VG uuid.", vg_name_old);
				return 0;
			}
			match = 1;
		}
	}
Example #4
0
/*
 * lvrename command implementation.
 * Check arguments and call lv_rename() to execute the request.
 */
int lvrename(struct cmd_context *cmd, int argc, char **argv)
{
	size_t maxlen;
	char *lv_name_old, *lv_name_new;
	const char *vg_name, *vg_name_new, *vg_name_old;
	char *st;
	int r = ECMD_FAILED;

	struct volume_group *vg = NULL;
	struct lv_list *lvl;

	if (argc == 3) {
		vg_name = skip_dev_dir(cmd, argv[0], NULL);
		lv_name_old = argv[1];
		lv_name_new = argv[2];
		if (strchr(lv_name_old, '/') &&
		    (vg_name_old = extract_vgname(cmd, lv_name_old)) &&
		    strcmp(vg_name_old, vg_name)) {
			log_error("Please use a single volume group name "
				  "(\"%s\" or \"%s\")", vg_name, vg_name_old);
			return EINVALID_CMD_LINE;
		}
	} else if (argc == 2) {
		lv_name_old = argv[0];
		lv_name_new = argv[1];
		vg_name = extract_vgname(cmd, lv_name_old);
	} else {
		log_error("Old and new logical volume names required");
		return EINVALID_CMD_LINE;
	}

	if (!validate_name(vg_name)) {
		log_error("Please provide a valid volume group name");
		return EINVALID_CMD_LINE;
	}

	if (strchr(lv_name_new, '/') &&
	    (vg_name_new = extract_vgname(cmd, lv_name_new)) &&
	    strcmp(vg_name, vg_name_new)) {
		log_error("Logical volume names must "
			  "have the same volume group (\"%s\" or \"%s\")",
			  vg_name, vg_name_new);
		return EINVALID_CMD_LINE;
	}

	if ((st = strrchr(lv_name_old, '/')))
		lv_name_old = st + 1;

	if ((st = strrchr(lv_name_new, '/')))
		lv_name_new = st + 1;

	/* Check sanity of new name */
	maxlen = NAME_LEN - strlen(vg_name) - strlen(cmd->dev_dir) - 3;
	if (strlen(lv_name_new) > maxlen) {
		log_error("New logical volume path exceeds maximum length "
			  "of %" PRIsize_t "!", maxlen);
		return ECMD_FAILED;
	}

	if (!*lv_name_new) {
		log_error("New logical volume name may not be blank");
		return ECMD_FAILED;
	}

	if (!apply_lvname_restrictions(lv_name_new)) {
		stack;
		return ECMD_FAILED;
	}

	if (!validate_name(lv_name_new)) {
		log_error("New logical volume name \"%s\" is invalid",
		     lv_name_new);
		return EINVALID_CMD_LINE;
	}

	if (!strcmp(lv_name_old, lv_name_new)) {
		log_error("Old and new logical volume names must differ");
		return EINVALID_CMD_LINE;
	}

	log_verbose("Checking for existing volume group \"%s\"", vg_name);
	vg = vg_read_for_update(cmd, vg_name, NULL, 0);
	if (vg_read_error(vg)) {
		release_vg(vg);
		stack;
		return ECMD_FAILED;
	}

	if (!(lvl = find_lv_in_vg(vg, lv_name_old))) {
		log_error("Existing logical volume \"%s\" not found in "
			  "volume group \"%s\"", lv_name_old, vg_name);
		goto error;
	}

	if (!lv_rename(cmd, lvl->lv, lv_name_new))
		goto error;

	log_print("Renamed \"%s\" to \"%s\" in volume group \"%s\"",
		  lv_name_old, lv_name_new, vg_name);

	r = ECMD_PROCESSED;
error:
	unlock_and_release_vg(cmd, vg, vg_name);
	return r;
}
Example #5
0
int vgextend(struct cmd_context *cmd, int argc, char **argv)
{
	const char *vg_name;
	struct volume_group *vg = NULL;
	int r = ECMD_FAILED;
	struct pvcreate_params pp;
	int fixed = 0, i = 0;

	if (!argc) {
		log_error("Please enter volume group name and "
			  "physical volume(s)");
		return EINVALID_CMD_LINE;
	}

	vg_name = skip_dev_dir(cmd, argv[0], NULL);
	argc--;
	argv++;

	if (arg_count(cmd, metadatacopies_ARG)) {
		log_error("Invalid option --metadatacopies, "
			  "use --pvmetadatacopies instead.");
		return EINVALID_CMD_LINE;
	}
	pvcreate_params_set_defaults(&pp);
	if (!pvcreate_params_validate(cmd, argc, argv, &pp)) {
		return EINVALID_CMD_LINE;
	}

	/*
	 * It is always ok to add new PVs to a VG - even if there are
	 * missing PVs.  No LVs are affected by this operation, but
	 * repair processes - particularly for RAID segtypes - can
	 * be facilitated.
	 */
	cmd->handles_missing_pvs = 1;

	log_verbose("Checking for volume group \"%s\"", vg_name);
	vg = vg_read_for_update(cmd, vg_name, NULL, 0);
	if (vg_read_error(vg)) {
		release_vg(vg);
		return_ECMD_FAILED;
	}

	if (!archive(vg))
		goto_bad;

	if (arg_count(cmd, restoremissing_ARG)) {
		for (i = 0; i < argc; ++i) {
			if (_restore_pv(vg, argv[i]))
				++ fixed;
		}
		if (!fixed) {
			log_error("No PV has been restored.");
			goto bad;
		}
	} else { /* no --restore, normal vgextend */
		if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) {
			log_error("Can't get lock for orphan PVs");
			unlock_and_release_vg(cmd, vg, vg_name);
			return ECMD_FAILED;
		}

		if (arg_count(cmd, metadataignore_ARG) &&
		    (vg_mda_copies(vg) != VGMETADATACOPIES_UNMANAGED) &&
		    (pp.force == PROMPT) &&
		    yes_no_prompt("Override preferred number of copies "
			  "of VG %s metadata? [y/n]: ",
				  vg_name) == 'n') {
			log_error("Volume group %s not changed", vg_name);
			goto bad;
		}

		/* extend vg */
		if (!vg_extend(vg, argc, (const char* const*)argv, &pp))
			goto_bad;

		if (arg_count(cmd, metadataignore_ARG) &&
		    (vg_mda_copies(vg) != VGMETADATACOPIES_UNMANAGED) &&
		    (vg_mda_copies(vg) != vg_mda_used_count(vg))) {
			log_warn("WARNING: Changing preferred number of copies of VG %s "
			 "metadata from %"PRIu32" to %"PRIu32, vg_name,
				 vg_mda_copies(vg), vg_mda_used_count(vg));
			vg_set_mda_copies(vg, vg_mda_used_count(vg));
		}

		/* ret > 0 */
		log_verbose("Volume group \"%s\" will be extended by %d new "
			    "physical volumes", vg_name, argc);
	}

	/* store vg on disk(s) */
	if (!vg_write(vg) || !vg_commit(vg))
		goto_bad;

	backup(vg);
	log_print_unless_silent("Volume group \"%s\" successfully extended", vg_name);
	r = ECMD_PROCESSED;

bad:
	if (!arg_count(cmd, restoremissing_ARG))
		unlock_vg(cmd, VG_ORPHANS);
	unlock_and_release_vg(cmd, vg, vg_name);
	return r;
}
Example #6
0
static int _lvcreate_name_params(struct lvcreate_params *lp,
				 struct cmd_context *cmd,
				 int *pargc, char ***pargv)
{
	int argc = *pargc;
	char **argv = *pargv, *ptr;
	const char *vg_name;

	lp->pool = arg_str_value(cmd, thinpool_ARG, NULL);

	/* If --thinpool contains VG name, extract it. */
	if (lp->pool && strchr(lp->pool, '/')) {
		if (!(lp->vg_name = extract_vgname(cmd, lp->pool)))
			return 0;
		/* Strip VG from pool */
		if ((ptr = strrchr(lp->pool, (int) '/')))
			lp->pool = ptr + 1;
	}

	lp->lv_name = arg_str_value(cmd, name_ARG, NULL);

	/* If --name contains VG name, extract it. */
	if (lp->lv_name && strchr(lp->lv_name, '/')) {
		if (!_set_vg_name(lp, extract_vgname(cmd, lp->lv_name)))
			return_0;

		/* Strip VG from lv_name */
		if ((ptr = strrchr(lp->lv_name, (int) '/')))
			lp->lv_name = ptr + 1;
	}

	/* Need an origin? */
	if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
		/* argv[0] might be origin or vg/origin */
		if (!argc) {
			log_error("Please specify a logical volume to act as "
				  "the snapshot origin.");
			return 0;
		}

		lp->origin = skip_dev_dir(cmd, argv[0], NULL);
		if (strrchr(lp->origin, '/')) {
			if (!_set_vg_name(lp, extract_vgname(cmd, lp->origin)))
				return_0;

			/* Strip the volume group from the origin */
			if ((ptr = strrchr(lp->origin, (int) '/')))
				lp->origin = ptr + 1;
		}

		if (!lp->vg_name &&
		    !_set_vg_name(lp, extract_vgname(cmd, NULL)))
			return_0;

		if (!lp->vg_name) {
			log_error("The origin name should include the "
				  "volume group.");
			return 0;
		}

		(*pargv)++, (*pargc)--;
	} else if (seg_is_thin(lp) && !lp->pool && argc) {
		/* argv[0] might be vg or vg/Pool */

		vg_name = skip_dev_dir(cmd, argv[0], NULL);
		if (!strrchr(vg_name, '/')) {
			if (!_set_vg_name(lp, vg_name))
				return_0;
		} else {
			lp->pool = vg_name;
			if (!_set_vg_name(lp, extract_vgname(cmd, lp->pool)))
				return_0;

			if (!lp->vg_name &&
			    !_set_vg_name(lp, extract_vgname(cmd, NULL)))
				return_0;

			if (!lp->vg_name) {
				log_error("The pool name should include the "
					  "volume group.");
				return 0;
			}

			/* Strip the volume group */
			if ((ptr = strrchr(lp->pool, (int) '/')))
				lp->pool = ptr + 1;
		}

		(*pargv)++, (*pargc)--;
	} else {
		/*
		 * If VG not on command line, try environment default.
		 */
		if (!argc) {
			if (!lp->vg_name && !(lp->vg_name = extract_vgname(cmd, NULL))) {
				log_error("Please provide a volume group name");
				return 0;
			}
		} else {
			vg_name = skip_dev_dir(cmd, argv[0], NULL);
			if (strrchr(vg_name, '/')) {
				log_error("Volume group name expected "
					  "(no slash)");
				return 0;
			}

			if (!_set_vg_name(lp, vg_name))
				return_0;

			(*pargv)++, (*pargc)--;
		}
	}

	if (!validate_name(lp->vg_name)) {
		log_error("Volume group name %s has invalid characters",
			  lp->vg_name);
		return 0;
	}

	if (lp->lv_name) {
		if (!apply_lvname_restrictions(lp->lv_name))
			return_0;

		if (!validate_name(lp->lv_name)) {
			log_error("Logical volume name \"%s\" is invalid",
				  lp->lv_name);
			return 0;
		}
	}

	if (lp->pool) {
		if (!apply_lvname_restrictions(lp->pool))
			return_0;

		if (!validate_name(lp->pool)) {
			log_error("Logical volume name \"%s\" is invalid",
				  lp->pool);
			return 0;
		}

		if (lp->lv_name && !strcmp(lp->lv_name, lp->pool)) {
			log_error("Logical volume name %s and pool name %s must be different.", 
				  lp->lv_name, lp->pool);
			return 0;
		}
	}

	return 1;
}
Example #7
0
int vgrename(struct cmd_context *cmd, int argc, char **argv)
{
	struct vgrename_params vp = { 0 };
	struct processing_handle *handle;
	const char *vg_name_new;
	const char *vg_name_old;
	struct id id;
	int ret;

	if (argc != 2) {
		log_error("Old and new volume group names need specifying");
		return EINVALID_CMD_LINE;
	}

	vg_name_old = skip_dev_dir(cmd, argv[0], NULL);
	vg_name_new = skip_dev_dir(cmd, argv[1], NULL);

	if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new))
		return_0;

	if (!(vp.vg_name_old = dm_pool_strdup(cmd->mem, vg_name_old)))
		return_ECMD_FAILED;

	if (!(vp.vg_name_new = dm_pool_strdup(cmd->mem, vg_name_new)))
		return_ECMD_FAILED;

	/* Needed change the global VG namespace. */
	if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES))
		return_ECMD_FAILED;

	/*
	 * Special case where vg_name_old may be a UUID:
	 * If vg_name_old is a UUID, then process_each may
	 * translate it to an actual VG name that we don't
	 * yet know.  The lock ordering, and pre-locking,
	 * needs to be done based on VG names.  When
	 * vg_name_old is a UUID, do not do any pre-locking
	 * based on it, since it's likely to be wrong, and
	 * defer all the locking to the _single function.
	 *
	 * When it's not a UUID, we know the two VG names,
	 * and we can pre-lock the new VG name if the lock
	 * ordering wants it locked before the old VG name
	 * which will be locked by process_each.  If lock
	 * ordering wants the old name locked first, then
	 * the _single function will lock the new VG name.
	 */
	if (!(vp.old_name_is_uuid = id_read_format_try(&id, vg_name_old))) {
		if (strcmp(vg_name_new, vg_name_old) < 0) {
			vp.lock_vg_old_first = 0;
			vp.unlock_new_name = 1;

			if (!_lock_new_vg_for_rename(cmd, vg_name_new))
				return ECMD_FAILED;
		} else {
			/* The old VG is locked by process_each_vg. */
			vp.lock_vg_old_first = 1;
		}
	}

	if (!(handle = init_processing_handle(cmd))) {
		log_error("Failed to initialize processing handle.");
		return ECMD_FAILED;
	}

	handle->custom_handle = &vp;

	ret = process_each_vg(cmd, 0, NULL, vg_name_old,
			      READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
			      handle, _vgrename_single);

	/* Needed if process_each_vg returns error before calling _single. */
	if (vp.unlock_new_name)
		unlock_vg(cmd, vg_name_new);

	destroy_processing_handle(cmd, handle);
	return ret;
}
Example #8
0
int vgextend(struct cmd_context *cmd, int argc, char **argv)
{
	char *vg_name;
	struct volume_group *vg = NULL;
	int r = ECMD_FAILED;
	struct pvcreate_params pp;

	if (!argc) {
		log_error("Please enter volume group name and "
			  "physical volume(s)");
		return EINVALID_CMD_LINE;
	}

	vg_name = skip_dev_dir(cmd, argv[0], NULL);
	argc--;
	argv++;

	if (arg_count(cmd, metadatacopies_ARG)) {
		log_error("Invalid option --metadatacopies, "
			  "use --pvmetadatacopies instead.");
		return EINVALID_CMD_LINE;
	}
	pvcreate_params_set_defaults(&pp);
	if (!pvcreate_params_validate(cmd, argc, argv, &pp)) {
		return EINVALID_CMD_LINE;
	}

	log_verbose("Checking for volume group \"%s\"", vg_name);
	vg = vg_read_for_update(cmd, vg_name, NULL, 0);
	if (vg_read_error(vg)) {
		vg_release(vg);
		stack;
		return ECMD_FAILED;
	}

	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
		log_error("Can't get lock for orphan PVs");
		unlock_and_release_vg(cmd, vg, vg_name);
		return ECMD_FAILED;
	}

	if (!archive(vg))
		goto_bad;

	/* extend vg */
	if (!vg_extend(vg, argc, argv, &pp))
		goto_bad;

	/* ret > 0 */
	log_verbose("Volume group \"%s\" will be extended by %d new "
		    "physical volumes", vg_name, argc);

	/* store vg on disk(s) */
	if (!vg_write(vg) || !vg_commit(vg))
		goto_bad;

	backup(vg);
	log_print("Volume group \"%s\" successfully extended", vg_name);
	r = ECMD_PROCESSED;

bad:
	unlock_vg(cmd, VG_ORPHANS);
	unlock_and_release_vg(cmd, vg, vg_name);
	return r;
}
Example #9
0
int vgcreate(struct cmd_context *cmd, int argc, char **argv)
{
    size_t max_lv, max_pv;
    uint32_t extent_size;
    char *vg_name;
    struct volume_group *vg;
    const char *tag;
    alloc_policy_t alloc;
    int clustered;

    if (!argc) {
        log_error("Please provide volume group name and "
                  "physical volumes");
        return EINVALID_CMD_LINE;
    }

    if (argc == 1) {
        log_error("Please enter physical volume name(s)");
        return EINVALID_CMD_LINE;
    }

    vg_name = skip_dev_dir(cmd, argv[0], NULL);
    max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG, 0);
    max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
    alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);

    if (alloc == ALLOC_INHERIT) {
        log_error("Volume Group allocation policy cannot inherit "
                  "from anything");
        return EINVALID_CMD_LINE;
    }

    if (!(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
        if (!max_lv)
            max_lv = 255;
        if (!max_pv)
            max_pv = 255;
        if (max_lv > 255 || max_pv > 255) {
            log_error("Number of volumes may not exceed 255");
            return EINVALID_CMD_LINE;
        }
    }

    if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
        log_error("Physical extent size may not be negative");
        return EINVALID_CMD_LINE;
    }

    if (arg_sign_value(cmd, maxlogicalvolumes_ARG, 0) == SIGN_MINUS) {
        log_error("Max Logical Volumes may not be negative");
        return EINVALID_CMD_LINE;
    }

    if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
        log_error("Max Physical Volumes may not be negative");
        return EINVALID_CMD_LINE;
    }

    /* Units of 512-byte sectors */
    extent_size =
        arg_uint_value(cmd, physicalextentsize_ARG, DEFAULT_EXTENT) * 2;

    if (!extent_size) {
        log_error("Physical extent size may not be zero");
        return EINVALID_CMD_LINE;
    }

    if (!validate_vg_name(cmd, vg_name)) {
        log_error("New volume group name \"%s\" is invalid", vg_name);
        return ECMD_FAILED;
    }

    /* Create the new VG */
    if (!(vg = vg_create(cmd, vg_name, extent_size, max_pv, max_lv, alloc,
                         argc - 1, argv + 1)))
        return ECMD_FAILED;

    if (max_lv != vg->max_lv)
        log_warn("WARNING: Setting maxlogicalvolumes to %d "
                 "(0 means unlimited)", vg->max_lv);

    if (max_pv != vg->max_pv)
        log_warn("WARNING: Setting maxphysicalvolumes to %d "
                 "(0 means unlimited)", vg->max_pv);

    if (arg_count(cmd, addtag_ARG)) {
        if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
            log_error("Failed to get tag");
            return ECMD_FAILED;
        }

        if (!(vg->fid->fmt->features & FMT_TAGS)) {
            log_error("Volume group format does not support tags");
            return ECMD_FAILED;
        }

        if (!str_list_add(cmd->mem, &vg->tags, tag)) {
            log_error("Failed to add tag %s to volume group %s",
                      tag, vg_name);
            return ECMD_FAILED;
        }
    }

    if (arg_count(cmd, clustered_ARG))
        clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
    else
        /* Default depends on current locking type */
        clustered = locking_is_clustered();

    if (clustered)
        vg->status |= CLUSTERED;
    else
        vg->status &= ~CLUSTERED;

    if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
        log_error("Can't get lock for orphan PVs");
        return ECMD_FAILED;
    }

    if (!lock_vol(cmd, vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
        log_error("Can't get lock for %s", vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    if (!archive(vg)) {
        unlock_vg(cmd, vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    /* Store VG on disk(s) */
    if (!vg_write(vg) || !vg_commit(vg)) {
        unlock_vg(cmd, vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    unlock_vg(cmd, vg_name);
    unlock_vg(cmd, ORPHAN);

    backup(vg);

    log_print("Volume group \"%s\" successfully created", vg->name);

    return ECMD_PROCESSED;
}
Example #10
0
static int _lvcreate_name_params(struct lvcreate_params *lp,
				 struct cmd_context *cmd,
				 int *pargc, char ***pargv)
{
	int argc = *pargc;
	char **argv = *pargv, *ptr;
	char *vg_name;

	lp->lv_name = arg_str_value(cmd, name_ARG, NULL);

	if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
		if (!argc) {
			log_error("Please specify a logical volume to act as "
				  "the snapshot origin.");
			return 0;
		}

		lp->origin = argv[0];
		(*pargv)++, (*pargc)--;
		if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
			log_error("The origin name should include the "
				  "volume group.");
			return 0;
		}

		/* Strip the volume group from the origin */
		if ((ptr = strrchr(lp->origin, (int) '/')))
			lp->origin = ptr + 1;

	} else {
		/*
		 * If VG not on command line, try -n arg and then
		 * environment.
		 */
		if (!argc) {
			if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
				log_error("Please provide a volume group name");
				return 0;
			}

		} else {
			vg_name = skip_dev_dir(cmd, argv[0], NULL);
			if (strrchr(vg_name, '/')) {
				log_error("Volume group name expected "
					  "(no slash)");
				return 0;
			}

			/*
			 * Ensure lv_name doesn't contain a
			 * different VG.
			 */
			if (lp->lv_name && strchr(lp->lv_name, '/')) {
				if (!(lp->vg_name =
				      extract_vgname(cmd, lp->lv_name)))
					return 0;

				if (strcmp(lp->vg_name, vg_name)) {
					log_error("Inconsistent volume group "
						  "names "
						  "given: \"%s\" and \"%s\"",
						  lp->vg_name, vg_name);
					return 0;
				}
			}

			lp->vg_name = vg_name;
			(*pargv)++, (*pargc)--;
		}
	}

	if (!validate_name(lp->vg_name)) {
		log_error("Volume group name %s has invalid characters",
			  lp->vg_name);
		return 0;
	}

	if (lp->lv_name) {
		if ((ptr = strrchr(lp->lv_name, '/')))
			lp->lv_name = ptr + 1;

		if (!apply_lvname_restrictions(lp->lv_name))
			return_0;

		if (!validate_name(lp->lv_name)) {
			log_error("Logical volume name \"%s\" is invalid",
				  lp->lv_name);
			return 0;
		}
	}

	return 1;
}