Exemple #1
0
static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv)
{
	int want_contiguous = 0;
	alloc_policy_t alloc;

	want_contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n");
	alloc = want_contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT;
	alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, alloc);

	if (alloc == lv->alloc) {
		log_error("Allocation policy of logical volume \"%s\" is "
			  "already %s", lv->name, get_alloc_string(alloc));
		return 0;
	}

	lv->alloc = alloc;

	/* FIXME If contiguous, check existing extents already are */

	log_verbose("Setting contiguous allocation policy for \"%s\" to %s",
		    lv->name, get_alloc_string(alloc));

	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);

	/* No need to suspend LV for this change */
	if (!vg_write(lv->vg) || !vg_commit(lv->vg))
		return_0;

	backup(lv->vg);

	return 1;
}
Exemple #2
0
static int _lvchange_activate(struct cmd_context *cmd, struct logical_volume *lv)
{
	int activate;

	activate = arg_uint_value(cmd, activate_ARG, 0);

	if (lv_is_cow(lv) && !lv_is_virtual_origin(origin_from_cow(lv)))
		lv = origin_from_cow(lv);

	if (activate == CHANGE_AAY) {
		if (!lv_passes_auto_activation_filter(cmd, lv))
			return 1;
		activate = CHANGE_ALY;
	}

	if (activate == CHANGE_ALN) {
		log_verbose("Deactivating logical volume \"%s\" locally",
			    lv->name);
		if (!deactivate_lv_local(cmd, lv))
			return_0;
	} else if (activate == CHANGE_AN) {
		log_verbose("Deactivating logical volume \"%s\"", lv->name);
		if (!deactivate_lv(cmd, lv))
			return_0;
	} else {
		if ((activate == CHANGE_AE) ||
		    lv_is_origin(lv) ||
		    lv_is_thin_type(lv)) {
			log_verbose("Activating logical volume \"%s\" "
				    "exclusively", lv->name);
			if (!activate_lv_excl(cmd, lv))
				return_0;
		} else if (activate == CHANGE_ALY) {
			log_verbose("Activating logical volume \"%s\" locally",
				    lv->name);
			if (!activate_lv_local(cmd, lv))
				return_0;
		} else {
			log_verbose("Activating logical volume \"%s\"",
				    lv->name);
			if (!activate_lv(cmd, lv))
				return_0;
		}

		if (background_polling())
			lv_spawn_background_polling(cmd, lv);
	}

	return 1;
}
Exemple #3
0
static int _read_size_params(struct lvcreate_params *lp,
			     struct lvcreate_cmdline_params *lcp,
			     struct cmd_context *cmd)
{
	if (arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG) != 1) {
		log_error("Please specify either size or extents (not both)");
		return 0;
	}

	if (arg_count(cmd, extents_ARG)) {
		if (arg_sign_value(cmd, extents_ARG, 0) == SIGN_MINUS) {
			log_error("Negative number of extents is invalid");
			return 0;
		}
		lp->extents = arg_uint_value(cmd, extents_ARG, 0);
		lcp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
	}

	/* Size returned in kilobyte units; held in sectors */
	if (arg_count(cmd, size_ARG)) {
		if (arg_sign_value(cmd, size_ARG, 0) == SIGN_MINUS) {
			log_error("Negative size is invalid");
			return 0;
		}
		lcp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
		lcp->percent = PERCENT_NONE;
	}

	/* Size returned in kilobyte units; held in sectors */
	if (arg_count(cmd, virtualsize_ARG)) {
		if (arg_sign_value(cmd, virtualsize_ARG, 0) == SIGN_MINUS) {
			log_error("Negative virtual origin size is invalid");
			return 0;
		}
		lp->voriginsize = arg_uint64_value(cmd, virtualsize_ARG,
						   UINT64_C(0));
		if (!lp->voriginsize) {
			log_error("Virtual origin size may not be zero");
			return 0;
		}
	}

	return 1;
}
Exemple #4
0
static int lvchange_availability(struct cmd_context *cmd,
				 struct logical_volume *lv)
{
	int activate;

	activate = arg_uint_value(cmd, available_ARG, 0);

	if (activate == CHANGE_ALN) {
		log_verbose("Deactivating logical volume \"%s\" locally",
			    lv->name);
		if (!deactivate_lv_local(cmd, lv))
			return_0;
	} else if (activate == CHANGE_AN) {
		log_verbose("Deactivating logical volume \"%s\"", lv->name);
		if (!deactivate_lv(cmd, lv))
			return_0;
	} else {
		if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
			log_verbose("Activating logical volume \"%s\" "
				    "exclusively", lv->name);
			if (!activate_lv_excl(cmd, lv))
				return_0;
		} else if (activate == CHANGE_ALY) {
			log_verbose("Activating logical volume \"%s\" locally",
				    lv->name);
			if (!activate_lv_local(cmd, lv))
				return_0;
		} else {
			log_verbose("Activating logical volume \"%s\"",
				    lv->name);
			if (!activate_lv(cmd, lv))
				return_0;
		}

		if (background_polling())
			lv_spawn_background_polling(cmd, lv);
	}

	return 1;
}
Exemple #5
0
static int lvchange_readahead(struct cmd_context *cmd,
			      struct logical_volume *lv)
{
	unsigned read_ahead = 0;
	unsigned pagesize = (unsigned) lvm_getpagesize() >> SECTOR_SHIFT;
	int r = 0;

	read_ahead = arg_uint_value(cmd, readahead_ARG, 0);

	if (read_ahead != DM_READ_AHEAD_AUTO &&
	    (lv->vg->fid->fmt->features & FMT_RESTRICTED_READAHEAD) &&
	    (read_ahead < 2 || read_ahead > 120)) {
		log_error("Metadata only supports readahead values between 2 and 120.");
		return 0;
	}

	if (read_ahead != DM_READ_AHEAD_AUTO &&
	    read_ahead != DM_READ_AHEAD_NONE && read_ahead % pagesize) {
		if (read_ahead < pagesize)
			read_ahead = pagesize;
		else
			read_ahead = (read_ahead / pagesize) * pagesize;
		log_warn("WARNING: Overriding readahead to %u sectors, a multiple "
			    "of %uK page size.", read_ahead, pagesize >> 1);
	}

	if (lv->read_ahead == read_ahead) {
		if (read_ahead == DM_READ_AHEAD_AUTO)
			log_error("Read ahead is already auto for \"%s\"", lv->name);
		else
			log_error("Read ahead is already %u for \"%s\"",
				  read_ahead, lv->name);
		return 0;
	}

	lv->read_ahead = read_ahead;

	log_verbose("Setting read ahead to %u for \"%s\"", read_ahead,
		    lv->name);

	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
	if (!vg_write(lv->vg))
		return_0;

	if (!suspend_lv(cmd, lv)) {
		log_error("Failed to lock %s", lv->name);
		vg_revert(lv->vg);
		goto out;
	}

	if (!vg_commit(lv->vg)) {
		if (!resume_lv(cmd, lv))
			stack;
		goto_out;
	}

	log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
	if (!resume_lv(cmd, lv)) {
		log_error("Problem reactivating %s", lv->name);
		goto out;
	}

	r = 1;
out:
	backup(lv->vg);
	return r;
}
Exemple #6
0
static int lvchange_permission(struct cmd_context *cmd,
			       struct logical_volume *lv)
{
	uint32_t lv_access;
	struct lvinfo info;
	int r = 0;

	lv_access = arg_uint_value(cmd, permission_ARG, 0);

	if ((lv_access & LVM_WRITE) && (lv->status & LVM_WRITE)) {
		log_error("Logical volume \"%s\" is already writable",
			  lv->name);
		return 0;
	}

	if (!(lv_access & LVM_WRITE) && !(lv->status & LVM_WRITE)) {
		log_error("Logical volume \"%s\" is already read only",
			  lv->name);
		return 0;
	}

	if ((lv->status & MIRRORED) && (vg_is_clustered(lv->vg)) &&
	    lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) {
		log_error("Cannot change permissions of mirror \"%s\" "
			  "while active.", lv->name);
		return 0;
	}

	/* Not allowed to change permissions on RAID sub-LVs directly */
	if ((lv->status & RAID_META) || (lv->status & RAID_IMAGE)) {
		log_error("Cannot change permissions of RAID %s \"%s\"",
			  (lv->status & RAID_IMAGE) ? "image" :
			  "metadata area", lv->name);
		return 0;
	}

	if (lv_access & LVM_WRITE) {
		lv->status |= LVM_WRITE;
		log_verbose("Setting logical volume \"%s\" read/write",
			    lv->name);
	} else {
		lv->status &= ~LVM_WRITE;
		log_verbose("Setting logical volume \"%s\" read-only",
			    lv->name);
	}

	log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
	if (!vg_write(lv->vg))
		return_0;

	if (!suspend_lv(cmd, lv)) {
		log_error("Failed to lock %s", lv->name);
		vg_revert(lv->vg);
		goto out;
	}

	if (!vg_commit(lv->vg)) {
		if (!resume_lv(cmd, lv))
			stack;
		goto_out;
	}

	log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
	if (!resume_lv(cmd, lv)) {
		log_error("Problem reactivating %s", lv->name);
		goto out;
	}

	r = 1;
out:
	backup(lv->vg);
	return r;
}
Exemple #7
0
static int _read_size_params(struct lvcreate_params *lp,
			     struct lvcreate_cmdline_params *lcp,
			     struct cmd_context *cmd)
{
	if (arg_count(cmd, extents_ARG) && arg_count(cmd, size_ARG)) {
		log_error("Please specify either size or extents (not both)");
		return 0;
	}

	if (!lp->thin && !lp->snapshot && !arg_count(cmd, extents_ARG) && !arg_count(cmd, size_ARG)) {
		log_error("Please specify either size or extents");
		return 0;
	}

	if (arg_count(cmd, extents_ARG)) {
		if (arg_sign_value(cmd, extents_ARG, SIGN_NONE) == SIGN_MINUS) {
			log_error("Negative number of extents is invalid");
			return 0;
		}
		lp->extents = arg_uint_value(cmd, extents_ARG, 0);
		lcp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
	}

	/* Size returned in kilobyte units; held in sectors */
	if (arg_count(cmd, size_ARG)) {
		if (arg_sign_value(cmd, size_ARG, SIGN_NONE) == SIGN_MINUS) {
			log_error("Negative size is invalid");
			return 0;
		}
		lcp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0));
		lcp->percent = PERCENT_NONE;
	}

	/* If size/extents given with thin, then we are creating a thin pool */
	if (seg_is_thin(lp) && (arg_count(cmd, size_ARG) || arg_count(cmd, extents_ARG)))
		lp->create_pool = 1;

	if (!lp->create_pool && arg_count(cmd, poolmetadatasize_ARG)) {
		log_error("--poolmetadatasize may only be specified when allocating the pool.");
		return 0;
	}

	if (arg_count(cmd, virtualsize_ARG)) {
		if (seg_is_thin_pool(lp)) {
			log_error("Virtual size in incompatible with thin_pool segment type.");
			return 0;
		}
		if (arg_sign_value(cmd, virtualsize_ARG, SIGN_NONE) == SIGN_MINUS) {
			log_error("Negative virtual origin size is invalid");
			return 0;
		}
		/* Size returned in kilobyte units; held in sectors */
		lp->voriginsize = arg_uint64_value(cmd, virtualsize_ARG,
						   UINT64_C(0));
		if (!lp->voriginsize) {
			log_error("Virtual origin size may not be zero");
			return 0;
		}
	} else {
		/* No virtual size given and no snapshot, so no thin LV to create. */
		if (seg_is_thin_volume(lp) && !lp->snapshot &&
		    !(lp->segtype = get_segtype_from_string(cmd, "thin-pool")))
			return_0;

		lp->thin = 0;
	}

	return 1;
}
Exemple #8
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;
}
Exemple #9
0
static int lvchange_pool_update(struct cmd_context *cmd,
				struct logical_volume *lv)
{
	int r = 0;
	int update = 0;
	unsigned val;
	thin_discards_t discards;

	if (!lv_is_thin_pool(lv)) {
		log_error("Logical volume \"%s\" is not a thin pool.", lv->name);
		return 0;
	}

	if (arg_count(cmd, discards_ARG)) {
		discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_IGNORE);
		if (discards != first_seg(lv)->discards) {
			if ((discards != THIN_DISCARDS_IGNORE) &&
				 (first_seg(lv)->chunk_size &
				  (first_seg(lv)->chunk_size - 1)))
				log_error("Cannot change discards state for "
					  "logical volume \"%s\" "
					  "with non power of 2 chunk size.", lv->name);
			else if (((discards == THIN_DISCARDS_IGNORE) ||
			     (first_seg(lv)->discards == THIN_DISCARDS_IGNORE)) &&
			    lv_is_active(lv))
				log_error("Cannot change discards state for active "
					  "logical volume \"%s\".", lv->name);
			else {
				first_seg(lv)->discards = discards;
				update++;
			}
		} else
			log_error("Logical volume \"%s\" already uses --discards %s.",
				  lv->name, get_pool_discards_name(discards));
	}

	if (arg_count(cmd, zero_ARG)) {
		val = arg_uint_value(cmd, zero_ARG, 1);
		if (val != first_seg(lv)->zero_new_blocks) {
			first_seg(lv)->zero_new_blocks = val;
			update++;
		} else
			log_error("Logical volume \"%s\" already %szero new blocks.",
				  lv->name, val ? "" : "does not ");
	}

	if (!update)
		return 0;

	log_very_verbose("Updating logical volume \"%s\" on disk(s).", lv->name);
	if (!vg_write(lv->vg))
		return_0;

	if (!suspend_lv_origin(cmd, lv)) {
		log_error("Failed to update active %s/%s (deactivation is needed).",
			  lv->vg->name, lv->name);
		vg_revert(lv->vg);
		goto out;
	}

	if (!vg_commit(lv->vg)) {
		if (!resume_lv_origin(cmd, lv))
			stack;
		goto_out;
	}

	if (!resume_lv_origin(cmd, lv)) {
		log_error("Problem reactivating %s.", lv->name);
		goto out;
	}

	r = 1;
out:
	backup(lv->vg);
	return r;
}