前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初探lustre中的MGC

初探lustre中的MGC

作者头像
用户4700054
发布2022-08-17 12:41:01
6470
发布2022-08-17 12:41:01
举报
文章被收录于专栏:存储内核技术交流

基本介绍

  • lustre 客户端包含了三个主要的组件,分别是MGC(management client)MDC(metadata client)、若干个OSC(object storage client)。客户端中每个osc对应后端lustre的ost.MGC管理客户端是作为整个lustre vfs和MGS(lustre management server)之间的接口.lustre通过MGT后端设备注册MGS,后续客户端请求MGS来获取文件系统信息
  • MGC中的核心模块有处理lustre 日志、分布式锁管理、文件系统设置这三类核心函数。MGC是整个lustre文件系统中第一个初始化的OBD设备。MGC是单独作为一个kernel module实现,具体定义在
代码语言:javascript
复制
[ ~/lustre-2.14.52/lustre/mgc]$ ls -l -1h
Makefile.in
autoMakefile.am
lproc_mgc.c
mgc_internal.h
mgc_request.c

MGC模块初始化

  • 当MGC内核模块初始化,是通过注册一个OBD设备类型来注册一个MGC的组件,在mgc_init函数中进行初始化。OBD的数据和元数据操作是通过obd_ops和md_ops的结构来定义。MGC中仅仅涉及数据的操作。但是在客户端的MDC涉及了数据操作和元数据操作,这是因为lustre的Data On Metadata的功能。当lustre客户端初始化的时候,MGC的内核模块会调用mgc_init针对MGC初始化,当客户端销毁时候调用mgc_exit来清理MGC占用的资源
代码语言:javascript
复制
// MGC的数据操作的函数定义表
static const struct obd_ops mgc_obd_ops = {
       .o_owner        = THIS_MODULE,
       .o_setup        = mgc_setup,
       .o_precleanup   = mgc_precleanup,
       .o_cleanup      = mgc_cleanup,
       .o_add_conn     = client_import_add_conn,
       .o_del_conn     = client_import_del_conn,
       .o_connect      = client_connect_import,
       .o_disconnect   = client_disconnect_export,
       .o_set_info_async = mgc_set_info_async,
       .o_get_info       = mgc_get_info,
       .o_import_event = mgc_import_event,
       .o_process_config = mgc_process_config,
};

// MGC的内核模块初始化函数
static int __init mgc_init(void)
{
   return class_register_type(&mgc_obd_ops, NULL, false,
   			   LUSTRE_MGC_NAME, NULL);
}

// MGC内核模块退出的函数
static void __exit mgc_exit(void)
{
       class_unregister_type(LUSTRE_MGC_NAME);
}

MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
MODULE_DESCRIPTION("Lustre Management Client");
MODULE_VERSION(LUSTRE_VERSION_STRING);
MODULE_LICENSE("GPL");

module_init(mgc_init);
module_exit(mgc_exit);
  • MGC的OBD仅仅涉及到OBD的数据操作,其中通过定义mgc_obd_ops函数操作表来操作MGC的涉及到的操作。
代码语言:javascript
复制
1.lustre_init :lustre客户端进行mount时候初始化函数,这里涉及到的是lustre文件系统的注册(lustre_fs_type)
2.lustre_mount:当用户态执行mount时候,会调用lustre_mount来做
mount的过程
3.lustre_fill_super:客户端挂载点的mount执行
4.lustre_start_mgc:设置MGC的OBD设备处理启动的日志
5.lustre_start_simple:启动MDC的OBD,通过调用do_lcfg根据不同的命令操作MDC OBD
6.class_process_config:根据cmd初始化lustre_cfg配置MDC OBD.分别调用class_attach(),class_setup()注册和设置MDC OBD.class_attch函数调用class_register_device来注册lustre的MDC OBD.class_setup函数来设置MDC的OBD.这里class_setup实际调用的是mgc_setup.

MGC连接到MGS流程

  • MGC的启动流程,核心分为两步。第一是注册MGC的OBD;第二是连接到MGS.如下是启动的核心函数流程
代码语言:javascript
复制
// 启动lustre client 中的mgc
int lustre_start_mgc(struct super_block *sb)
{
   // 注册mdc obd和设置mdc obd
   rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME,
   			 (char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
   			 niduuid, NULL, NULL);
   // 设置完成连接到mgs
	rc = obd_connect(NULL, &exp, obd, uuid, data, NULL);
}

int class_process_config(struct lustre_cfg *lcfg)
{
   struct obd_device *obd;
   int err;

   LASSERT(lcfg && !IS_ERR(lcfg));
   CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);

   // 根据lcfg_commond注册MDC OBD
   switch (lcfg->lcfg_command) {
   	case LCFG_ATTACH: {
   		err = class_attach(lcfg);
   		GOTO(out, err);
   	}
   }
   // 根据MDC设置的数据操作参数表,调用mgc_setup设置
   switch(lcfg->lcfg_command) {
   	case LCFG_SETUP: {
   		err = class_setup(obd, lcfg);
   		GOTO(out, err);
   	}
   }
}
// 根据配置进行处理
static int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
   	   char *s1, char *s2, char *s3, char *s4)
{

   rc = class_process_config(lcfg);
   OBD_FREE(lcfg, lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens));
   return rc;
}

// 启动mgc的核心函数
int lustre_start_simple(char *obdname, char *type, char *uuid,
   		char *s1, char *s2, char *s3, char *s4)
{
   int rc;

   CDEBUG(D_MOUNT, "Starting OBD %s (typ=%s)\n", obdname, type);
   // mdc OBD分为2个阶段处理,LCFG_ATTACH命令是进行注册
   rc = do_lcfg(obdname, 0, LCFG_ATTACH, type, uuid, NULL, NULL);
   if (rc) {
   	CERROR("%s attach error %d\n", obdname, rc);
   	return rc;
   }
   // LCFG_SETUP是调用具体的mgc模块的mgc_setup进行设置
   rc = do_lcfg(obdname, 0, LCFG_SETUP, s1, s2, s3, s4);
   if (rc) {
   	CERROR("%s setup error %d\n", obdname, rc);
   	do_lcfg(obdname, 0, LCFG_DETACH, NULL, NULL, NULL, NULL);
   }
   return rc;
}

MDC的初始化设置

  • mgc_setup初始化客户端的RPC(lustre client到mgs),接着解析MGS发来的日志(mgs到mdc是通过解析log)。lustre中的默认的参数在MGS端持久化,然后发给lustre客户端和MGC,最后一步启动内核线程调用mgc_requeue_thread监听MGS是否有新的log发送,如果有就不断的根据mgc_process_log函数来进行处理。这里有一个场景,比如有新的ost添加到集群,这时候MGS发送log给mdc,mdc来解析log,配置当前lustre客户端模块中的mdc,通过命令就能看到当前新加入的ost的信息。
代码语言:javascript
复制
static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
{
	struct task_struct	*task;
	int			 rc;
	ENTRY;
	// 初始化一个rpc
	rc = ptlrpcd_addref();
	if (rc < 0)
		RETURN(rc);
	// mdc设置rpc
	rc = client_obd_setup(obd, lcfg);
	if (rc)
		GOTO(err_decref, rc);
	// mdc处理MGS发过来的log
	rc = mgc_llog_init(NULL, obd);
	if (rc) {
		CERROR("failed to setup llogging subsystems\n");
		GOTO(err_cleanup, rc);
	}
	// 默认参数的初始化
	rc = mgc_tunables_init(obd);
	if (rc)
		GOTO(err_sysfs, rc);

	if (atomic_inc_return(&mgc_count) == 1) {
		rq_state = 0;
		init_waitqueue_head(&rq_waitq);

		// 启动内核线程来运行mgc_requeue_thread
		task = kthread_run(mgc_requeue_thread, NULL, "ll_cfg_requeue");
		if (IS_ERR(task)) {
			rc = PTR_ERR(task);
			CERROR("%s: cannot start requeue thread: rc = %d; "
			       "no more log updates\n",
			       obd->obd_name, rc);
			GOTO(err_sysfs, rc);
		}
		/* rc is the task_struct pointer of mgc_requeue_thread. */
		rc = 0;
		wait_for_completion(&rq_start);
	}

	RETURN(rc);

err_sysfs:
	lprocfs_obd_cleanup(obd);
err_cleanup:
	client_obd_cleanup(obd);
err_decref:
	ptlrpcd_decref();
	RETURN(rc);
}

static int mgc_requeue_thread(void *data)
{
	rq_state |= RQ_RUNNING;
	while (!(rq_state & RQ_STOP)) {
		struct config_llog_data *cld, *cld_prev;
		// 休眠每次循环时间间隔
		to = cfs_time_seconds(MGC_TIMEOUT_MIN_SECONDS * 100 + rand);
		/* rand is centi-seconds */
		wait_event_idle_timeout(rq_waitq,
					rq_state & (RQ_STOP | RQ_PRECLEANUP),
					to/100);
		// 处理当前来自mgs的log
		do_requeue(cld) {
			mgc_process_log(...)
		}
	}
}

MDC日志处理

  • lustre使用了大量的log(lustre中的log一般成为llogs)方式用于分布式事务的恢复和提交。lustre提供llog_reader工具来解析lustre中的日志。当lustre注册MGS,MGS会为MDT会构造log.当客户端mount,这个动作会触发从MGS端下载lustre conf logs给客户端。MDC子系统负责读取和处理这些log.
  • MDC模块中通过lustre_process_log从MGS中获取conf log然后进行log的处理。lustre_process_log会在lustre client和lustre server端调用。处理过程中首先是通过lustre_cfg_bufs和调用obd_process_conf()来调用具体OBD的处理函数(mgc_process_config).

MDC 模块清理

  • MDC中定义了mgc_precleanup和mgc_cleanup函数,用来处理unmount和一些异常的情况。class_cleanup函数处理MDC OBD关闭的清理工作。第一步调用mgc_precleanup函数确保所有的exports在关闭MDC OBD前销毁。mgc_precleanup会维护mgc_count,当mgc_setup执行mgc_count会自增。mgc_count维护了当前MGC中的线程。接下来会调用obd_cleanup_client_import函数销毁客户端的mdc obd.最后mgc_precleanup调用mgc_llog_fini函数清理MGC相关的lustre logs。
  • mgc_cleanup调用class_del_profiles函数删除MGC OBD的profiles.当MGS发送数据给MGC,使用lustre profiles来识别这些数据。接下来使用lprocfs_obd_cleanup函数清理当前MDC的OBD的sysfs和debugfs相关信息,清理完毕PRC维护初始化的计数器自减,最后调用class_cleanup函数关闭MGC关闭流程。

OBD通信方式

  • lustre中每个OBD会有import和export.比如2个OBD通信,import是负责发送请求和接受响应;export负责接受请求和发送响应。客户端使用imports和服务端的exports进行通信。比如MDS想和MGS通信,MDS会使用它自己的inport和MGS端的export进行通信。MDC中有各种各样的事件类型,通过枚举来obd_import_event定义
代码语言:javascript
复制
	enum obd_import_event {
        IMP_EVENT_DISCON     = 0x808001,
        IMP_EVENT_INACTIVE   = 0x808002,
        IMP_EVENT_INVALIDATE = 0x808003,
        IMP_EVENT_ACTIVE     = 0x808004,
        IMP_EVENT_OCD        = 0x808005,
        IMP_EVENT_DEACTIVATE = 0x808006,
        IMP_EVENT_ACTIVATE   = 0x808007,
};
  • 如下是显示了lustre客户端各层OBD和服务端的OST之间的通信方式,这个方式也和MDC和MGS之间通信一样。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 存储内核技术交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本介绍
    • MGC模块初始化
      • MGC连接到MGS流程
        • MDC的初始化设置
          • MDC日志处理
            • MDC 模块清理
              • OBD通信方式
              相关产品与服务
              分布式事务 DTF
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档