文档章节

LVM源码分析3-lvextend

LastRitter
 LastRitter
发布于 2017/09/12 14:16
字数 957
阅读 12
收藏 0
LVM

命令参数定义:

$ cat tools/command.h
...

xx(lvextend,
   "Add space to a logical volume",
   0,
   "lvextend\n"
   "\t[-A|--autobackup y|n]\n"
   "\t[--alloc AllocationPolicy]\n"
   "\t[--commandprofile ProfileName]\n"
   "\t[-d|--debug]\n"
   "\t[-f|--force]\n"
   "\t[-h|--help]\n"
   "\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
   "\t{-l|--extents [+]LogicalExtentsNumber[%{VG|LV|PVS|FREE|ORIGIN}] |\n"
   "\t -L|--size [+]LogicalVolumeSize[bBsSkKmMgGtTpPeE]}\n"
   "\t --poolmetadatasize [+]MetadataVolumeSize[bBsSkKmMgG]}\n"
   "\t[-m|--mirrors Mirrors]\n"
   "\t[--nosync]\n"
   "\t[--use-policies]\n"
   "\t[-n|--nofsck]\n"
   "\t[--noudevsync]\n"
   "\t[--reportformat {basic|json}]\n"
   "\t[-r|--resizefs]\n"
   "\t[-t|--test]\n"
   "\t[--type VolumeType]\n"
   "\t[-v|--verbose]\n"
   "\t[--version]\n"
   "\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",

   alloc_ARG, autobackup_ARG, extents_ARG, force_ARG, mirrors_ARG,
   nofsck_ARG, nosync_ARG, noudevsync_ARG, poolmetadatasize_ARG,
   reportformat_ARG, resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG,
   test_ARG, type_ARG, usepolicies_ARG)

...

命令入口,调用lvresize:

$ cat tools/lvextend.c
...

#include "tools.h"

int lvextend(struct cmd_context *cmd, int argc, char **argv)
{
	return lvresize(cmd, argc, argv);
}

...

lvresize函数入口:

$ cat tools/lvresize.c
...

int lvresize(struct cmd_context *cmd, int argc, char **argv)
{
	struct processing_handle *handle;
	struct lvresize_params lp = { 0 };
	int ret;

	if (!_lvresize_params(cmd, argc, argv, &lp)) {
		stack;
		return EINVALID_CMD_LINE;
	}

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

	handle->custom_handle = &lp;

	ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
			      &_lvresize_single);

	destroy_processing_handle(cmd, handle);

	return ret;
}

...
...

static int _lvresize_single(struct cmd_context *cmd, const char *vg_name,
			    struct volume_group *vg, struct processing_handle *handle)
{
	struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
	struct dm_list *pvh;
	struct logical_volume *lv;
	int ret = ECMD_FAILED;

	/* Does LV exist? */
	if (!(lv = find_lv(vg, lp->lv_name))) {
		log_error("Logical volume %s not found in volume group %s.",
			  lp->lv_name, vg->name);
		goto out;
	}

	if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc, lp->argv, 1) : &vg->pvs))
		goto_out;

	if (!lv_resize(lv, lp, pvh))
		goto_out;

	ret = ECMD_PROCESSED;
out:
	return ret;
}


...

lv_resize关键部分:

$ cat lib/metadata/lv_mainp.c
...

int lv_resize(struct logical_volume *lv,
	      struct lvresize_params *lp,
	      struct dm_list *pvh)
{
	struct volume_group *vg = lv->vg;
	struct cmd_context *cmd = vg->cmd;
	struct logical_volume *lock_lv = (struct logical_volume*) lv_lock_holder(lv);
	struct logical_volume *aux_lv = NULL; /* Note: aux_lv never resizes fs */
	struct lvresize_params aux_lp;
	int activated = 0;
	int ret = 0;

	if (!_lvresize_check(lv, lp))
		return_0;

	if (lp->use_policies) {
		lp->extents = 0;
		lp->sign = SIGN_PLUS;
		lp->percent = PERCENT_LV;

		aux_lp = *lp;
		if (!_lvresize_adjust_policy(lv, &lp->extents, &aux_lp.extents))
			return_0;

		if (!lp->extents) {
			if (!aux_lp.extents)
				return 1;  /* Nothing to do */
			/* Resize thin-pool metadata as mainlv */
			lv = first_seg(lv)->metadata_lv; /* metadata LV */
			lp->extents = aux_lp.extents;
		} else if (aux_lp.extents) {
			/* Also resize thin-pool metadata */
			aux_lv = _lvresize_setup_aux(first_seg(lv)->metadata_lv, &aux_lp);
		}
	} else if (lp->poolmetadata_size) {
		if (!lp->extents && !lp->size) {
			/* When only --poolmetadatasize give and not --size
			 * swith directly to resize metadata LV */
			lv = first_seg(lv)->metadata_lv;
			lp->size = lp->poolmetadata_size;
			lp->sign = lp->poolmetadata_sign;
		} else {
			aux_lp = *lp;
			aux_lv = _lvresize_setup_aux(first_seg(lv)->metadata_lv, &aux_lp);
			aux_lp.size = lp->poolmetadata_size;
			aux_lp.sign = lp->poolmetadata_sign;
		}
	}

	if (aux_lv && !_lvresize_prepare(&aux_lv, &aux_lp, pvh))
		return_0;

	if (!_lvresize_prepare(&lv, lp, pvh))
		return_0;

	if (lv_is_thin_pool(lock_lv) &&  /* Lock holder is thin-pool */
	    !lv_is_active(lock_lv)) {

		if (!activation()) {
			log_error("Cannot resize %s without using "
				  "device-mapper kernel driver.",
				  display_lvname(lock_lv));
			return 0;
		}
		/*
		 * Active 'hidden' -tpool can be waiting for resize, but the
		 * pool LV itself might be inactive.
		 * Here plain suspend/resume would not work.
		 * So active temporarily pool LV (with on disk metadata)
		 * then use suspend and resume and deactivate pool LV,
		 * instead of searching for an active thin volume.
		 */
		if (!activate_lv_excl(cmd, lock_lv)) {
			log_error("Failed to activate %s.", display_lvname(lock_lv));
			return 0;
		}

		activated = 1;
	}

	/*
	 * If the LV is locked from activation, this lock call is a no-op.
	 * Otherwise, this acquires a transient lock on the lv (not PERSISTENT).
	 */
	if (!lockd_lv(cmd, lock_lv, "ex", 0))
		return_0;

	if (aux_lv) {
		if (!_lvresize_volume(aux_lv, &aux_lp, pvh))
			goto_bad;

		/* store vg on disk(s) */
		if (!lv_update_and_reload(lock_lv))
			goto_bad;
	}

	if (!_lvresize_volume(lv, lp, pvh))
		goto_bad;

	/* store vg on disk(s) */
	if (!lv_update_and_reload(lock_lv))
		goto_bad;

	if (lv_is_cow_covering_origin(lv))
		if (!monitor_dev_for_events(cmd, lv, 0, 0))
			stack;

	if (lv_is_thin_pool(lock_lv)) {
		/* Update lvm pool metadata (drop messages). */
		if (!update_pool_lv(lock_lv, 0))
			goto_bad;

		backup(vg);
	}

	log_print_unless_silent("Logical volume %s successfully resized.",
				display_lvname(lv));

	if (lp->resizefs && (lp->resize == LV_EXTEND) &&
	    !_fsadm_cmd(FSADM_CMD_RESIZE, lv, lp->extents, lp->force, NULL))
		return_0;

	ret = 1;
bad:
	if (activated && !deactivate_lv(cmd, lock_lv)) {
		log_error("Problem deactivating %s.", display_lvname(lock_lv));
		ret = 0;
	}

	return ret;
}

...
$ cat lib/locking/file_locking.c
...

static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
			       uint32_t flags, const struct logical_volume *lv)
{

...

		case LCK_UNLOCK:
			log_very_verbose("Unlocking LV %s%s%s", resource, origin_only ? " without snapshots" : "", revert ? " (reverting)" : "");
			if (!lv_resume_if_active(cmd, resource, origin_only, 0, revert, lv_committed(lv)))
				return 0;
			break;

...

		case LCK_WRITE:
			log_very_verbose("Locking LV %s (W)%s", resource, origin_only ? " without snapshots" : "");
			if (!lv_suspend_if_active(cmd, resource, origin_only, 0, lv_committed(lv), lv))
				return 0;
			break;

...

	return 1;
}

...
$ cat lib/active/active.c
...

/*
 * In a cluster, set exclusive to indicate that only one node is using the
 * device.  Any preloaded tables may then use non-clustered targets.
 *
 * Returns success if the device is not active
 */
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, unsigned exclusive,
			 const struct logical_volume *lv, const struct logical_volume *lv_pre)
{
	struct lv_activate_opts laopts = {
		.origin_only = origin_only,
		.exclusive = exclusive
	};

	return _lv_suspend(cmd, lvid_s, &laopts, 0, lv, lv_pre);
}

...

/*
 * In a cluster, set exclusive to indicate that only one node is using the
 * device.  Any tables loaded may then use non-clustered targets.
 *
 * @origin_only
 * @exclusive   This parameter only has an affect in cluster-context.
 *              It forces local target type to be used (instead of
 *              cluster-aware type).
 * Returns success if the device is not active
 */
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
			unsigned origin_only, unsigned exclusive,
			unsigned revert, const struct logical_volume *lv)
{
	struct lv_activate_opts laopts = {
		.origin_only = origin_only,
		.exclusive = exclusive,
		.revert = revert
	};

	return _lv_resume(cmd, lvid_s, &laopts, 0, lv);
}

...

© 著作权归作者所有

共有 人打赏支持
LastRitter
粉丝 36
博文 37
码字总数 171159
作品 0
武汉
高级程序员
Centos 7 LVM硬盘动态扩容要点

LVM硬盘扩容方法要点: 1、如果采用VMWARE,可以直接动态添加硬盘。 2、通过echo "scsi add-single-device 0 0 1 0" >/proc/scsi/scsi 动态添加。 3、fdisk -l 显示后,通过fdisk 里创建分区...

boydreaming
2016/02/28
158
0
linux中LVM动态扩容和管理

相关概念 pv:物理卷 pe:物理拓展卷 lvm的最小存储单元 vg :卷组 lvm :最终使用的可伸缩设备 2. lvm 建立 1).划分物理分区,修改其标签为lvm 通过L 查出8e编号符合要求 修改成功 (2)pvc...

技术小白JDY
2017/11/09
0
0
linux调整lvm分区大小

最近开始捣鼓linux,把开发环境转到linux上。。。由于本人有怪癖。。不喜欢集成包。。所以apache+php+mysql相关的开发环境都是手动编译的。。 在安装centos的时候由于对分区不熟悉,选择了默...

吃鱼的虾米
2014/01/21
0
5
Ubuntu的Linux逻辑卷管理-LVM快速入门

LVM(逻辑卷)管理系统可以将多个物理磁盘组装为一个大的逻辑磁盘进行使用,尤其是管理大文件时非常方便。LVM可以减少多个磁盘的部分空间闲置的情况,集中使用提高磁盘利用率。LVM的卷可以动...

openthings
2016/11/07
43
0
centos 用命令创建LVM逻辑卷

LVM基本术语   LVM是在磁盘分区和文件系统之间添加的一个逻辑层,来为文件系统屏蔽下层磁盘分区布局,提供一个抽象的盘卷,在盘卷上建立文件系统。 物理存储介质(The physical media):这...

求学ing
2013/03/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day122-20181020-英语流利阅读-待学习

蜘蛛侠新片《毒液》来袭!导演灵感来自哪? Roxy 2018-10-20 1.今日导读 你还记得漫威宇宙中飞檐走壁的蜘蛛侠小可爱吗?在刚过去的国庆黄金周里,索尼影业发行的漫威超级英雄蜘蛛侠系列大片《...

飞鱼说编程
17分钟前
1
0
美团点评Docker容器管理平台

美团点评容器平台简介 本文介绍美团点评的Docker容器集群管理平台(以下简称“容器平台”)。该平台始于2015年,是基于美团云的基础架构和组件而开发的Docker容器集群管理平台。目前该平台为...

Skqing
23分钟前
1
0
JDK8笔记

判断两个对象是否相等 Objects.equals(value1, value2)

呼呼南风
今天
1
0
OSChina 周六乱弹 —— 到底谁是小公猫……

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享Trivium的单曲《Throes Of Perdition》 《Throes Of Perdition》- Trivium 手机党少年们想听歌,请使劲儿戳(这里) @小鱼丁:...

小小编辑
今天
354
5
基础选择器

注意:本教程参考自网上流传的李兴华老师的jquery开发框架视频,但是苦于没有相应的配套笔记,由我本人做了相应的整理. 本次学习的内容 学习jquery提供的各种选择器的使用,掌握了jquery选择...

江戸川
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部