前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊lustre中的恢复机制之认知篇

聊聊lustre中的恢复机制之认知篇

作者头像
用户4700054
发布2023-02-26 14:47:26
8070
发布2023-02-26 14:47:26
举报
文章被收录于专栏:存储内核技术交流

背景

  • lustre中恢复机制分为客户端和服务端,客户端进行文件操作时候的异常情况制和服务端(MDS/OST)进行文件操作时候的异常情况,lustre提供整套的异常情况下的恢复机制。这一篇着重讲解涉及核心数据结构和核心API,整个服务之间同时通过RPC连接,客户端失败或者服务端失败大部分都能体现在网络上RPC上,所以接下来会着重分析关于网络方面的基本信息

核心数据结构解说

  • lustre客户端都会在struct obd_import数据结构(这个数据结构是客户端通过obd_import发送请求到lustre的服务端)中维护struct ptlrpc_connection结构来维护lustre服务端的链接。其中obd_import->imp_state维护了enum lustre_imp_state定义的链接状态.
代码语言:javascript
复制
struct obd_import {

	// 引用计数
	refcount_t		  imp_refcount;
	struct lustre_handle      imp_dlm_handle; /* client's ldlm export */

	// 当前活跃的连接
	struct ptlrpc_connection *imp_connection;

    // 当前活跃连接客户端RPC结构
     struct ptlrpc_client     *imp_client;
	/** List element for linking into pinger chain */
	struct list_head	  imp_pinger_chain;
	/** work struct for destruction of import */
	struct work_struct	  imp_zombie_work;

 
    // 请求已经发送但是未收到响应的列表
	struct list_head	imp_replay_list;
	// 请求发送列表  obd_import->imp_sending_list
	struct list_head	imp_sending_list;
	// delayed队列obd_import->imp_delayed_list
	struct list_head	imp_delayed_list;

	struct list_head	imp_committed_list;
	struct list_head	*imp_replay_cursor;
	/** @} */

	/** List of not replied requests */
	struct list_head	imp_unreplied_list;
	/** Known maximal replied XID */
	__u64			imp_known_replied_xid;

	/** obd device for this import */
	struct obd_device	*imp_obd;


	struct ptlrpc_sec        *imp_sec;
	rwlock_t		  imp_sec_lock;
	time64_t		imp_sec_expire;
	pid_t			  imp_sec_refpid;
        /** @} */

	/** Wait queue for those who need to wait for recovery completion */
	wait_queue_head_t         imp_recovery_waitq;

	/** Number of requests allocated */
	atomic_t                  imp_reqs;
	
};
  • imp_state维护的状态目前有11中,具体如下
代码语言:javascript
复制
enum lustre_imp_state {
		// 连接关闭
        LUSTRE_IMP_CLOSED     = 1,
        // 请求发送到服务端开启新的连接
        LUSTRE_IMP_NEW        = 2,
        // 断开连接
        LUSTRE_IMP_DISCON     = 3,
        // 连接中的状态
        LUSTRE_IMP_CONNECTING = 4,
        // 连接的响应状态
        LUSTRE_IMP_REPLAY     = 5,
        // repay & lock的连接状态
        LUSTRE_IMP_REPLAY_LOCKS = 6,
        // 响应等待的状态
        LUSTRE_IMP_REPLAY_WAIT  = 7,
        // 连接的recovery的状态
        LUSTRE_IMP_RECOVER    = 8,
        // 活跃连接的状态
        LUSTRE_IMP_FULL       = 9,
        // 被驱逐链接的状态
        LUSTRE_IMP_EVICTED    = 10,
	LUSTRE_IMP_IDLE	      = 11,
	LUSTRE_IMP_LAST
};

// 状态到名称状态转换
static inline const char *ptlrpc_import_state_name(enum lustre_imp_state state)
{
	static const char * const import_state_names[] = {
		"<UNKNOWN>", "CLOSED",  "NEW", "DISCONN",
		"CONNECTING", "REPLAY", "REPLAY_LOCKS", "REPLAY_WAIT",
		"RECOVER", "FULL", "EVICTED", "IDLE",
	};

	LASSERT(state < LUSTRE_IMP_LAST);
	return import_state_names[state];
}

核心Recovery API解说

ptlrpc_fail_import
  • ptlrpc_fail_import当客户端锁请求时候被调用,这个函数着重做2个事情,第一个是设置连接断开状态;第二是强制启动通信的ping行为。
代码语言:javascript
复制
static DECLARE_DELAYED_WORK(ping_work, ptlrpc_pinger_main);

void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt)
{
	// 设置连接断开状态
	if (ptlrpc_set_import_discon(imp, conn_cnt, true))
		ptlrpc_pinger_force(imp);

	EXIT;
}
  • ptlrpc_set_import_discon函数中的实现实现中最终调用的是obd_import_event所指向的函数指针.lustre中在mgc/mdc/lwp/osc/osp都会针对这个函数指针设置自身的函数。
ptlrpc_recover_import
  • ptlrpc_recover_import函数是rpc层发送端的重连的实现,其中最核心的是设置断开连接状态然后再去连接。
代码语言:javascript
复制
int ptlrpc_recover_import(struct obd_import *imp...)
{
	// 强制断开连接
	ptlrpc_set_import_discon(imp, 0, false)
	rc = ptlrpc_connect_import(imp)
	{
		ptlrpc_connect_import_locked(imp)
		{
			// 尝试连接
			obd_reconnect(NULL, imp->imp_obd->obd_self_export, obd,
			   &obd->obd_uuid, &ocd, NULL)
			
		}
	}
}
ptlrpc_reconnect_import
  • ptlrpc_reconnect_import重新连接import端用来发送请求,这个执行链路如下。
代码语言:javascript
复制
int ptlrpc_reconnect_import(struct obd_import *imp)
{
	// 设置连接状态
	ptlrpc_set_import_discon(imp, 0, false)

	// 校验import
	ptlrpc_invalidate_import(imp)
	// 断开连接
	ptlrpc_disconnect_import(imp, 1)
	// 激活import发送端
	ptlrpc_activate_import(imp, false)
	// 恢复import发送端
	ptlrpc_recover_import(imp, NULL, 0);
}
ptlrpc_resend
  • ptlrpc_resend核心功能是遍历obd_import->imp_sending_list然后把这个列表的所有请求发送出去。
代码语言:javascript
复制
int ptlrpc_resend(struct obd_import *imp)
{
	list_for_each_entry(req, &imp->imp_sending_list, rq_list) {
		if (!ptlrpc_no_resend(req) &&
		    (req->rq_timedout || !req->rq_allow_replay))
			ptlrpc_resend_req(req);
	}
}
ptlrpc_wake_delayed
  • ptlrpc_wake_delayed遍历obd_import->imp_delayed_list然后唤醒线程重新发送请求
代码语言:javascript
复制
void ptlrpc_wake_delayed(struct obd_import *imp)
{
	struct ptlrpc_request *req;

	spin_lock(&imp->imp_lock);
	list_for_each_entry(req, &imp->imp_delayed_list, rq_list) {
		ptlrpc_client_wake_req(req);
	}
	spin_unlock(&imp->imp_lock);
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-01-06,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 核心数据结构解说
  • 核心Recovery API解说
    • ptlrpc_fail_import
      • ptlrpc_recover_import
        • ptlrpc_reconnect_import
          • ptlrpc_resend
            • ptlrpc_wake_delayed
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档