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; }
static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg, struct pv_segment *pvseg, void *handle) { int consistent = 0; struct physical_volume *pv = pvseg->pv; int ret = ECMD_PROCESSED; if (!lock_vol(cmd, pv_vg_name(pv), LCK_VG_READ)) { log_error("Can't lock %s: skipping", pv_vg_name(pv)); return ECMD_FAILED; } if (!(vg = vg_read(cmd, pv_vg_name(pv), NULL, &consistent))) { log_error("Can't read %s: skipping", pv_vg_name(pv)); goto out; } if (!vg_check_status(vg, CLUSTERED)) { ret = ECMD_FAILED; goto out; } if (!report_object(handle, vg, NULL, pv, NULL, pvseg)) ret = ECMD_FAILED; out: unlock_vg(cmd, pv_vg_name(pv)); return ret; }
static int _lock_new_vg_for_rename(struct cmd_context *cmd, const char *vg_name_new) { if (!lock_vol(cmd, vg_name_new, LCK_VG_WRITE, NULL)) { log_error("Can't get lock for %s", vg_name_new); return 0; } return 1; }
static int pvremove_single(struct cmd_context *cmd, const char *pv_name, void *handle) // __attribute((unused))) { struct device *dev; if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); return ECMD_FAILED; } if (!pvremove_check(cmd, pv_name)) goto error; if (!(dev = dev_cache_get(pv_name, cmd->filter))) { log_error("%s: Couldn't find device. Check your filters?", pv_name); goto error; } if (!dev_test_excl(dev)) { log_error("Can't open %s exclusively - not removing. " "Mounted filesystem?", dev_name(dev)); goto error; } /* Wipe existing label(s) */ if (!label_remove(dev)) { log_error("Failed to wipe existing label(s) on %s", pv_name); goto error; } log_print("Labels on physical volume \"%s\" successfully wiped", pv_name); unlock_vg(cmd, ORPHAN); return ECMD_PROCESSED; error: unlock_vg(cmd, ORPHAN); return ECMD_FAILED; }
int pvcreate(struct cmd_context *cmd, int argc, char **argv) { int i; int ret = ECMD_PROCESSED; struct pvcreate_params pp; struct physical_volume *pv; pvcreate_params_set_defaults(&pp); if (!pvcreate_restore_params_validate(cmd, argc, argv, &pp)) { return EINVALID_CMD_LINE; } if (!pvcreate_params_validate(cmd, argc, argv, &pp)) { return EINVALID_CMD_LINE; } for (i = 0; i < argc; i++) { if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); return ECMD_FAILED; } dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); if (!(pv = pvcreate_single(cmd, argv[i], &pp, 1))) { stack; ret = ECMD_FAILED; } unlock_vg(cmd, VG_ORPHANS); if (sigint_caught()) return ret; } return ret; }
static int _pv_resize_single(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv, const uint64_t new_size) { struct pv_list *pvl; uint64_t size = 0; uint32_t new_pe_count = 0; int r = 0; struct dm_list mdas; const char *pv_name = pv_dev_name(pv); const char *vg_name; struct lvmcache_info *info; int mda_count = 0; struct volume_group *old_vg = vg; dm_list_init(&mdas); if (is_orphan_vg(pv_vg_name(pv))) { vg_name = VG_ORPHANS; if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) { log_error("Can't get lock for orphans"); return 0; } if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) { unlock_vg(cmd, vg_name); log_error("Unable to read PV \"%s\"", pv_name); return 0; } mda_count = dm_list_size(&mdas); } else { vg_name = pv_vg_name(pv); vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) goto bad; if (!(pvl = find_pv_in_vg(vg, pv_name))) { log_error("Unable to find \"%s\" in volume group \"%s\"", pv_name, vg->name); goto bad; } pv = pvl->pv; if (!(info = info_from_pvid(pv->dev->pvid, 0))) { log_error("Can't get info for PV %s in volume group %s", pv_name, vg->name); goto bad; } mda_count = dm_list_size(&info->mdas); if (!archive(vg)) goto bad; } /* FIXME Create function to test compatibility properly */ if (mda_count > 1) { log_error("%s: too many metadata areas for pvresize", pv_name); goto bad; } if (!(pv->fmt->features & FMT_RESIZE_PV)) { log_error("Physical volume %s format does not support resizing.", pv_name); goto bad; } /* Get new size */ if (!dev_get_size(pv_dev(pv), &size)) { log_error("%s: Couldn't get size.", pv_name); goto bad; } if (new_size) { if (new_size > size) log_warn("WARNING: %s: Overriding real size. " "You could lose data.", pv_name); log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64 " sectors.", pv_name, new_size, pv_size(pv)); size = new_size; } if (size < PV_MIN_SIZE) { log_error("%s: Size must exceed minimum of %ld sectors.", pv_name, PV_MIN_SIZE); goto bad; } if (size < pv_pe_start(pv)) { log_error("%s: Size must exceed physical extent start of " "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv)); goto bad; } pv->size = size; if (vg) { pv->size -= pv_pe_start(pv); new_pe_count = pv_size(pv) / vg->extent_size; if (!new_pe_count) { log_error("%s: Size must leave space for at " "least one physical extent of " "%" PRIu32 " sectors.", pv_name, pv_pe_size(pv)); goto bad; } if (!pv_resize(pv, vg, new_pe_count)) goto_bad; } log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.", pv_name, pv_size(pv)); log_verbose("Updating physical volume \"%s\"", pv_name); if (!is_orphan_vg(pv_vg_name(pv))) { if (!vg_write(vg) || !vg_commit(vg)) { log_error("Failed to store physical volume \"%s\" in " "volume group \"%s\"", pv_name, vg->name); goto bad; } backup(vg); } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) { log_error("Failed to store physical volume \"%s\"", pv_name); goto bad;; } log_print("Physical volume \"%s\" changed", pv_name); r = 1; bad: unlock_vg(cmd, vg_name); if (!old_vg) vg_release(vg); return r; }
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; }
/* * See if we may pvcreate on this device. * 0 indicates we may not. */ static int pvcreate_check(struct cmd_context *cmd, const char *name) { struct physical_volume *pv; struct device *dev; uint64_t md_superblock; /* is the partition type set correctly ? */ if ((arg_count(cmd, force_ARG) < 1) && !is_lvm_partition(name)) { log_error("%s: Not LVM partition type: use -f to override", name); return 0; } /* Is there a pv here already? */ /* FIXME Use partial mode here? */ pv = pv_read(cmd, name, NULL, NULL, 0); /* Allow partial & exported VGs to be destroyed. */ /* We must have -ff to overwrite a non orphan */ if (pv && !is_orphan(pv) && arg_count(cmd, force_ARG) != 2) { log_error("Can't initialize physical volume \"%s\" of " "volume group \"%s\" without -ff", name, pv_vg_name(pv)); return 0; } /* prompt */ if (pv && !is_orphan(pv) && !arg_count(cmd, yes_ARG) && yes_no_prompt(_really_init, name, pv_vg_name(pv)) == 'n') { log_print("%s: physical volume not initialized", name); return 0; } if (sigint_caught()) return 0; dev = dev_cache_get(name, cmd->filter); /* Is there an md superblock here? */ if (!dev && md_filtering()) { unlock_vg(cmd, ORPHAN); persistent_filter_wipe(cmd->filter); lvmcache_destroy(); init_md_filtering(0); if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); init_md_filtering(1); return 0; } dev = dev_cache_get(name, cmd->filter); init_md_filtering(1); } if (!dev) { log_error("Device %s not found (or ignored by filtering).", name); return 0; } if (!dev_test_excl(dev)) { log_error("Can't open %s exclusively. Mounted filesystem?", name); return 0; } /* Wipe superblock? */ if (dev_is_md(dev, &md_superblock) && ((!arg_count(cmd, uuidstr_ARG) && !arg_count(cmd, restorefile_ARG)) || arg_count(cmd, yes_ARG) || (yes_no_prompt("Software RAID md superblock " "detected on %s. Wipe it? [y/n] ", name) == 'y'))) { log_print("Wiping software RAID md superblock on %s", name); if (!dev_set(dev, md_superblock, 4, 0)) { log_error("Failed to wipe RAID md superblock on %s", name); return 0; } } if (sigint_caught()) return 0; if (pv && !is_orphan(pv) && arg_count(cmd, force_ARG)) { log_warn("WARNING: Forcing physical volume creation on " "%s%s%s%s", name, !is_orphan(pv) ? " of volume group \"" : "", !is_orphan(pv) ? pv_vg_name(pv) : "", !is_orphan(pv) ? "\"" : ""); } return 1; }
static int pvcreate_single(struct cmd_context *cmd, const char *pv_name, void *handle) { struct pvcreate_params *pp = (struct pvcreate_params *) handle; void *pv; void *existing_pv; struct id id, *idp = NULL; const char *uuid = NULL; uint64_t size = 0; struct device *dev; struct list mdas; int pvmetadatacopies; uint64_t pvmetadatasize; struct volume_group *vg; const char *restorefile; uint64_t pe_start = 0; uint32_t extent_count = 0, extent_size = 0; if (arg_count(cmd, uuidstr_ARG)) { uuid = arg_str_value(cmd, uuidstr_ARG, ""); if (!id_read_format(&id, uuid)) return EINVALID_CMD_LINE; if ((dev = device_from_pvid(cmd, &id)) && (dev != dev_cache_get(pv_name, cmd->filter))) { log_error("uuid %s already in use on \"%s\"", uuid, dev_name(dev)); return ECMD_FAILED; } idp = &id; } if (arg_count(cmd, restorefile_ARG)) { restorefile = arg_str_value(cmd, restorefile_ARG, ""); /* The uuid won't already exist */ init_partial(1); if (!(vg = backup_read_vg(cmd, NULL, restorefile))) { log_error("Unable to read volume group from %s", restorefile); return ECMD_FAILED; } init_partial(0); if (!(existing_pv = find_pv_in_vg_by_uuid(vg, idp))) { log_error("Can't find uuid %s in backup file %s", uuid, restorefile); return ECMD_FAILED; } pe_start = pv_pe_start(existing_pv); extent_size = pv_pe_size(existing_pv); extent_count = pv_pe_count(existing_pv); } if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); return ECMD_FAILED; } if (!pvcreate_check(cmd, pv_name)) goto error; if (sigint_caught()) goto error; if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) { log_error("Physical volume size may not be negative"); goto error; } size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0)) * 2; if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) { log_error("Metadata size may not be negative"); goto error; } pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0)) * 2; if (!pvmetadatasize) pvmetadatasize = find_config_tree_int(cmd, "metadata/pvmetadatasize", DEFAULT_PVMETADATASIZE); pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1); if (pvmetadatacopies < 0) pvmetadatacopies = find_config_tree_int(cmd, "metadata/pvmetadatacopies", DEFAULT_PVMETADATACOPIES); if (!(dev = dev_cache_get(pv_name, cmd->filter))) { log_error("%s: Couldn't find device. Check your filters?", pv_name); goto error; } list_init(&mdas); if (!(pv = pv_create(cmd->fmt, dev, idp, size, pe_start, extent_count, extent_size, pvmetadatacopies, pvmetadatasize, &mdas))) { log_error("Failed to setup physical volume \"%s\"", pv_name); goto error; } log_verbose("Set up physical volume for \"%s\" with %" PRIu64 " available sectors", pv_name, pv_size(pv)); /* Wipe existing label first */ if (!label_remove(pv_dev(pv))) { log_error("Failed to wipe existing label on %s", pv_name); goto error; } if (pp->zero) { log_verbose("Zeroing start of device %s", pv_name); if (!dev_open_quiet(dev)) { log_error("%s not opened: device not zeroed", pv_name); goto error; } if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) { log_error("%s not wiped: aborting", pv_name); dev_close(dev); goto error; } dev_close(dev); } log_very_verbose("Writing physical volume data to disk \"%s\"", pv_name); if (!(pv_write(cmd, (struct physical_volume *)pv, &mdas, arg_int64_value(cmd, labelsector_ARG, DEFAULT_LABELSECTOR)))) { log_error("Failed to write physical volume \"%s\"", pv_name); goto error; } log_print("Physical volume \"%s\" successfully created", pv_name); unlock_vg(cmd, ORPHAN); return ECMD_PROCESSED; error: unlock_vg(cmd, ORPHAN); return ECMD_FAILED; }
int vgcreate(struct cmd_context *cmd, int argc, char **argv) { struct vgcreate_params vp_new; struct vgcreate_params vp_def; struct volume_group *vg; const char *tag; const char *clustered_message = ""; char *vg_name; struct pvcreate_params pp; if (!argc) { log_error("Please provide volume group name and " "physical volumes"); return EINVALID_CMD_LINE; } vg_name = argv[0]; argc--; argv++; pvcreate_params_set_defaults(&pp); if (!pvcreate_params_validate(cmd, argc, argv, &pp)) { return EINVALID_CMD_LINE; } vgcreate_params_set_defaults(&vp_def, NULL); vp_def.vg_name = vg_name; if (vgcreate_params_set_from_args(cmd, &vp_new, &vp_def)) return EINVALID_CMD_LINE; if (vgcreate_params_validate(cmd, &vp_new)) return EINVALID_CMD_LINE; /* Create the new VG */ vg = vg_create(cmd, vp_new.vg_name); if (vg_read_error(vg)) { if (vg_read_error(vg) == FAILED_EXIST) log_error("A volume group called %s already exists.", vp_new.vg_name); else log_error("Can't get lock for %s.", vp_new.vg_name); vg_release(vg); return ECMD_FAILED; } if (!vg_set_extent_size(vg, vp_new.extent_size) || !vg_set_max_lv(vg, vp_new.max_lv) || !vg_set_max_pv(vg, vp_new.max_pv) || !vg_set_alloc_policy(vg, vp_new.alloc) || !vg_set_clustered(vg, vp_new.clustered) || !vg_set_mda_copies(vg, vp_new.vgmetadatacopies)) goto bad_orphan; if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); goto bad_orphan; } /* attach the pv's */ if (!vg_extend(vg, argc, argv, &pp)) goto_bad; if (vp_new.max_lv != vg->max_lv) log_warn("WARNING: Setting maxlogicalvolumes to %d " "(0 means unlimited)", vg->max_lv); if (vp_new.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"); goto bad; } if (!vg_change_tag(vg, tag, 1)) goto_bad; } if (vg_is_clustered(vg)) { clustered_message = "Clustered "; } else { if (locking_is_clustered()) clustered_message = "Non-clustered "; } if (!archive(vg)) goto_bad; /* Store VG on disk(s) */ if (!vg_write(vg) || !vg_commit(vg)) goto_bad; unlock_vg(cmd, VG_ORPHANS); unlock_vg(cmd, vp_new.vg_name); backup(vg); log_print("%s%colume group \"%s\" successfully created", clustered_message, *clustered_message ? 'v' : 'V', vg->name); vg_release(vg); return ECMD_PROCESSED; bad: unlock_vg(cmd, VG_ORPHANS); bad_orphan: vg_release(vg); unlock_vg(cmd, vp_new.vg_name); return ECMD_FAILED; }
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; }
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; }