文档章节

LVM源码分析3-lvextend

LastRitter
 LastRitter
发布于 2017/09/12 14:16
字数 957
阅读 17
收藏 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
粉丝 37
博文 40
码字总数 190940
作品 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
Linux系统逻辑盘卷管理LVM详细介绍

  一、 前言   每个Linux使用者在安装Linux时都会遇到这样的困境:在为系统分区时,如何精确评估和分配各个硬盘分区的容量,因为系统管理员不但要考虑到当前某个分区需要的容量,还要预见...

红薯
2009/05/07
847
1

没有更多内容

加载失败,请刷新页面

加载更多

Spring源码学习笔记-1-Resource

打算补下基础,学习下Spring源码,参考书籍是《Spring源码深度解析》,使用版本是Spring 3.2.x,本来想试图用脑图记录的,发现代码部分不好贴,还是作罢,这里只大略记录下想法,不写太细了 ...

zypy333
今天
10
0
RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
今天
17
0

中国龙-扬科
昨天
2
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
10
0
java框架学习日志-6(bean作用域和自动装配)

本章补充bean的作用域和自动装配 bean作用域 之前提到可以用scope来设置单例模式 <bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean> 除此之外还有几种用法 singleton:......

白话
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部