mkfs_lustre实际上是一个用户空间程序,本质上是构成一个mke2fs命令并对磁盘格式化,然后挂载到临时目录,并书写server配置文件。
让我们先看一下mkfs.lustre的命令行:
[root@people ~]# mkfs.lustre mkfs.lustre v2.2.51 usage: mkfs.lustre <target types> [options] <device> <device>:block device or file (e.g /dev/sda or /tmp/ost1) target types: --ost: object storage, mutually exclusive with mdt,mgs --mdt: metadata storage, mutually exclusive with ost --mgs: configuration management service - one per site options (in order of popularity): --mgsnode=<nid>[,<...>] : NID(s) of a remote mgs node required for all targets other than the mgs node --fsname=<filesystem_name> : default is 'lustre' --failnode=<nid>[,<...>] : NID(s) of a failover partner cannot be used with --servicenode --servicenode=<nid>[,<...>] : NID(s) of all service partners treat all nodes as equal service node, cannot be used with --failnode --param <key>=<value> : set a permanent parameter e.g. --param sys.timeout=40 --param lov.stripesize=2M --index=#N : target index (i.e. ost index within lov) --comment=<user comment>: arbitrary string (824 bytes) --mountfsoptions=<opts> : permanent mount options --network=<net>[,<...>] : restrict OST/MDT to network(s) --backfstype=<fstype> : backing fs type (ext3, ldiskfs) --device-size=#N(KB) : device size for loop devices --mkfsoptions=<opts> : format options --reformat: overwrite an existing disk --stripe-count-hint=#N : for optimizing MDT inode size --iam-dir: use IAM directory format, not ext3 compatible --dryrun: just report what we would do; don't write to disk --verbose : e.g. show mkfs progress --quiet |
结构体类型:
结构体struct mkfs_opts,摘自<mkfs_lustre.c>
类型 |
域 |
描述 |
struct lustre_disk_data |
mo_ldd |
Lustre disk data,用mount –t ldiskfs挂载后,可以看到该结构体的实例内容存放在挂载目录下的CONFIGS/mountdata文件中 |
char |
mo_device[128] |
挂载的磁盘设备名 |
char |
mo_loopdev[128] |
使用loop设备的情况 |
char |
mo_mkfsopts[512] |
Backing-store fs格式化选项 |
__u64 |
mo_device_sz |
挂载设备大小,以KB为单位 |
int |
mo_stripe_count |
挂载设备条带计数(用于计算MDT的节点文件大小) |
int |
mo_flags |
挂载选项标记,比如对设备进行stat判断不是块设备时,就会将该标记| MO_IS_LOOP |
int |
mo_mgs_failnodes |
|
Table struct mkfs_opts
结构体struct lustre_disk_data,摘自<lustre/include/lustre_disk.h>,该文件的内容被存放在磁盘根目录下的CONFIGS/mountdata文件中。这个MDT/OST被看作是server,本身就是一个OSD设备,具有server name、index、所属文件系统、ldd标记(比如如需要index、注册、更新config日志)等server特性,又因为是磁盘挂载形成的server,所以具有挂载类型、挂载选项、
类型 |
域 |
描述 |
__u32 |
ldd_magic |
Lustre类型的磁盘魔数,为LDD_MAGIC |
__u32 |
ldd_feature_compat |
/* compatible feature flags */ |
__u32 |
ldd_feature_rocompat |
/* read-only compatible feature flags */ |
__u32 |
ldd_feature_incompat |
/* incompatible feature flags */ |
__u32 |
ldd_config_ver |
/* config rewrite count - not used */ |
__u32 |
ldd_flags |
/* LDD_SV_TYPE ,比如MDT/OST,可以看LDD_F_NEED_INDEX为例*/ |
__u32 |
ldd_svindex |
比如0001,必须和svname匹配 |
__u32 |
ldd_mount_type |
/* target fs type LDD_MT_* */以何种类型挂载,比如:ext3、ldiskfs等 |
char |
ldd_fsname[64] |
磁盘所属文件系统名字 |
char |
ldd_svname[64] |
Server名:比如(lustre-mdt0001) |
__u8 |
ldd_uuid[40] |
Server的UUID (COMPAT_146) |
char |
ldd_userdata[1024 - 200] |
用户数据,这个用户数据之前的成员一共占据200个字符的成员 |
__u8 |
ldd_padding[4096 - 1024] |
|
char |
ldd_mount_opts[4096] |
挂载选项 |
char |
ldd_params[4096] |
Key=value对 |
在格式化文件系统时,初始默认值为:
void set_defaults(struct mkfs_opts *mop) { mop->mo_ldd.ldd_magic = LDD_MAGIC; mop->mo_ldd.ldd_config_ver = 1; mop->mo_ldd.ldd_flags = LDD_F_NEED_INDEX | LDD_F_UPDATE | LDD_F_VIRGIN; mop->mo_mgs_failnodes = 0; strcpy(mop->mo_ldd.ldd_fsname, "lustre"); mop->mo_ldd.ldd_mount_type = LDD_MT_LDISKFS;
mop->mo_ldd.ldd_svindex = INDEX_UNASSIGNED; mop->mo_stripe_count = 1; } |
成员ldd_flags为需要分配index、更新该server的config logs、未注册,默认文件系统名ldd_fsname为lustre,挂载类型ldd_mount_type=LDD_MT_LDISKFS,该server的索引值ldd_svindex=INDEX_UNASSIGNED.
分析命令行选项,比较重要的有:
l -- iam-dir |-a:仅MDT有效,将ldd_flags |= LDD_F_IAM_DIR
l --backfstype | -b:指定ldd_mount_type,有ext3、ldiskfs等
l -- stripe-count-hint|-c:指定条带数,仅对MDT有效,mo_stripe_count= stripe_count;
l -- configdev|-C:没有使用
l --device-size|-d,指定mo_device_sz = atol(optarg)
l erase-params|-e:erase-params
/*清除参数,准备更新config logs*/ mop->mo_ldd.ldd_params[0] = '\0'; /* Must update the mgs logs */ mop->mo_ldd.ldd_flags |= LDD_F_UPDATE; |
l --failnode|-f指定failnode节点,--servicenode|-s指定service节点,这两个都可以在命令行中使用多次,但不能同时使用。这儿将产生的failover.node=optarg(处理后)加入ldd_params中。并且如果是-s,则置标记ldd_flags |= LDD_F_NO_PRIMNODE。将ldd_flags |=LDD_F_UPDATE,更新mdg log
l --mgs | -G: ldd_flags |= LDD_F_SV_TYPE_MGS是个MGS设备
l --help|-h
l --index|-i:如果ldd_flags没有设置这些位:(LDD_F_UPGRADE14 | LDD_F_VIRGIN |LDD_F_WRITECONF),则无法改变一个已注册设备的索引,return 1;否则,如果是MDT/OST:将optarg转换成atol后赋给ldd_svindex,并去掉ldd_flags | ~ LDD_F_NEED_INDEX,说明已有index了,不需要mds计算并赋给它一个index了;其他return 1。
l -- mkfsoptions | -k:将格式化选项optarg赋给mo_mkfsopts。
l --fsname|-L:如果
(!(mop->mo_flags & MO_FORCEFORMAT) && (!(mop->mo_ldd.ldd_flags & (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF)))) |
则无法改变一个已注册设备的名字,返回1;
文件系统名必须大于1,小于8,返回1;
“/:”不准出现在文件系统名中,返回1;
将文件系统名optarg拷贝到ldd_fsname
l --mgsnid|-m:分析optarg将其转化成IP@net形式,并mgsnode=IP@net加入ldd_params,然后mo_mgs_failnodes++;
l --mdt|-M:将ldd_flags |= LDD_F_SV_TYPE_MDT;
l --noformat|-n:print_only++仅打印下信息,不格式化。
l --nomgs|-N:ldd_flags &= ~LDD_F_SV_TYPE_MGS在ldd_flags中取消掉MGS类型标记;
l --mountfsoptions|-o:参数中*mountopts = optarg,以返回给该分析选项的函数的调用者;
l --ost|-O:ldd_flags |= LDD_F_SV_TYPE_OST
l --param|-p:将optarg加入到ldd_params,并且更新ldd_flags |= LDD_F_UPDATE;
l --quiet|-q:verbose--;
l --reformat|-r:mo_flags |= MO_FORCEFORMAT;
l --network|-t:必须是MDT/OST才行,否则返回1;optarg为空,返回1;将network=optarg赋给ldd_params;
l --comment|-u:将userdata拷贝到ldd_userdata;
l --verbose|-v:verbose++;
l --writeconf|-w:ldd_flags |= LDD_F_WRITECONF
l --upgrade_to_18 | -U:upgrade_to_18=1;
l 默认:如果上述都没匹配,而opt!=?就出错退出EINVAL;
如果最后分析完option后optind != argc -1,则出错退出EINVAL;
分析命令行,并赋值struct mkfs_opts实例mop及其内置的struct lustre_disk_data实例后,ldd =&mop.mo_ldd,判断ldd必须是MGS/MDT/OST中的一种,否则出错,返回错误码;判断OST不能和MDT/MGS在一个盘上:((IS_MDT(ldd) || IS_MGS(ldd))) && IS_OST(ldd),否则出错,返回错误码;判断LDD_F_NEED_INDEX | LDD_F_UPGRADE14不能同时出现;
判断ldd_mount_type如果是:LDD_MT_EXT3、LDD_MT_LDISKFS、LDD_MT_LDISKFS2:
default_mountopts[]:”,errors=remount-ro”
如果是:MDT/MGS类型:always_mountopts[]:",user_xattr"
如果是:OST且LDD_MT_LDISKFS、LDD_MT_LDISKFS2:default_mountopts[]:
",extents,mballoc"
其他ldd_mount_type出错,返回错误码
如果mountopts存在,可通过--mountfsoptions|-o赋值:
检查default_mountopts和always_mountopts中的项是否在mounts中出现,如果always_mountopts中的项在mountopts中没有出现,报错返回。
将mountopts赋值给ldd_mount_opts。
如果mountopts不存在,则将always_mountopts和default_mountopts赋值给ldd_mount_opts,并去除ldd_mount_opts中的空格等。
根据ldd的ldd_flags、ldd_svindex、ldd_fsname来决定ldd_svname:如果是MDT/OST:lustre-OST0000,MGS则是MGS。
检查mop.mo_device指定的设备是否已经挂载:setmntent/getmntent/endmntent;
判断—reformat:mop.mo_flags & MO_FORCEFORMAT,判断是lustre target,则提示需要加—reformat。
调用make_lustre_backfs(&mop)格式化backing filesystem。
<1>、命令行中指定大小和读设备文件获得的大小相比,选择使用其中的小者
->mop->mo_device_sz,而且设备大小必须>8MB。
<2>、根据mop->mo_device_sz获得4kB大小的块数,并作限制;
<3>、如果ldd_mount_type是LDD_MT_EXT3、LDD_MT_LDISKFS、LDD_MT_LDISKFS2其中的
一种,则:
(1)、如果mo_mkfsopts没有"-J",则根据盘大小来决定日志大小,”-J size=”加入
mo_mkfsopts中;
(2)、如果mo_mkfsopts没有"-I"决定inode大小,分为MDT和OST两种。MDT根据条
带数mo_stripe_count来决定inode_size。OST则inode_size=256,将-Iinode_size加
入mo_mkfsopts中;
(3)、如果mo_mkfsopts没有"-i"或”-N”,则需要来决定inode对应的文件大小,即每-i
指定大小的文件空间创建一个inode,分为MDT和OST两种。对于MDT:
bytes_per_inode = inode_size +1536,并且如果条带数mo_stripe_count> 72,就会将
mo_stripe_count * 24后按4KB对齐(每个条带多分配24字节),加到
bytes_per_inode中。
如果是OST:则需要根据设备大小来分配,如ost > 16TB,bytes_per_node = 1024 *
1024。
使能一些默认的ext4特性:不能指定多个-O选项,处理-O mkfs选项;
处理-E mkfs选项:不能指定多个-E选项,然后处理resize选项:如果设备为OST
且mo_device_sz超过100MB且块数目 < 0xffffffffULL,则为了文件系统元数据按照
1MB对齐,给定一个resize值来预留2的幂次个组描述符块,但其中至少1个块给
superblock,因为resize限制,这个仅对小于2^32块的文件系统有效。将组内块数
group_blocks=4096 * 8(块大小*8),desc_per_block=4096/32(块大小/32,ext2组
描述符占32个字节,desc_per_block是指每个块有多少个描述符),
resize_blks= (1ULL<<32) - desc_per_block*group_blocks
最后利用mke2fs -j-b 块大小 -L ldd_svname mo_mkfsopts dev制作出mke2fs命
令。并执行。
调用write_local_files(struct mkfs_opts *mop)来写serverconfig文件
<1>、首先,创建/tmp/mntXXXXXX临时目录;
<2>、检查mo_flags&MO_IS_LOOP是不是loop设备,如果是则dev=mop->mo_loopdev;
<3>、将设备dev以ldd_mount_opts方式挂载到/tmp/mntXXXXXX目录上,以ldd_mount_type
指定的ext3、ldiskfs等类型挂载;
<4>、创建/tmp/mntXXXXXX/CONFIGS/目录,因为此时磁盘已经挂载到/tmp/mntXXXXXX上,
所以是在磁盘根目录下创建CONFIGS目录。
<5>、打开/tmp/mntXXXXXX/CONFIGS/mountdata文件,调用fwrite()将mop->mo_ldd结构体
实例的内容写入该文件,注意这个lustre_disk_data结构体实例里面没有指针,如果有
则只会写指针本身,而不会自动写指针指向的内容。关闭文件。
<6>、卸载目录,并删除该临时目录/tmp/mntXXXXXX/。
如果是tunefs,则
先将/tmp/mntXXXXXX/LOGS/client拷贝到/tmp/mntXXXXXX/CONFIGS/lustre-client(lustre代指文件系统名字),
再将/tmp/mntXXXXXX/LOGS/ldd_uuid指定文件到/tmp/mntXXXXXX/CONFIGS/lustre-MDT0000