前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lustre客户端mount过程都做了什么?

lustre客户端mount过程都做了什么?

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

lustre client介绍

  • lustre 客户端的VFS层在lustre中叫做llite.它是linux kernel和LOV、MDC、LDLM这些lustre子系统的桥梁。
  • llite负责挂载客户端文件系统、处理名字查找、文件IO和文件权限等操作
llite源代码文件说明
代码语言:javascript
复制
//	acl.c- 文件acl处理
lustre-2.14.52/lustre/llite/acl.c
lustre-2.14.52/lustre/llite/autoMakefile.am
lustre-2.14.52/lustre/llite/crypto.c
// dcache.c-linux dentry cache交互的处理接口
lustre-2.14.52/lustre/llite/dcache.c
// dir.c-readdir的处理
lustre-2.14.52/lustre/llite/dir.c
// file.c-文件处理,包括文件的ioctl、文件的分布式锁等
lustre-2.14.52/lustre/llite/file.c
lustre-2.14.52/lustre/llite/foreign_symlink.h
lustre-2.14.52/lustre/llite/glimpse.c
lustre-2.14.52/lustre/llite/lcommon_cl.c
lustre-2.14.52/lustre/llite/lcommon_misc.c
lustre-2.14.52/lustre/llite/llite_foreign.c
lustre-2.14.52/lustre/llite/llite_foreign_symlink.c
// llite_internal.h-中定义llite模块中定义函数原型和数据结构
lustre-2.14.52/lustre/llite/llite_internal.h
// llite_lib.c-处理主要的请求和客户端挂载
lustre-2.14.52/lustre/llite/llite_lib.c
// llite_mmap.c-处理mempry-mapped IO操作
lustre-2.14.52/lustre/llite/llite_mmap.c
// llite_nfs.c-处理从客户端到处nfs的逻辑
lustre-2.14.52/lustre/llite/llite_nfs.c
// lproc_llite.c-处理/proc下可调整的静态数据逻辑
lustre-2.14.52/lustre/llite/lproc_llite.c
// namei.c-文件名查找、intent的处理
lustre-2.14.52/lustre/llite/namei.c
lustre-2.14.52/lustre/llite/pcc.c
lustre-2.14.52/lustre/llite/pcc.h
// rw*.c-内核IO处理函数
lustre-2.14.52/lustre/llite/rw.c
lustre-2.14.52/lustre/llite/rw26.c
// statahead.c-目录的statahead操作,比如"ls -l"和“rm -r"
lustre-2.14.52/lustre/llite/statahead.c
// super25.c-lustre文件系统注册
lustre-2.14.52/lustre/llite/super25.c
// symlink.c-符号链接处理
lustre-2.14.52/lustre/llite/symlink.c
lustre-2.14.52/lustre/llite/vvp_dev.c
lustre-2.14.52/lustre/llite/vvp_internal.h
lustre-2.14.52/lustre/llite/vvp_io.c
lustre-2.14.52/lustre/llite/vvp_object.c
lustre-2.14.52/lustre/llite/vvp_page.c
// xattr*.c-用户属性处理
lustre-2.14.52/lustre/llite/xattr.c
lustre-2.14.52/lustre/llite/xattr_cache.c
lustre-2.14.52/lustre/llite/xattr_security.c
lustre客户端内核模块
  • lustre客户端模块定义
代码语言:javascript
复制
//lustre-2.14.52\lustre\llite\super25.c

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

module_init(lustre_init);
module_exit(lustre_exit);



// lustre客户端的超级块,是从linux kernel中的super_block中s_fs_info获取。因为linux 文件系统采用了工厂模式,每个文件的私有的super_block都应该会在s_fs_info中(zfs/xfs/ext4等)

struct super_block *sb->s_fs_info

#define     s2lsi(sb)        ((struct lustre_sb_info *)((sb)->s_fs_info))

struct lustre_sb_info *lsi = s2lsi(sb);
  • lustre_init和lustre_exit函数
代码语言:javascript
复制
// 当执行modprobe lustre 会自动加载这个内核模块,注册lustre文件系统
static int __init lustre_init(void)
{
	// 注册以后,在宿主机上执行mount时候会去找对应文件系统的mount函数,并执行
	// 比如  mount -t lustre xxx:tcp0/samplefs  /mnt/samplefs.这个命令时候会去找lustre的内核模块,通过linux 内核去执行lustre系统的mount函数
	rc = register_filesystem(&lustre_fs_type);
}

static void __exit lustre_exit(void)
{
	// 从linux kernel中移除lustre客户端端内核模块信息
	unregister_filesystem(&lustre_fs_type);
}
  • lustre_fs_type定义
代码语言:javascript
复制
static struct file_system_type lustre_fs_type = {
	.owner		= THIS_MODULE,
	// 内核模块名称
	.name		= "lustre",
	// lustre文件系统的mount函数定义
	.mount		= lustre_mount,
	.kill_sb	= lustre_kill_super,
	.fs_flags	= FS_RENAME_DOES_D_MOVE,
};
lustre内核module
  • 所有的内核模块
代码语言:javascript
复制
// lustre中所有的内核模块定义
#define LUSTRE_MDS_NAME         "mds"
#define LUSTRE_MDT_NAME         "mdt"
#define LUSTRE_MDC_NAME         "mdc"
#define LUSTRE_OSS_NAME         "ost"       /* FIXME change name to oss */
#define LUSTRE_OST_NAME         "obdfilter" /* FIXME change name to ost */
#define LUSTRE_OSC_NAME         "osc"
#define LUSTRE_LOV_NAME         "lov"
#define LUSTRE_MGS_NAME         "mgs"
#define LUSTRE_MGC_NAME         "mgc"

#define LUSTRE_ECHO_NAME        "obdecho"
#define LUSTRE_ECHO_CLIENT_NAME "echo_client"
#define LUSTRE_QMT_NAME         "qmt"
  • obd类型的定义
代码语言:javascript
复制
/* lustre中的每个组件的服务名称 */
#define LUSTRE_MDS_OBDNAME "MDS"
#define LUSTRE_OSS_OBDNAME "OSS"
#define LUSTRE_MGS_OBDNAME "MGS"
#define LUSTRE_MGC_OBDNAME "MGC"
客户端的mount函数执行路径
代码语言:javascript
复制
// lustre mount整个函数调用链路如下,从第5个函数lustre_mount开始开始执行lustre的mount的函数,接下来也会重点分析这些函数
1.sys_mount
2.do_mount
3.vfs_kern_mount
4.mount_fs
5.lustre_mount
6.mount_nodev
7.lustre_fill_super
8.ll_fill_super
9.client_common_fill_super
lustre挂载核心函数分析
  • lustre_mount函数
代码语言:javascript
复制
// linux内核中进行mount
/***************** FS registration ******************/
static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
				   const char *devname, void *data)
{
	// mount_nodev 挂载非块设备的文件系统
	// fs_type 代表文件系统类型
	// data 是挂载文件系统时候的mount option数据
	// lustre_file_super 是lustre文件系统挂载时候的入口函数
	return mount_nodev(fs_type, flags, data, lustre_fill_super);
}
  • lustre_fill_super 函数
代码语言:javascript
复制
// 当进行mount操作,直接进入该函数
static int lustre_fill_super(struct super_block *sb, void *lmd2_data,
			     int silent)
{
	// lustre 超级块的结构
	struct lustre_sb_info *lsi;
	// lsi初始化,在lsi中指定lustre_mount_data,赋值struct super_block中的s_fs_info为 lustre_sb_info
	lsi = lustre_init_lsi(sb);
	
	// 解析挂载参数
	lmd_parse(lmd2_data, lmd);
	
	// 判断是否是客户端挂载,如果是mdt/ost 则会走如下的逻辑
	if (!lmd_is_client(lmd)) {
		rc = server_fill_super(sb);
		goto out:
	}
	
	// lustre 客户端会走如下逻辑代码:
	
	// lustre客户端连接mgc
	rc = lustre_start_mgc(sb);

	// 超级块初始化,同时连接osc和mdc
	rc = ll_fill_super(sb) {
		// 超级块初始化,同时连接osc和mdc
		err = client_common_fill_super(sb, md, dt);
	}

out:
	return rc;
}
  • lustre_start_mgc函数
代码语言:javascript
复制
// 客户端测定义mgc的操作函数,这个定义在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);
}

static void __exit mgc_exit(void)
{
        class_unregister_type(LUSTRE_MGC_NAME);
}


int lustre_start_mgc(struct super_block *sb)
{
	// 这里是定义的是一个mdt 设备
	struct obd_device *obd;
	obd = class_name2obd(mgcname);
	
	// obd_set_info_async 实际是调用 mgc_obd_ops中的mgc_set_info_async
	rc = obd_set_info_async(NULL, obd->obd_self_export,
				strlen(KEY_MGSSEC), KEY_MGSSEC,
				strlen(mgssec), mgssec, NULL);
	
	// 这里实际调用的是mgc_obd_ops中的o_connect,到这里完成了到客户端连接到lustre的mgs端
	rc = obd_connect(NULL, &exp, obd, uuid, data, NULL);
out:
	lsi->lsi_mgc = obd;
}
  • ll_fill_super函数
代码语言:javascript
复制
// lustre文件系统名称的最大长度,这是硬编码。如果需要修改限制,需要重新编译
#define LUSTRE_MAXFSNAME 8

int ll_fill_super(struct super_block *sb)
{
	struct	lustre_profile *lprof = NULL;
	char	*dt = NULL, *md = NULL;
	char	*profilenm = get_profile_name(sb);
	
	// LUSTRE_MAXFSNAME 中定义文件lustre文件系统最大的长度为8个字节
	// 获取oss的信息
	dt_len = strlen(lprof->lp_dt) + instlen + 2;
	OBD_ALLOC(dt, dt_len);
	snprintf(dt, dt_len - 1, "%s-%016lx", lprof->lp_dt, cfg_instance);
	
	// 获取mds信息
	md_len = strlen(lprof->lp_md) + instlen + 2;
	OBD_ALLOC(md, md_len);
	snprintf(md, md_len - 1, "%s-%016lx", lprof->lp_md, cfg_instance);
	
	err = client_common_fill_super(sb, md, dt);
}
  • client_common_fill_super函数
代码语言:javascript
复制
// osc 内核模块中定义,提供给客户端使用
static const struct obd_ops osc_obd_ops = {
        .o_owner                = THIS_MODULE,
        .o_setup                = osc_setup,
        .o_precleanup           = osc_precleanup,
		.o_cleanup              = osc_cleanup_common,
        .o_add_conn             = client_import_add_conn,
        .o_del_conn             = client_import_del_conn,
		.o_connect              = client_connect_import,
        .o_reconnect            = osc_reconnect,
        .o_disconnect           = osc_disconnect,
        .o_statfs               = osc_statfs,
        .o_statfs_async         = osc_statfs_async,
        .o_create               = osc_create,
        .o_destroy              = osc_destroy,
        .o_getattr              = osc_getattr,
        .o_setattr              = osc_setattr,
        .o_iocontrol            = osc_iocontrol,
        .o_set_info_async       = osc_set_info_async,
        .o_import_event         = osc_import_event,
        .o_quotactl             = osc_quotactl,
};

// mdc 内核模块定义,提供给客户端使用
static const struct obd_ops mdc_obd_ops = {
	.o_owner	    = THIS_MODULE,
	.o_setup	    = mdc_setup,
	.o_precleanup       = mdc_precleanup,
	.o_cleanup	    = mdc_cleanup,
	.o_add_conn	    = client_import_add_conn,
	.o_del_conn	    = client_import_del_conn,
	.o_connect	    = client_connect_import,
	.o_reconnect	    = osc_reconnect,
	.o_disconnect	    = osc_disconnect,
	.o_iocontrol	    = mdc_iocontrol,
	.o_set_info_async   = mdc_set_info_async,
	.o_statfs	    = mdc_statfs,
	.o_statfs_async     = mdc_statfs_async,
	.o_fid_init	    = client_fid_init,
	.o_fid_fini	    = client_fid_fini,
	.o_fid_alloc	    = mdc_fid_alloc,
	.o_import_event     = mdc_import_event,
	.o_get_info	    = mdc_get_info,
	.o_get_uuid	    = mdc_get_uuid,
	.o_quotactl	    = mdc_quotactl,
};

static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
{
	sbi->ll_md_obd = class_name2obd(md);
	
	// 设置超级块中struct file的操作函数(posix语义的文件操作函数)
	sbi->ll_fop = ll_select_file_operations(sbi);
	
	// 客户端连接mds,实际调用的是osc_obd_ops中的o_connect函数
	err = obd_connect(NULL, &sbi->ll_md_exp, sbi->ll_md_obd,
			  &sbi->ll_sb_uuid, data, sbi->ll_cache);

	// 本地客户端的fid初始化
	err = obd_fid_init(sbi->ll_md_exp->exp_obd, sbi->ll_md_exp,
			   LUSTRE_SEQ_METADATA);
	
	// lustre客户端超级块的设置
	sb->s_blocksize = osfs->os_bsize;
	sb->s_blocksize_bits = log2(osfs->os_bsize);
	sb->s_magic = LL_SUPER_MAGIC;
	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sbi->ll_namelen = osfs->os_namelen;
	sbi->ll_mnt.mnt = current->fs->root.mnt;
	
	// 设置超级块的oss
	sbi->ll_dt_obd = class_name2obd(dt);
	
	// 客户端连接osc,实际调用的是osc_obd_ops中的o_connect
	err = obd_connect(NULL, &sbi->ll_dt_exp, sbi->ll_dt_obd,
			  &sbi->ll_sb_uuid, data, sbi->ll_cache);
}

// 至此完成了整个mount -t lustre 10.211.55.15@tcp0:/samplefs /mnt/lustre/ 挂载
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • lustre client介绍
    • llite源代码文件说明
      • lustre客户端内核模块
        • lustre内核module
          • 客户端的mount函数执行路径
            • lustre挂载核心函数分析
            相关产品与服务
            专用宿主机
            专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档