Lustre系统工具-lfs migrate
lustre版本:2.15.4
以下所有的代码流程参考命令lfs migrate -c 2 ./abc/test.txt。
1. main
文件路径:lustre/utils/lfs.c
mian函数中调用Parser_execarg函数对用户输入的lfs命令进行解析。
int main(int argc, char **argv)
{
int rc;
// ......
if (argc > 1) {
llapi_set_command_name(argv[1]);
// 解析lfs命令和参数
rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
llapi_clear_command_name();
} else {
rc = Parser_commands();
}
// ......
}
2. Parser_execarg
文件路径:libcfs/libcfs/util/parser.c
Parser_execarg函数会从cmdlist中查找并匹配migrate命令,如果匹配成功,则执行lfs_setstripe_migrate函数。
int Parser_execarg(int argc, char **argv, command_t cmds[])
{
command_t *cmd;
// 从cmdlist中查找并匹配migrate命令
cmd = Parser_findargcmd(argv[0], cmds);
if (cmd && cmd->pc_func) {
// 执行migrate命令对应的函数
// migrate命令对应的pc_func可以从cmdlist中查看到为lfs_setstripe_migrate
int rc = cmd->pc_func(argc, argv);
if (rc == CMD_HELP)
fprintf(stderr, "%s\n", cmd->pc_help);
return rc;
}
// ......
return -1;
}
3. lfs_setstripe_migrate
文件路径:lustre/utils/lfs.c
static inline int lfs_setstripe_migrate(int argc, char **argv)
{
return lfs_setstripe_internal(argc, argv, SO_MIGRATE);
}
4. lfs_setstripe_internal
文件路径:lustre/utils/lfs.c
static int lfs_setstripe_internal(int argc, char **argv,
enum setstripe_origin opc)
{
// ......
// 以上省略的代码主要是初始化lsa
// 以上省略的代码可以得到几个关键变量
// mirror_mode=true layout=NULL from_copy=false migration_flags=0
if (migrate_mdt_mode) {
// ......
} else if (!layout) {
// ......
// 初始化param
param = calloc(1, offsetof(typeof(*param),
lsp_osts[lsa.lsa_nr_tgts]));
// 填充param参数
if (lsa.lsa_stripe_size != LLAPI_LAYOUT_DEFAULT)
param->lsp_stripe_size = lsa.lsa_stripe_size;
if (lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT) {
if (lsa.lsa_stripe_count == LLAPI_LAYOUT_WIDE)
param->lsp_stripe_count = -1;
else
param->lsp_stripe_count = lsa.lsa_stripe_count;
}
if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
param->lsp_stripe_offset = -1;
else
param->lsp_stripe_offset = lsa.lsa_stripe_off;
param->lsp_stripe_pattern =
llapi_pattern_to_lov(lsa.lsa_pattern);
if (param->lsp_stripe_pattern == EINVAL) {
fprintf(stderr, "error: %s: invalid stripe pattern\n",
argv[0]);
free(param);
goto usage_error;
}
param->lsp_pool = lsa.lsa_pool_name;
param->lsp_is_specific = false;
}
// ......
// 调用lfs_migrate函数
if (migrate_mdt_mode) {
result = llapi_migrate_mdt(fname, &migrate_mdt_param);
} else if (migrate_mode) {
result = lfs_migrate(fname, migration_flags, param,
layout);
}
// ......
}
5. lfs_migrate
文件路径:lustre/utils/lfs.c
static int lfs_migrate(char *name, __u64 migration_flags,
struct llapi_stripe_param *param,
struct llapi_layout *layout)
{
// ......
// 打开一个临时的字符设备,如果该字符设备不存在,则创建
rc = migrate_open_files(name, migration_flags, param, layout,
&fd, &fdv);
// ......
existing = llapi_layout_get_by_fd(fd, 0);
// ......
if (!(migration_flags & LLAPI_MIGRATION_NONBLOCK)) {
/*
* Blocking mode (forced if servers do not support file lease).
* It is also the default mode, since we cannot distinguish
* between a broken lease and a server that does not support
* atomic swap/close (LU-6785)
*/
rc = migrate_block(fd, fdv);
goto out;
}
// ......
}
6. migrate_open_files
文件路径:lustre/utils/lfs.c
static int migrate_open_files(const char *name, __u64 migration_flags,
const struct llapi_stripe_param *param,
struct llapi_layout *layout, int *fd_src, int *fd_tgt)
{
// 初始化父目录路径
strncpy(parent, name, sizeof(parent));
ptr = strrchr(parent, '/');
// 如果name中没有指定路径,则获取当前文件的绝对路径
if (!ptr) {
if (!getcwd(parent, sizeof(parent))) {
error_loc = "getcwd";
return -errno;
}
} else {
if (ptr == parent) /* leading '/' */
ptr = parent + 1;
*ptr = '\0';
}
// ......
// 创建一个临时字文件
do {
// 设置临时文件打开方式
int open_flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW |
/* Allow migrating without the key on encrypted files */
O_FILE_ENC;
// 设置临时文件权限
mode_t open_mode = S_IRUSR | S_IWUSR;
if (rflags & O_DIRECT)
open_flags |= O_DIRECT;
// 产生随机数
random_value = random();
// 拼接临时文件的名字,名字类似:/mnt/lustre/.0c131412:VOLATILE:0:1:fd=1
rc = snprintf(volatile_file, sizeof(volatile_file),
"%s/%s:%.4X:%.4X:fd=%.2d", parent,
LUSTRE_VOLATILE_HDR, mdt_index,
random_value, fd);
// ......
/* create, open a volatile file, use caching (ie no directio) */
if (layout) {
/* Returns -1 and sets errno on error: */
fdv = llapi_layout_file_open(volatile_file, open_flags,
open_mode, layout);
if (fdv < 0)
fdv = -errno;
} else {
/* Does the right thing on error: */
fdv = llapi_file_open_param(volatile_file, open_flags,
open_mode, param);
}
} while (fdv < 0 && (rc = fdv) == -EEXIST);
// ......
}
7. llapi_file_open_param
文件路径:lustre/utils/liblustreapi.c
int llapi_file_open_param(const char *name, int flags, mode_t mode,
const struct llapi_stripe_param *param)
{
// ......
// 打开临时文件,如果不存在,则创建
fd = open(name, flags | O_LOV_DELAY_CREATE, mode);
// ......
// 初始化lum
lum->lmm_magic = LOV_USER_MAGIC_V1;
lum->lmm_pattern = param->lsp_stripe_pattern;
lum->lmm_stripe_size = param->lsp_stripe_size;
lum->lmm_stripe_count = param->lsp_stripe_count;
lum->lmm_stripe_offset = param->lsp_stripe_offset;
// ......
// 设置临时文件的layout
if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, lum) != 0) {
// ......
}
}