From f7f3b18128d4ec45226f5b94841fb843cc8f980b Mon Sep 17 00:00:00 2001 From: Lihong Kou Date: Thu, 16 Feb 2023 11:48:36 +0000 Subject: [PATCH 1/3] hmdfs: add root layer for cloud Signed-off-by: Lihong Kou Change-Id: I304bc8ea3d3cbca788766aa1dde0b2b842a93579 --- fs/hmdfs/file_root.c | 18 ++++++++++++++++++ fs/hmdfs/hmdfs_device_view.h | 3 +++ fs/hmdfs/inode_root.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/fs/hmdfs/file_root.c b/fs/hmdfs/file_root.c index d82ff4d0b04b..73c026de04f9 100644 --- a/fs/hmdfs/file_root.c +++ b/fs/hmdfs/file_root.c @@ -18,11 +18,13 @@ #define DEVICE_VIEW_CTX_POS 2 #define MERGE_VIEW_CTX_POS 3 +#define CLOUD_MERGE_VIEW_CTX_POS 4 #define ROOT_DIR_INO_START 20000000 // used by hmdfs_device_iterate functions #define DEVICE_VIEW_INO_START 20000002 #define LOCAL_DEVICE_CTX_POS 2 +#define CLOUD_DEVICE_CTX_POS 3 struct hmdfs_peer *get_next_con(struct hmdfs_sb_info *sbi, unsigned long current_dev_id) @@ -84,6 +86,16 @@ int hmdfs_device_iterate(struct file *file, struct dir_context *ctx) goto out; (ctx->pos)++; } + + if (ctx->pos == CLOUD_DEVICE_CTX_POS) { + err = dir_emit(ctx, DEVICE_VIEW_CLOUD, + sizeof(DEVICE_VIEW_CLOUD) - 1, ino_start++, + DT_DIR); + if (!err) + goto out; + (ctx->pos)++; + } + next_con = get_next_con(file->f_inode->i_sb->s_fs_info, 0); if (!next_con) goto out; @@ -140,6 +152,12 @@ int hmdfs_root_iterate(struct file *file, struct dir_context *ctx) return 0; (ctx->pos)++; } + if (sbi->s_merge_switch && ctx->pos == CLOUD_MERGE_VIEW_CTX_POS) { + if (!dir_emit(ctx, CLOUD_MERGE_VIEW_ROOT, sizeof(CLOUD_MERGE_VIEW_ROOT) - 1, + ino_start, DT_DIR)) + return 0; + (ctx->pos)++; + } return 0; } diff --git a/fs/hmdfs/hmdfs_device_view.h b/fs/hmdfs/hmdfs_device_view.h index 0e397254c8ea..2fc72436e216 100644 --- a/fs/hmdfs/hmdfs_device_view.h +++ b/fs/hmdfs/hmdfs_device_view.h @@ -16,9 +16,12 @@ #define DEVICE_VIEW_ROOT "device_view" #define MERGE_VIEW_ROOT "merge_view" +#define CLOUD_MERGE_VIEW_ROOT "cloud_merge_view" #define UPDATE_LOCAL_DST "/device_view/local/" +#define UPDATE_CLOUD_DST "/device_view/cloud/" #define DEVICE_VIEW_LOCAL "local" +#define DEVICE_VIEW_CLOUD "cloud" /* * in order to distinguish from vfs, we define our own bitmask, this should diff --git a/fs/hmdfs/inode_root.c b/fs/hmdfs/inode_root.c index b3b2b5c2b2fc..4c93fc4377c0 100644 --- a/fs/hmdfs/inode_root.c +++ b/fs/hmdfs/inode_root.c @@ -139,6 +139,34 @@ struct dentry *hmdfs_device_lookup(struct inode *parent_inode, hmdfs_put_reset_lower_path(child_dentry); goto out; } + } else if (!strncmp(d_name, DEVICE_VIEW_CLOUD, + sizeof(DEVICE_VIEW_CLOUD) - 1)) { + err = init_hmdfs_dentry_info(sbi, child_dentry, + HMDFS_LAYER_SECOND_LOCAL); + if (err) { + ret_dentry = ERR_PTR(err); + goto out; + } + di = hmdfs_d(sb->s_root); + root_lower_path = &(di->lower_path); + hmdfs_set_lower_path(child_dentry, root_lower_path); + path_get(root_lower_path); + root_inode = fill_device_local_inode( + sb, d_inode(root_lower_path->dentry)); + if (IS_ERR(root_inode)) { + err = PTR_ERR(root_inode); + ret_dentry = ERR_PTR(err); + hmdfs_put_reset_lower_path(child_dentry); + goto out; + } + ret_dentry = d_splice_alias(root_inode, child_dentry); + if (IS_ERR(ret_dentry)) { + err = PTR_ERR(ret_dentry); + ret_dentry = ERR_PTR(err); + hmdfs_put_reset_lower_path(child_dentry); + goto out; + } + } else { err = init_hmdfs_dentry_info(sbi, child_dentry, HMDFS_LAYER_SECOND_REMOTE); @@ -201,6 +229,11 @@ struct dentry *hmdfs_root_lookup(struct inode *parent_inode, if (ret && !IS_ERR(ret)) child_dentry = ret; root_inode = d_inode(child_dentry); + } else if (sbi->s_merge_switch && !strcmp(d_name, CLOUD_MERGE_VIEW_ROOT)) { + ret = hmdfs_lookup_merge(parent_inode, child_dentry, flags); + if (ret && !IS_ERR(ret)) + child_dentry = ret; + root_inode = d_inode(child_dentry); } else if (!strcmp(d_name, DEVICE_VIEW_ROOT)) { ret = ERR_PTR(init_hmdfs_dentry_info( sbi, child_dentry, HMDFS_LAYER_FIRST_DEVICE)); -- Gitee From a2e19e88f408e9839f6268b90bf63931a92cb296 Mon Sep 17 00:00:00 2001 From: Lihong Kou Date: Fri, 17 Feb 2023 03:09:45 +0000 Subject: [PATCH 2/3] hmdfs: lookup cloud dir from dentry file Change-Id: I6df26a798bfe08d6e4ef9d2383116fb4666210c6 Signed-off-by: Lihong Kou --- fs/hmdfs/Makefile | 1 + fs/hmdfs/dentry.c | 3 + fs/hmdfs/file_cloud.c | 121 ++++++++++ fs/hmdfs/file_remote.c | 2 +- fs/hmdfs/file_remote.h | 4 + fs/hmdfs/hmdfs.h | 1 + fs/hmdfs/hmdfs_dentryfile.c | 59 ++++- fs/hmdfs/hmdfs_dentryfile.h | 1 + fs/hmdfs/hmdfs_device_view.h | 9 + fs/hmdfs/inode.h | 6 + fs/hmdfs/inode_cloud.c | 447 +++++++++++++++++++++++++++++++++++ fs/hmdfs/inode_local.c | 1 + fs/hmdfs/inode_root.c | 40 +++- fs/hmdfs/main.c | 1 + 14 files changed, 682 insertions(+), 14 deletions(-) create mode 100644 fs/hmdfs/file_cloud.c create mode 100644 fs/hmdfs/inode_cloud.c diff --git a/fs/hmdfs/Makefile b/fs/hmdfs/Makefile index 20896e71636a..80aee290e3f6 100644 --- a/fs/hmdfs/Makefile +++ b/fs/hmdfs/Makefile @@ -7,6 +7,7 @@ hmdfs-y += inode_merge.o hmdfs_dentryfile.o file_root.o file_remote.o hmdfs-y += file_local.o client_writeback.o server_writeback.o stash.o hmdfs-y += hmdfs_share.o +hmdfs-y += file_cloud.o inode_cloud.o hmdfs-y += comm/device_node.o comm/message_verify.o comm/node_cb.o hmdfs-y += comm/connection.o comm/socket_adapter.o comm/transport.o diff --git a/fs/hmdfs/dentry.c b/fs/hmdfs/dentry.c index 8ec7ab33412f..7555fd83f1f3 100644 --- a/fs/hmdfs/dentry.c +++ b/fs/hmdfs/dentry.c @@ -186,6 +186,9 @@ static void hmdfs_dev_d_release(struct dentry *dentry) case HMDFS_LAYER_SECOND_REMOTE: hmdfs_clear_cache_dents(dentry, false); break; + case HMDFS_LAYER_SECOND_CLOUD: + hmdfs_clear_cache_dents(dentry, false); + break; default: hmdfs_err("Unexpected dentry type %d", hmdfs_d(dentry)->dentry_type); diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c new file mode 100644 index 000000000000..a5c1b0148e1d --- /dev/null +++ b/fs/hmdfs/file_cloud.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/hmdfs/file_cloud.c + * + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_remote.h" + +#include "comm/socket_adapter.h" +#include "hmdfs.h" +#include "hmdfs_client.h" +#include "hmdfs_dentryfile.h" +#include "hmdfs_trace.h" + +static const struct vm_operations_struct hmdfs_cloud_vm_ops = { + .fault = filemap_fault, + .map_pages = filemap_map_pages, + .page_mkwrite = NULL, +}; + +static int hmdfs_file_mmap_cloud(struct file *file, struct vm_area_struct *vma) +{ + vma->vm_ops = &hmdfs_cloud_vm_ops; + file_accessed(file); + + return 0; +} + +int hmdfs_file_open_cloud(struct inode *inode, struct file *file) +{ + return -ENOENT; +} + +const struct file_operations hmdfs_dev_file_fops_cloud = { + .owner = THIS_MODULE, + .llseek = generic_file_llseek, + .read_iter = NULL, + .write_iter = NULL, + .mmap = NULL, + .open = hmdfs_file_open_cloud, + .release = NULL, + .flush = NULL, + .fsync = NULL, + .splice_read = NULL, + .splice_write = NULL, +}; + + +const struct address_space_operations hmdfs_dev_file_aops_cloud = { + .readpage = NULL, + .write_begin = NULL, + .write_end = NULL, + .writepage = NULL, + .set_page_dirty = NULL, +}; + +static int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx) +{ + int err = 0; + loff_t start_pos = ctx->pos; + uint64_t dev_id = CLOUD_DEVICE; + + if (ctx->pos == -1) + return 0; + ctx->pos = hmdfs_set_pos(dev_id, 0, 0); + err = analysis_dentry_file_from_con( + file->f_inode->i_sb->s_fs_info, file, file->private_data, ctx); + + if (err <= 0) + ctx->pos = -1; + + trace_hmdfs_iterate_remote(file->f_path.dentry, start_pos, ctx->pos, + err); + return err; +} + +int hmdfs_dir_open_cloud(struct inode *inode, struct file *file) +{ + struct hmdfs_inode_info *info = hmdfs_i(inode); + struct clearcache_item *cache_item = NULL; + + get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info); + cache_item = hmdfs_find_cache_item(CLOUD_DEVICE, + file->f_path.dentry); + if (cache_item) { + file->private_data = cache_item->filp; + get_file(file->private_data); + kref_put(&cache_item->ref, release_cache_item); + return 0; + } + /* need to return -ENOENT */ + return 0; +} + +static int hmdfs_dir_release_cloud(struct inode *inode, struct file *file) +{ + if (file->private_data) + fput(file->private_data); + file->private_data = NULL; + return 0; +} + +const struct file_operations hmdfs_dev_dir_ops_cloud = { + .owner = THIS_MODULE, + .iterate = hmdfs_iterate_cloud, + .open = hmdfs_dir_open_cloud, + .release = hmdfs_dir_release_cloud, + .fsync = __generic_file_fsync, +}; diff --git a/fs/hmdfs/file_remote.c b/fs/hmdfs/file_remote.c index f9a77ddf4dcc..aac6f508e18b 100644 --- a/fs/hmdfs/file_remote.c +++ b/fs/hmdfs/file_remote.c @@ -888,7 +888,7 @@ loff_t hmdfs_set_pos(unsigned long dev_id, unsigned long group_id, return pos; } -static int analysis_dentry_file_from_con(struct hmdfs_sb_info *sbi, +int analysis_dentry_file_from_con(struct hmdfs_sb_info *sbi, struct file *file, struct file *handler, struct dir_context *ctx) diff --git a/fs/hmdfs/file_remote.h b/fs/hmdfs/file_remote.h index 026bd0c944a6..3ed9f0f20c37 100644 --- a/fs/hmdfs/file_remote.h +++ b/fs/hmdfs/file_remote.h @@ -23,4 +23,8 @@ void hmdfs_remote_add_wr_opened_inode_nolock(struct hmdfs_peer *conn, ssize_t hmdfs_file_write_iter_remote_nocheck(struct kiocb *iocb, struct iov_iter *iter); +int analysis_dentry_file_from_con(struct hmdfs_sb_info *sbi, + struct file *file, + struct file *handler, + struct dir_context *ctx); #endif diff --git a/fs/hmdfs/hmdfs.h b/fs/hmdfs/hmdfs.h index 45fcf9f9b3f3..fd964ecf2e5d 100644 --- a/fs/hmdfs/hmdfs.h +++ b/fs/hmdfs/hmdfs.h @@ -136,6 +136,7 @@ struct hmdfs_sb_info { unsigned long dcache_threshold; struct list_head client_cache; struct list_head server_cache; + struct list_head cloud_cache; struct list_head to_delete; struct mutex cache_list_lock; diff --git a/fs/hmdfs/hmdfs_dentryfile.c b/fs/hmdfs/hmdfs_dentryfile.c index 1a65e3fc479c..f9aa6fff9d4c 100644 --- a/fs/hmdfs/hmdfs_dentryfile.c +++ b/fs/hmdfs/hmdfs_dentryfile.c @@ -132,6 +132,11 @@ static int hmdfs_get_root_dentry_type(struct dentry *dentry, int *is_root) fallthrough; case HMDFS_LAYER_SECOND_LOCAL: return HMDFS_LAYER_SECOND_LOCAL; + case HMDFS_LAYER_OTHER_CLOUD: + *is_root = 0; + fallthrough; + case HMDFS_LAYER_SECOND_CLOUD: + return HMDFS_LAYER_SECOND_CLOUD; case HMDFS_LAYER_OTHER_REMOTE: *is_root = 0; fallthrough; @@ -1190,7 +1195,12 @@ struct cache_file_node *__find_cfn(struct hmdfs_sb_info *sbi, const char *cid, const char *path, bool server) { struct cache_file_node *cfn = NULL; - struct list_head *head = get_list_head(sbi, server); + struct list_head *head = NULL; + + if (!strcmp(cid, CLOUD_CID)) + head = &sbi->cloud_cache; + else + head = get_list_head(sbi, server); list_for_each_entry(cfn, head, list) { if (dentry_file_match(cfn, cid, path)) { @@ -1245,7 +1255,10 @@ static struct file *insert_cfn(struct hmdfs_sb_info *sbi, const char *filename, goto out; } - head = get_list_head(sbi, server); + if (!strcmp(cid, CLOUD_CID)) + head = &sbi->cloud_cache; + else + head = get_list_head(sbi, server); mutex_lock(&sbi->cache_list_lock); exist = __find_cfn(sbi, cid, path, server); @@ -1359,6 +1372,33 @@ struct file *cache_file_persistent(struct hmdfs_peer *con, struct file *filp, return filp; } +int get_cloud_cache_file(struct dentry *dentry, struct hmdfs_sb_info *sbi) +{ + struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); + char *relative_path = NULL; + struct cache_file_node *cfn = NULL; + char *cid = CLOUD_CID; + struct file *filp = NULL; + + relative_path = hmdfs_get_dentry_relative_path(dentry); + if (unlikely(!relative_path)) { + hmdfs_err("get relative path failed %d", -ENOMEM); + return -ENOMEM; + } + + mutex_lock(&d_info->cache_pull_lock); + cfn = find_cfn(sbi, cid, relative_path, false); + if (cfn) { + filp = cfn->filp; + release_cfn(cfn); + hmdfs_add_cache_list(CLOUD_DEVICE, dentry, filp); + } + mutex_unlock(&d_info->cache_pull_lock); + + kfree(relative_path); + return 0; +} + void __destroy_cfn(struct list_head *head) { struct cache_file_node *cfn = NULL; @@ -1375,6 +1415,7 @@ void hmdfs_cfn_destroy(struct hmdfs_sb_info *sbi) mutex_lock(&sbi->cache_list_lock); __destroy_cfn(&sbi->client_cache); __destroy_cfn(&sbi->server_cache); + __destroy_cfn(&sbi->cloud_cache); mutex_unlock(&sbi->cache_list_lock); } @@ -1570,17 +1611,20 @@ void load_cfn(struct hmdfs_sb_info *sbi, const char *fullname, const char *path, goto out; } - if (cache_get_dentry_count(sbi, cfn->filp) < sbi->dcache_threshold) { + if (cache_get_dentry_count(sbi, cfn->filp) < sbi->dcache_threshold && strcmp(cid, CLOUD_CID)) { add_to_delete_list(sbi, cfn); return; } - if (!cache_check_case_sensitive(sbi, cfn->filp)) { + if (!cache_check_case_sensitive(sbi, cfn->filp) && strcmp(cid, CLOUD_CID)) { add_to_delete_list(sbi, cfn); return; } - head = get_list_head(sbi, server); + if (!strcmp(cid, CLOUD_CID)) + head = &sbi->cloud_cache; + else + head = get_list_head(sbi, server); mutex_lock(&sbi->cache_list_lock); cfn1 = __find_cfn(sbi, cid, path, server); @@ -1653,6 +1697,7 @@ static void store_one(const char *name, struct cache_file_callback *cb) hmdfs_err("getxattr return: %zd", error); goto out_kvalue; } + kvalue[error] = '\0'; cid[0] = '\0'; @@ -1801,6 +1846,10 @@ void hmdfs_cfn_load(struct hmdfs_sb_info *sbi) snprintf(fullname, PATH_MAX, "%s/dentry_cache/server/", sbi->cache_dir); hmdfs_do_load(sbi, fullname, true); + + snprintf(fullname, PATH_MAX, "%s/dentry_cache/cloud/", + sbi->cache_dir); + hmdfs_do_load(sbi, fullname, false); kfree(fullname); hmdfs_delete_useless_cfn(sbi); diff --git a/fs/hmdfs/hmdfs_dentryfile.h b/fs/hmdfs/hmdfs_dentryfile.h index df1463007f15..0544f8bf887c 100644 --- a/fs/hmdfs/hmdfs_dentryfile.h +++ b/fs/hmdfs/hmdfs_dentryfile.h @@ -292,6 +292,7 @@ int hmdfs_metainfo_read(struct hmdfs_sb_info *sbi, struct file *filp, bool get_remote_dentry_file(struct dentry *dentry, struct hmdfs_peer *con); void get_remote_dentry_file_sync(struct dentry *dentry, struct hmdfs_peer *con); +int get_cloud_cache_file(struct dentry *dentry, struct hmdfs_sb_info *sbi); void release_cache_item(struct kref *ref); void remove_cache_item(struct clearcache_item *item); diff --git a/fs/hmdfs/hmdfs_device_view.h b/fs/hmdfs/hmdfs_device_view.h index 2fc72436e216..6e53af7bf2bf 100644 --- a/fs/hmdfs/hmdfs_device_view.h +++ b/fs/hmdfs/hmdfs_device_view.h @@ -22,6 +22,8 @@ #define DEVICE_VIEW_LOCAL "local" #define DEVICE_VIEW_CLOUD "cloud" +#define CLOUD_CID "cloud" +#define CLOUD_DEVICE (1) /* * in order to distinguish from vfs, we define our own bitmask, this should @@ -101,6 +103,13 @@ extern const struct file_operations hmdfs_dev_file_fops_remote; extern const struct address_space_operations hmdfs_dev_file_aops_remote; extern const struct inode_operations hmdfs_dev_dir_inode_ops_remote; extern const struct file_operations hmdfs_dev_dir_ops_remote; + +/* cloud device operation */ +extern const struct inode_operations hmdfs_dev_file_iops_cloud; +extern const struct file_operations hmdfs_dev_file_fops_cloud; +extern const struct address_space_operations hmdfs_dev_file_aops_cloud; +extern const struct inode_operations hmdfs_dev_dir_inode_ops_cloud; +extern const struct file_operations hmdfs_dev_dir_ops_cloud; extern int hmdfs_dev_unlink_from_con(struct hmdfs_peer *conn, struct dentry *dentry); extern int hmdfs_dev_readdir_from_con(struct hmdfs_peer *con, struct file *file, diff --git a/fs/hmdfs/inode.h b/fs/hmdfs/inode.h index 47f189f3cf82..9619b5bb2792 100644 --- a/fs/hmdfs/inode.h +++ b/fs/hmdfs/inode.h @@ -202,7 +202,9 @@ enum HMDFS_ROOT { HMDFS_ROOT_DEV, // /device_view HMDFS_ROOT_DEV_LOCAL, // /device_view/local HMDFS_ROOT_DEV_REMOTE, // /device_view/remote + HMDFS_ROOT_DEV_CLOUD, // /device_view/cloud HMDFS_ROOT_MERGE, // /merge_view + HMDFS_ROOT_MERGE_CLOUD, // /cloud_merge_view HMDFS_ROOT_INVALID, }; @@ -213,11 +215,15 @@ enum HMDFS_LAYER_TYPE { HMDFS_LAYER_FIRST_DEVICE, // /device_view HMDFS_LAYER_SECOND_LOCAL, // /device_view/local HMDFS_LAYER_SECOND_REMOTE, // /device_view/remote + HMDFS_LAYER_SECOND_CLOUD, // /device_view/cloud HMDFS_LAYER_OTHER_LOCAL, // /device_view/local/xx HMDFS_LAYER_OTHER_REMOTE, // /device_view/remote/xx + HMDFS_LAYER_OTHER_CLOUD, // /device_view/cloud/xx HMDFS_LAYER_FIRST_MERGE, // /merge_view HMDFS_LAYER_OTHER_MERGE, // /merge_view/xxx + HMDFS_LAYER_FIRST_MERGE_CLOUD, // /cloud_merge_view + HMDFS_LAYER_OTHER_MERGE_CLOUD, // /coud_merge_view/xxx HMDFS_LAYER_INVALID, }; diff --git a/fs/hmdfs/inode_cloud.c b/fs/hmdfs/inode_cloud.c new file mode 100644 index 000000000000..8bdc1eefcd45 --- /dev/null +++ b/fs/hmdfs/inode_cloud.c @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/hmdfs/inode_cloud.c + * + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + */ + +#include +#include +#include +#include + +#include "comm/socket_adapter.h" +#include "hmdfs.h" +#include "hmdfs_client.h" +#include "hmdfs_dentryfile.h" +#include "hmdfs_share.h" +#include "hmdfs_trace.h" +#include "authority/authentication.h" +#include "stash.h" + +struct hmdfs_lookup_ret *lookup_cloud_dentry(struct dentry *child_dentry, + const struct qstr *qstr, + uint64_t dev_id) +{ + struct hmdfs_lookup_ret *lookup_ret; + struct hmdfs_dentry *dentry = NULL; + struct clearcache_item *cache_item = NULL; + struct hmdfs_dcache_lookup_ctx ctx; + struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); + + + get_cloud_cache_file(child_dentry->d_parent, sbi); + cache_item = hmdfs_find_cache_item(dev_id, child_dentry->d_parent); + if (!cache_item) + return NULL; + + lookup_ret = kmalloc(sizeof(*lookup_ret), GFP_KERNEL); + if (!lookup_ret) + goto out; + + hmdfs_init_dcache_lookup_ctx(&ctx, sbi, qstr, cache_item->filp); + dentry = hmdfs_find_dentry(child_dentry, &ctx); + if (!dentry) { + kfree(lookup_ret); + lookup_ret = NULL; + goto out; + } + + lookup_ret->i_mode = le16_to_cpu(dentry->i_mode); + lookup_ret->i_size = le64_to_cpu(dentry->i_size); + lookup_ret->i_mtime = le64_to_cpu(dentry->i_mtime); + lookup_ret->i_mtime_nsec = le32_to_cpu(dentry->i_mtime_nsec); + lookup_ret->i_ino = le64_to_cpu(dentry->i_ino); + + hmdfs_unlock_file(ctx.filp, get_dentry_group_pos(ctx.bidx), + DENTRYGROUP_SIZE); + kfree(ctx.page); +out: + kref_put(&cache_item->ref, release_cache_item); + return lookup_ret; +} + +struct hmdfs_lookup_ret *hmdfs_lookup_by_cloud(struct dentry *dentry, + struct qstr *qstr, + unsigned int flags, + const char *relative_path) +{ + struct hmdfs_lookup_ret *result = NULL; + + result = lookup_cloud_dentry(dentry, qstr, CLOUD_DEVICE); + return result; +} + +/* + * hmdfs_update_inode_size - update inode size when finding aready existed + * inode. + * + * First of all, if the file is opened for writing, we don't update inode size + * here, because inode size is about to be changed after writing. + * + * If the file is not opened, simply update getattr_isize(not actual inode size, + * just a value showed to user). This is safe because inode size will be + * up-to-date after open. + * + * If the file is opened for read: + * a. getattr_isize == HMDFS_STALE_REMOTE_ISIZE + * 1) i_size == new_size, nothing need to be done. + * 2) i_size > new_size, we keep the i_size and set getattr_isize to new_size, + * stale data might be readed in this case, which is fine because file is + * opened before remote truncate the file. + * 3) i_size < new_size, we drop the last page of the file if i_size is not + * aligned to PAGE_SIZE, clear getattr_isize, and update i_size to + * new_size. + * b. getattr_isize != HMDFS_STALE_REMOTE_ISIZE, getattr_isize will only be set + * after 2). + * 4) getattr_isize > i_size, this situation is impossible. + * 5) i_size >= new_size, this case is the same as 2). + * 6) i_size < new_size, this case is the same as 3). + */ +static void hmdfs_update_inode_size(struct inode *inode, uint64_t new_size) +{ + struct hmdfs_inode_info *info = hmdfs_i(inode); + int writecount; + uint64_t size; + + inode_lock(inode); + size = info->getattr_isize; + if (size == HMDFS_STALE_REMOTE_ISIZE) + size = i_size_read(inode); + if (size == new_size) { + inode_unlock(inode); + return; + } + + writecount = atomic_read(&inode->i_writecount); + /* check if writing is in progress */ + if (writecount > 0) { + info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE; + inode_unlock(inode); + return; + } + + /* check if there is no one who opens the file */ + if (kref_read(&info->ref) == 0) + goto update_info; + + /* check if there is someone who opens the file for read */ + if (writecount == 0) { + uint64_t aligned_size; + + /* use inode size here instead of getattr_isize */ + size = i_size_read(inode); + if (new_size <= size) + goto update_info; + /* + * if the old inode size is not aligned to HMDFS_PAGE_SIZE, we + * need to drop the last page of the inode, otherwise zero will + * be returned while reading the new range in the page after + * chaning inode size. + */ + aligned_size = round_down(size, HMDFS_PAGE_SIZE); + if (aligned_size != size) + truncate_inode_pages(inode->i_mapping, aligned_size); + i_size_write(inode, new_size); + info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE; + inode_unlock(inode); + return; + } + +update_info: + info->getattr_isize = new_size; + inode_unlock(inode); +} + +static void hmdfs_update_inode(struct inode *inode, + struct hmdfs_lookup_ret *lookup_result) +{ + struct hmdfs_time_t remote_mtime = { + .tv_sec = lookup_result->i_mtime, + .tv_nsec = lookup_result->i_mtime_nsec, + }; + + /* + * We only update mtime if the file is not opened for writing. If we do + * update it before writing is about to start, user might see the mtime + * up-and-down if system time in server and client do not match. However + * mtime in client will eventually match server after timeout without + * writing. + */ + if (!inode_is_open_for_write(inode)) + inode->i_mtime = remote_mtime; + + /* + * We don't care i_size of dir, and lock inode for dir + * might cause deadlock. + */ + if (S_ISREG(inode->i_mode)) + hmdfs_update_inode_size(inode, lookup_result->i_size); +} + +static void hmdfs_fill_inode_permission(struct inode *inode, struct inode *dir, + umode_t mode) +{ +#ifdef CONFIG_HMDFS_FS_PERMISSION + inode->i_uid = dir->i_uid; + inode->i_gid = dir->i_gid; +#endif +} + +struct hmdfs_peer peer; + +struct inode *fill_inode_cloud(struct super_block *sb, struct hmdfs_lookup_ret *res, struct inode *dir) +{ + int ret = 0; + struct inode *inode = NULL; + struct hmdfs_inode_info *info; + umode_t mode = res->i_mode; + peer.device_id = CLOUD_DEVICE; + + inode = hmdfs_iget5_locked_remote(sb, &peer, res->i_ino); + if (!inode) + return ERR_PTR(-ENOMEM); + + info = hmdfs_i(inode); + info->inode_type = HMDFS_LAYER_OTHER_CLOUD; + /* the inode was found in cache */ + if (!(inode->i_state & I_NEW)) { + hmdfs_fill_inode_permission(inode, dir, mode); + hmdfs_update_inode(inode, res); + return inode; + } + + inode->i_ctime.tv_sec = 0; + inode->i_ctime.tv_nsec = 0; + inode->i_mtime.tv_sec = res->i_mtime; + inode->i_mtime.tv_nsec = res->i_mtime_nsec; + + inode->i_uid = KUIDT_INIT((uid_t)0); + inode->i_gid = KGIDT_INIT((gid_t)0); + + if (S_ISDIR(mode)) + inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH; + else if (S_ISREG(mode)) + inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + else { + ret = -EIO; + goto bad_inode; + } + + if (S_ISREG(mode)) { + inode->i_op = &hmdfs_dev_file_iops_cloud; + inode->i_fop = &hmdfs_dev_file_fops_cloud; + inode->i_size = res->i_size; + set_nlink(inode, 1); + } else if (S_ISDIR(mode)) { + inode->i_op = &hmdfs_dev_dir_inode_ops_cloud; + inode->i_fop = &hmdfs_dev_dir_ops_cloud; + set_nlink(inode, 2); + } else { + ret = -EIO; + goto bad_inode; + } + + inode->i_mapping->a_ops = &hmdfs_dev_file_aops_cloud; + + hmdfs_fill_inode_permission(inode, dir, mode); + unlock_new_inode(inode); + return inode; +bad_inode: + iget_failed(inode); + return ERR_PTR(ret); +} + +static struct dentry *hmdfs_lookup_cloud_dentry(struct inode *parent_inode, + struct dentry *child_dentry, + int flags) +{ + struct dentry *ret = NULL; + struct inode *inode = NULL; + struct super_block *sb = parent_inode->i_sb; + struct hmdfs_sb_info *sbi = sb->s_fs_info; + struct hmdfs_lookup_ret *lookup_result = NULL; + char *file_name = NULL; + int file_name_len = child_dentry->d_name.len; + struct qstr qstr; + struct hmdfs_dentry_info *gdi = hmdfs_d(child_dentry); + uint64_t device_id = 0; + char *relative_path = NULL; + + file_name = kzalloc(NAME_MAX + 1, GFP_KERNEL); + if (!file_name) + return ERR_PTR(-ENOMEM); + strncpy(file_name, child_dentry->d_name.name, file_name_len); + + qstr.name = file_name; + qstr.len = strlen(file_name); + + relative_path = hmdfs_get_dentry_relative_path(child_dentry->d_parent); + if (unlikely(!relative_path)) { + ret = ERR_PTR(-ENOMEM); + hmdfs_err("get relative path failed %d", -ENOMEM); + goto done; + } + + lookup_result = hmdfs_lookup_by_cloud(child_dentry, &qstr, flags, + relative_path); + if (lookup_result != NULL) { + if (in_share_dir(child_dentry)) + gdi->file_type = HM_SHARE; + inode = fill_inode_cloud(sb, lookup_result, parent_inode); + ret = d_splice_alias(inode, child_dentry); + if (!IS_ERR_OR_NULL(ret)) + child_dentry = ret; + if (!IS_ERR(ret)) + check_and_fixup_ownership_remote(parent_inode, + child_dentry); + } else { + ret = ERR_PTR(-ENOENT); + } + +done: + kfree(relative_path); + kfree(lookup_result); + kfree(file_name); + return ret; +} + +struct dentry *hmdfs_lookup_cloud(struct inode *parent_inode, + struct dentry *child_dentry, + unsigned int flags) +{ + int err = 0; + struct dentry *ret = NULL; + struct hmdfs_dentry_info *gdi = NULL; + struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); + + trace_hmdfs_lookup_remote(parent_inode, child_dentry, flags); + if (child_dentry->d_name.len > NAME_MAX) { + err = -ENAMETOOLONG; + ret = ERR_PTR(-ENAMETOOLONG); + goto out; + } + + err = init_hmdfs_dentry_info(sbi, child_dentry, + HMDFS_LAYER_OTHER_CLOUD); + if (err) { + ret = ERR_PTR(err); + goto out; + } + gdi = hmdfs_d(child_dentry); + gdi->device_id = hmdfs_d(child_dentry->d_parent)->device_id; + + ret = hmdfs_lookup_cloud_dentry(parent_inode, child_dentry, flags); + /* + * don't return error if inode do not exist, so that vfs can continue + * to create it. + */ + if (IS_ERR_OR_NULL(ret)) { + err = PTR_ERR(ret); + if (err == -ENOENT) + ret = NULL; + } else { + child_dentry = ret; + } + +out: + if (!err) + hmdfs_set_time(child_dentry, jiffies); + trace_hmdfs_lookup_remote_end(parent_inode, child_dentry, err); + return ret; +} + +int hmdfs_mkdir_cloud(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + return -EPERM; +} + +int hmdfs_create_cloud(struct inode *dir, struct dentry *dentry, umode_t mode, + bool want_excl) +{ + return -EPERM; +} + +int hmdfs_rmdir_cloud(struct inode *dir, struct dentry *dentry) +{ + return -EPERM; +} + +int hmdfs_unlink_cloud(struct inode *dir, struct dentry *dentry) +{ + return -EPERM; +} + +int hmdfs_rename_cloud(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + return -EPERM; +} + +static int hmdfs_dir_setattr_cloud(struct dentry *dentry, struct iattr *ia) +{ + // Do not support dir setattr + return 0; +} + +const struct inode_operations hmdfs_dev_dir_inode_ops_cloud = { + .lookup = hmdfs_lookup_cloud, + .mkdir = hmdfs_mkdir_cloud, + .create = hmdfs_create_cloud, + .rmdir = hmdfs_rmdir_cloud, + .unlink = hmdfs_unlink_cloud, + .rename = hmdfs_rename_cloud, + .setattr = hmdfs_dir_setattr_cloud, + .permission = hmdfs_permission, +}; + +static int hmdfs_setattr_cloud(struct dentry *dentry, struct iattr *ia) +{ + struct hmdfs_inode_info *info = hmdfs_i(d_inode(dentry)); + struct inode *inode = d_inode(dentry); + int err = 0; + + if (hmdfs_inode_is_stashing(info)) + return -EAGAIN; + + if (ia->ia_valid & ATTR_SIZE) { + err = inode_newsize_ok(inode, ia->ia_size); + if (err) + return err; + truncate_setsize(inode, ia->ia_size); + info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE; + } + if (ia->ia_valid & ATTR_MTIME) + inode->i_mtime = ia->ia_mtime; + + return err; +} + + +static int hmdfs_get_cached_attr_cloud(const struct path *path, + struct kstat *stat, u32 request_mask, + unsigned int flags) +{ + struct inode *inode = d_inode(path->dentry); + struct hmdfs_inode_info *info = hmdfs_i(inode); + uint64_t size = info->getattr_isize; + + stat->ino = inode->i_ino; + stat->mtime = inode->i_mtime; + stat->mode = inode->i_mode; + stat->uid.val = inode->i_uid.val; + stat->gid.val = inode->i_gid.val; + if (size == HMDFS_STALE_REMOTE_ISIZE) + size = i_size_read(inode); + + stat->size = size; + return 0; +} + +const struct inode_operations hmdfs_dev_file_iops_cloud = { + .setattr = hmdfs_setattr_cloud, + .permission = hmdfs_permission, + .getattr = hmdfs_get_cached_attr_cloud, + .listxattr = NULL, +}; diff --git a/fs/hmdfs/inode_local.c b/fs/hmdfs/inode_local.c index 2470c5f81aec..a06e5066ed06 100644 --- a/fs/hmdfs/inode_local.c +++ b/fs/hmdfs/inode_local.c @@ -50,6 +50,7 @@ int init_hmdfs_dentry_info(struct hmdfs_sb_info *sbi, struct dentry *dentry, if (dentry_type == HMDFS_LAYER_ZERO || dentry_type == HMDFS_LAYER_FIRST_DEVICE || dentry_type == HMDFS_LAYER_SECOND_LOCAL || + dentry_type == HMDFS_LAYER_SECOND_CLOUD || dentry_type == HMDFS_LAYER_SECOND_REMOTE) d_set_d_op(dentry, &hmdfs_dev_dops); else diff --git a/fs/hmdfs/inode_root.c b/fs/hmdfs/inode_root.c index 4c93fc4377c0..beb1819f7b92 100644 --- a/fs/hmdfs/inode_root.c +++ b/fs/hmdfs/inode_root.c @@ -96,6 +96,36 @@ static struct inode *fill_device_inode_remote(struct super_block *sb, return inode; } +static struct inode *fill_device_inode_cloud(struct super_block *sb) +{ + struct inode *inode = NULL; + struct hmdfs_inode_info *info = NULL; + + inode = hmdfs_iget_locked_root(sb, HMDFS_ROOT_DEV_CLOUD, NULL, NULL); + if (!inode) { + hmdfs_err("get inode NULL"); + inode = ERR_PTR(-ENOMEM); + goto out; + } + if (!(inode->i_state & I_NEW)) + goto out; + + info = hmdfs_i(inode); + info->inode_type = HMDFS_LAYER_SECOND_CLOUD; + + inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH; + + inode->i_uid = KUIDT_INIT((uid_t)1000); + inode->i_gid = KGIDT_INIT((gid_t)1000); + inode->i_op = &hmdfs_dev_dir_inode_ops_cloud; + inode->i_fop = &hmdfs_dev_dir_ops_cloud; + + unlock_new_inode(inode); + +out: + return inode; +} + struct dentry *hmdfs_device_lookup(struct inode *parent_inode, struct dentry *child_dentry, unsigned int flags) @@ -142,28 +172,22 @@ struct dentry *hmdfs_device_lookup(struct inode *parent_inode, } else if (!strncmp(d_name, DEVICE_VIEW_CLOUD, sizeof(DEVICE_VIEW_CLOUD) - 1)) { err = init_hmdfs_dentry_info(sbi, child_dentry, - HMDFS_LAYER_SECOND_LOCAL); + HMDFS_LAYER_SECOND_CLOUD); if (err) { ret_dentry = ERR_PTR(err); goto out; } di = hmdfs_d(sb->s_root); - root_lower_path = &(di->lower_path); - hmdfs_set_lower_path(child_dentry, root_lower_path); - path_get(root_lower_path); - root_inode = fill_device_local_inode( - sb, d_inode(root_lower_path->dentry)); + root_inode = fill_device_inode_cloud(sb); if (IS_ERR(root_inode)) { err = PTR_ERR(root_inode); ret_dentry = ERR_PTR(err); - hmdfs_put_reset_lower_path(child_dentry); goto out; } ret_dentry = d_splice_alias(root_inode, child_dentry); if (IS_ERR(ret_dentry)) { err = PTR_ERR(ret_dentry); ret_dentry = ERR_PTR(err); - hmdfs_put_reset_lower_path(child_dentry); goto out; } diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index cb3034e95651..3d5f8706386c 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -907,6 +907,7 @@ static int hmdfs_fill_super(struct super_block *sb, void *data, int silent) sbi->cred = get_cred(current_cred()); INIT_LIST_HEAD(&sbi->client_cache); INIT_LIST_HEAD(&sbi->server_cache); + INIT_LIST_HEAD(&sbi->cloud_cache); INIT_LIST_HEAD(&sbi->to_delete); mutex_init(&sbi->cache_list_lock); hmdfs_cfn_load(sbi); -- Gitee From e7fe0f89568fe865a7195b09b9bdd0ee3f6cd1e7 Mon Sep 17 00:00:00 2001 From: Lihong Kou Date: Mon, 20 Feb 2023 02:22:36 +0000 Subject: [PATCH 3/3] hmdfs: add cloud merge files Change-Id: Ida30c6f6a333cc9123b9b302de0d51667802dd0d Signed-off-by: Lihong Kou --- fs/hmdfs/Makefile | 1 + fs/hmdfs/file_cloud.c | 9 - fs/hmdfs/hmdfs_merge_view.h | 44 ++- fs/hmdfs/inode_cloud.c | 2 - fs/hmdfs/inode_cloud_merge.c | 610 +++++++++++++++++++++++++++++++++++ fs/hmdfs/inode_merge.c | 28 +- fs/hmdfs/inode_root.c | 2 +- 7 files changed, 669 insertions(+), 27 deletions(-) create mode 100644 fs/hmdfs/inode_cloud_merge.c diff --git a/fs/hmdfs/Makefile b/fs/hmdfs/Makefile index 80aee290e3f6..d6fee84b9f3f 100644 --- a/fs/hmdfs/Makefile +++ b/fs/hmdfs/Makefile @@ -8,6 +8,7 @@ hmdfs-y += file_local.o client_writeback.o server_writeback.o stash.o hmdfs-y += hmdfs_share.o hmdfs-y += file_cloud.o inode_cloud.o +hmdfs-y += inode_cloud_merge.o hmdfs-y += comm/device_node.o comm/message_verify.o comm/node_cb.o hmdfs-y += comm/connection.o comm/socket_adapter.o comm/transport.o diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c index a5c1b0148e1d..03cf3da0166b 100644 --- a/fs/hmdfs/file_cloud.c +++ b/fs/hmdfs/file_cloud.c @@ -30,14 +30,6 @@ static const struct vm_operations_struct hmdfs_cloud_vm_ops = { .page_mkwrite = NULL, }; -static int hmdfs_file_mmap_cloud(struct file *file, struct vm_area_struct *vma) -{ - vma->vm_ops = &hmdfs_cloud_vm_ops; - file_accessed(file); - - return 0; -} - int hmdfs_file_open_cloud(struct inode *inode, struct file *file) { return -ENOENT; @@ -88,7 +80,6 @@ static int hmdfs_iterate_cloud(struct file *file, struct dir_context *ctx) int hmdfs_dir_open_cloud(struct inode *inode, struct file *file) { - struct hmdfs_inode_info *info = hmdfs_i(inode); struct clearcache_item *cache_item = NULL; get_cloud_cache_file(file->f_path.dentry, file->f_inode->i_sb->s_fs_info); diff --git a/fs/hmdfs/hmdfs_merge_view.h b/fs/hmdfs/hmdfs_merge_view.h index f7d21cc5bd7f..13c2666a91ee 100644 --- a/fs/hmdfs/hmdfs_merge_view.h +++ b/fs/hmdfs/hmdfs_merge_view.h @@ -59,6 +59,7 @@ struct hmdfs_recursive_para { bool want_excl; const char *name; }; + static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry) { return dentry->d_fsdata; @@ -74,14 +75,53 @@ static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade) return comrade->dev_id == HMDFS_DEVID_LOCAL; } +struct hmdfs_cache_entry *allocate_entry(const char *name, int namelen, + int d_type); + +struct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode, + struct dentry *child_dentry, + unsigned int flags); + struct dentry *hmdfs_lookup_merge(struct inode *parent_inode, struct dentry *child_dentry, unsigned int flags); +struct hmdfs_file_info * +get_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id); +struct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head, + int device_id); +int insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry); struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id); - +int check_filename(const char *name, int len); +int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi, + struct dentry *dentry); +void hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para, + int opcode, mode_t mode, bool want_excl, + const char *name); void link_comrade(struct list_head *onstack_comrades_head, struct hmdfs_dentry_comrade *comrade); +void update_inode_attr(struct inode *inode, struct dentry *child_dentry); +int get_num_comrades(struct dentry *dentry); +void assign_comrades_unlocked(struct dentry *child_dentry, + struct list_head *onstack_comrades_head); +struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path, + const char *d_name, + int dev_id, + unsigned int flags); +int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, + struct hmdfs_sb_info *sbi, int devid, + const char *name, unsigned int flags); +char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type); +void lock_root_inode_shared(struct inode *root, bool *locked, bool *down); +void restore_root_inode_sem(struct inode *root, bool locked, bool down); +int hmdfs_getattr_merge(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int flags); +int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia); +int hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry); +int hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry); +int hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags); static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade) { @@ -190,6 +230,8 @@ extern const struct inode_operations hmdfs_file_iops_merge; extern const struct file_operations hmdfs_file_fops_merge; extern const struct inode_operations hmdfs_dir_iops_merge; extern const struct file_operations hmdfs_dir_fops_merge; +extern const struct inode_operations hmdfs_file_iops_cloud_merge; +extern const struct inode_operations hmdfs_dir_iops_cloud_merge; extern const struct dentry_operations hmdfs_dops_merge; /***************************************************************************** diff --git a/fs/hmdfs/inode_cloud.c b/fs/hmdfs/inode_cloud.c index 8bdc1eefcd45..3d24c3b4f2f0 100644 --- a/fs/hmdfs/inode_cloud.c +++ b/fs/hmdfs/inode_cloud.c @@ -259,13 +259,11 @@ static struct dentry *hmdfs_lookup_cloud_dentry(struct inode *parent_inode, struct dentry *ret = NULL; struct inode *inode = NULL; struct super_block *sb = parent_inode->i_sb; - struct hmdfs_sb_info *sbi = sb->s_fs_info; struct hmdfs_lookup_ret *lookup_result = NULL; char *file_name = NULL; int file_name_len = child_dentry->d_name.len; struct qstr qstr; struct hmdfs_dentry_info *gdi = hmdfs_d(child_dentry); - uint64_t device_id = 0; char *relative_path = NULL; file_name = kzalloc(NAME_MAX + 1, GFP_KERNEL); diff --git a/fs/hmdfs/inode_cloud_merge.c b/fs/hmdfs/inode_cloud_merge.c new file mode 100644 index 000000000000..820ea7e76311 --- /dev/null +++ b/fs/hmdfs/inode_cloud_merge.c @@ -0,0 +1,610 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/hmdfs/inode_cloud_merge.c + * + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + */ + +#include "hmdfs_merge_view.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "authority/authentication.h" +#include "hmdfs_trace.h" + +static struct inode *fill_inode_merge(struct super_block *sb, + struct inode *parent_inode, + struct dentry *child_dentry, + struct dentry *lo_d_dentry) +{ + int ret = 0; + struct dentry *fst_lo_d = NULL; + struct hmdfs_inode_info *info = NULL; + struct inode *inode = NULL; + umode_t mode; + + if (lo_d_dentry) { + fst_lo_d = lo_d_dentry; + dget(fst_lo_d); + } else { + fst_lo_d = hmdfs_get_fst_lo_d(child_dentry); + } + if (!fst_lo_d) { + inode = ERR_PTR(-EINVAL); + goto out; + } + if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO) + inode = hmdfs_iget_locked_root(sb, HMDFS_ROOT_MERGE, NULL, + NULL); + else + inode = hmdfs_iget5_locked_merge(sb, fst_lo_d); + if (!inode) { + hmdfs_err("iget5_locked get inode NULL"); + inode = ERR_PTR(-ENOMEM); + goto out; + } + if (!(inode->i_state & I_NEW)) + goto out; + info = hmdfs_i(inode); + if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO) + info->inode_type = HMDFS_LAYER_FIRST_MERGE; + else + info->inode_type = HMDFS_LAYER_OTHER_MERGE; + + inode->i_uid = KUIDT_INIT((uid_t)0); + inode->i_gid = KGIDT_INIT((gid_t)0); + + update_inode_attr(inode, child_dentry); + mode = d_inode(fst_lo_d)->i_mode; + + if (S_ISREG(mode)) { + inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + inode->i_op = &hmdfs_file_iops_cloud_merge; + inode->i_fop = &hmdfs_file_fops_merge; + set_nlink(inode, 1); + } else if (S_ISDIR(mode)) { + inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH; + inode->i_op = &hmdfs_dir_iops_cloud_merge; + inode->i_fop = &hmdfs_dir_fops_merge; + set_nlink(inode, get_num_comrades(child_dentry) + 2); + } else { + ret = -EIO; + goto bad_inode; + } + + unlock_new_inode(inode); +out: + dput(fst_lo_d); + return inode; +bad_inode: + iget_failed(inode); + return ERR_PTR(ret); +} + +static int lookup_merge_normal(struct dentry *dentry, unsigned int flags) +{ + int ret = -ENOMEM; + int err = 0; + int devid = -1; + struct dentry *pdentry = dget_parent(dentry); + struct hmdfs_dentry_info_merge *mdi = hmdfs_dm(dentry); + struct hmdfs_sb_info *sbi = hmdfs_sb(dentry->d_sb); + char *rname, *ppath, *cpath; + + rname = hmdfs_get_real_dname(dentry, &devid, &mdi->type); + if (unlikely(!rname)) { + goto out; + } + + ppath = hmdfs_merge_get_dentry_relative_path(pdentry); + if (unlikely(!ppath)) { + hmdfs_err("failed to get parent relative path"); + goto out_rname; + } + + cpath = kzalloc(PATH_MAX, GFP_KERNEL); + if (unlikely(!cpath)) { + hmdfs_err("failed to get child device_view path"); + goto out_ppath; + } + + mutex_lock(&mdi->work_lock); + mutex_lock(&sbi->connections.node_lock); + if (mdi->type != DT_REG || devid == 0) { + snprintf(cpath, PATH_MAX, "device_view/local%s/%s", ppath, + rname); + err = merge_lookup_async(mdi, sbi, 0, cpath, flags); + if (err) + hmdfs_err("failed to create local lookup work"); + } + + snprintf(cpath, PATH_MAX, "device_view/%s%s/%s", CLOUD_CID, + ppath, rname); + err = merge_lookup_async(mdi, sbi, CLOUD_DEVICE, cpath, + flags); + if (err) + hmdfs_err("failed lookup cloud"); + mutex_unlock(&sbi->connections.node_lock); + mutex_unlock(&mdi->work_lock); + + wait_event(mdi->wait_queue, is_merge_lookup_end(mdi)); + + ret = -ENOENT; + if (!is_comrade_list_empty(mdi)) + ret = 0; + + kfree(cpath); +out_ppath: + kfree(ppath); +out_rname: + kfree(rname); +out: + dput(pdentry); + return ret; +} + +/** + * do_lookup_merge_root - lookup the root of the merge view(root/merge_view) + * + * It's common for a network filesystem to incur various of faults, so we + * intent to show mercy for faults here, except faults reported by the local. + */ +static int do_lookup_cloud_merge_root(struct path path_dev, + struct dentry *child_dentry, unsigned int flags) +{ + struct hmdfs_dentry_comrade *comrade; + const int buf_len = + max((int)HMDFS_CID_SIZE + 1, (int)sizeof(DEVICE_VIEW_LOCAL)); + char *buf = kzalloc(buf_len, GFP_KERNEL); + LIST_HEAD(head); + int ret; + + if (!buf) + return -ENOMEM; + + // lookup real_dst/device_view/local + memcpy(buf, DEVICE_VIEW_LOCAL, sizeof(DEVICE_VIEW_LOCAL)); + comrade = lookup_comrade(path_dev, buf, HMDFS_DEVID_LOCAL, flags); + if (IS_ERR(comrade)) { + ret = PTR_ERR(comrade); + goto out; + } + link_comrade(&head, comrade); + + memcpy(buf, CLOUD_CID, 6); + buf[5] = '\0'; + comrade = lookup_comrade(path_dev, buf, CLOUD_DEVICE, flags); + if (IS_ERR(comrade)) { + ret = PTR_ERR(comrade); + goto out; + } + + link_comrade(&head, comrade); + + assign_comrades_unlocked(child_dentry, &head); + ret = 0; + +out: + kfree(buf); + return ret; +} + +static int lookup_cloud_merge_root(struct inode *root_inode, + struct dentry *child_dentry, unsigned int flags) +{ + struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); + struct path path_dev; + int ret = -ENOENT; + int buf_len; + char *buf = NULL; + bool locked, down; + + // consider additional one slash and one '\0' + buf_len = strlen(sbi->real_dst) + 1 + sizeof(DEVICE_VIEW_ROOT); + if (buf_len > PATH_MAX) + return -ENAMETOOLONG; + + buf = kmalloc(buf_len, GFP_KERNEL); + if (unlikely(!buf)) + return -ENOMEM; + + sprintf(buf, "%s/%s", sbi->real_dst, DEVICE_VIEW_ROOT); + lock_root_inode_shared(root_inode, &locked, &down); + ret = hmdfs_get_path_in_sb(child_dentry->d_sb, buf, LOOKUP_DIRECTORY, + &path_dev); + if (ret) + goto free_buf; + + ret = do_lookup_cloud_merge_root(path_dev, child_dentry, flags); + path_put(&path_dev); + +free_buf: + kfree(buf); + restore_root_inode_sem(root_inode, locked, down); + return ret; +} + +static void update_dm(struct dentry *dst, struct dentry *src) +{ + struct hmdfs_dentry_info_merge *dmi_dst = hmdfs_dm(dst); + struct hmdfs_dentry_info_merge *dmi_src = hmdfs_dm(src); + + trace_hmdfs_merge_update_dentry_info_enter(src, dst); + + spin_lock(&dst->d_lock); + spin_lock(&src->d_lock); + dst->d_fsdata = dmi_src; + src->d_fsdata = dmi_dst; + spin_unlock(&src->d_lock); + spin_unlock(&dst->d_lock); + + trace_hmdfs_merge_update_dentry_info_exit(src, dst); +} + +// do this in a map-reduce manner +struct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode, + struct dentry *child_dentry, + unsigned int flags) +{ + bool create = flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET); + struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); + struct hmdfs_inode_info *pii = hmdfs_i(parent_inode); + struct inode *child_inode = NULL; + struct dentry *ret_dentry = NULL; + int err = 0; + + /* + * Internal flags like LOOKUP_CREATE should not pass to device view. + * LOOKUP_REVAL is needed because dentry cache in hmdfs might be stale + * after rename in lower fs. LOOKUP_DIRECTORY is not needed because + * merge_view can do the judgement that whether result is directory or + * not. + */ + flags = flags & LOOKUP_REVAL; + + child_dentry->d_fsdata = NULL; + + if (child_dentry->d_name.len > NAME_MAX) { + err = -ENAMETOOLONG; + goto out; + } + + err = init_hmdfs_dentry_info_merge(sbi, child_dentry); + if (unlikely(err)) + goto out; + + if (pii->inode_type == HMDFS_LAYER_ZERO) { + hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_FIRST_MERGE; + err = lookup_cloud_merge_root(parent_inode, child_dentry, flags); + } else { + hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_OTHER_MERGE; + err = lookup_merge_normal(child_dentry, flags); + } + + if (!err) { + struct hmdfs_inode_info *info = NULL; + + child_inode = fill_inode_merge(parent_inode->i_sb, parent_inode, + child_dentry, NULL); + ret_dentry = d_splice_alias(child_inode, child_dentry); + if (IS_ERR(ret_dentry)) { + clear_comrades(child_dentry); + err = PTR_ERR(ret_dentry); + goto out; + } + if (ret_dentry) { + update_dm(ret_dentry, child_dentry); + child_dentry = ret_dentry; + } + info = hmdfs_i(child_inode); + if (info->inode_type == HMDFS_LAYER_FIRST_MERGE) + hmdfs_root_inode_perm_init(child_inode); + else + check_and_fixup_ownership_remote(parent_inode, + child_dentry); + + goto out; + } + + if ((err == -ENOENT) && create) + err = 0; + +out: + hmdfs_trace_merge(trace_hmdfs_lookup_merge_end, parent_inode, + child_dentry, err); + return err ? ERR_PTR(err) : ret_dentry; +} + +const struct inode_operations hmdfs_file_iops_cloud_merge = { + .getattr = hmdfs_getattr_merge, + .setattr = hmdfs_setattr_merge, + .permission = hmdfs_permission, +}; + +int do_mkdir_cloud_merge(struct inode *parent_inode, struct dentry *child_dentry, + umode_t mode, struct inode *lo_i_parent, + struct dentry *lo_d_child) +{ + int ret = 0; + struct super_block *sb = parent_inode->i_sb; + struct inode *child_inode = NULL; + + ret = vfs_mkdir(lo_i_parent, lo_d_child, mode); + if (ret) + goto out; + + child_inode = + fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child); + if (IS_ERR(child_inode)) { + ret = PTR_ERR(child_inode); + goto out; + } + + d_add(child_dentry, child_inode); + /* nlink should be increased with the joining of children */ + set_nlink(parent_inode, 2); +out: + return ret; +} + +int do_create_cloud_merge(struct inode *parent_inode, struct dentry *child_dentry, + umode_t mode, bool want_excl, struct inode *lo_i_parent, + struct dentry *lo_d_child) +{ + int ret = 0; + struct super_block *sb = parent_inode->i_sb; + struct inode *child_inode = NULL; + + ret = vfs_create(lo_i_parent, lo_d_child, mode, want_excl); + if (ret) + goto out; + + child_inode = + fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child); + if (IS_ERR(child_inode)) { + ret = PTR_ERR(child_inode); + goto out; + } + + d_add(child_dentry, child_inode); + /* nlink should be increased with the joining of children */ + set_nlink(parent_inode, 2); +out: + return ret; +} + +int hmdfs_do_ops_cloud_merge(struct inode *i_parent, struct dentry *d_child, + struct dentry *lo_d_child, struct path path, + struct hmdfs_recursive_para *rec_op_para) +{ + int ret = 0; + + if (rec_op_para->is_last) { + switch (rec_op_para->opcode) { + case F_MKDIR_MERGE: + ret = do_mkdir_cloud_merge(i_parent, d_child, + rec_op_para->mode, + d_inode(path.dentry), lo_d_child); + break; + case F_CREATE_MERGE: + ret = do_create_cloud_merge(i_parent, d_child, + rec_op_para->mode, + rec_op_para->want_excl, + d_inode(path.dentry), lo_d_child); + break; + default: + ret = -EINVAL; + break; + } + } else { + ret = vfs_mkdir(d_inode(path.dentry), lo_d_child, + rec_op_para->mode); + } + if (ret) + hmdfs_err("vfs_ops failed, ops %d, err = %d", + rec_op_para->opcode, ret); + return ret; +} + +int hmdfs_create_lower_cloud_dentry(struct inode *i_parent, struct dentry *d_child, + struct dentry *lo_d_parent, bool is_dir, + struct hmdfs_recursive_para *rec_op_para) +{ + struct hmdfs_sb_info *sbi = i_parent->i_sb->s_fs_info; + struct hmdfs_dentry_comrade *new_comrade = NULL; + struct dentry *lo_d_child = NULL; + char *path_buf = kmalloc(PATH_MAX, GFP_KERNEL); + char *absolute_path_buf = kmalloc(PATH_MAX, GFP_KERNEL); + char *path_name = NULL; + struct path path = { .mnt = NULL, .dentry = NULL }; + int ret = 0; + + if (unlikely(!path_buf || !absolute_path_buf)) { + ret = -ENOMEM; + goto out; + } + + path_name = dentry_path_raw(lo_d_parent, path_buf, PATH_MAX); + if (IS_ERR(path_name)) { + ret = PTR_ERR(path_name); + goto out; + } + if ((strlen(sbi->real_dst) + strlen(path_name) + + strlen(d_child->d_name.name) + 2) > PATH_MAX) { + ret = -ENAMETOOLONG; + goto out; + } + + sprintf(absolute_path_buf, "%s%s/%s", sbi->real_dst, path_name, + d_child->d_name.name); + + if (is_dir) + lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf, + &path, LOOKUP_DIRECTORY); + else + lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf, + &path, 0); + if (IS_ERR(lo_d_child)) { + ret = PTR_ERR(lo_d_child); + goto out; + } + // to ensure link_comrade after vfs_mkdir succeed + ret = hmdfs_do_ops_cloud_merge(i_parent, d_child, lo_d_child, path, + rec_op_para); + if (ret) + goto out_put; + new_comrade = alloc_comrade(lo_d_child, HMDFS_DEVID_LOCAL); + if (IS_ERR(new_comrade)) { + ret = PTR_ERR(new_comrade); + goto out_put; + } else { + link_comrade_unlocked(d_child, new_comrade); + } + +out_put: + done_path_create(&path, lo_d_child); +out: + kfree(absolute_path_buf); + kfree(path_buf); + return ret; +} + +static int create_lo_d_parent_recur(struct dentry *d_parent, + struct dentry *d_child, umode_t mode, + struct hmdfs_recursive_para *rec_op_para) +{ + struct dentry *lo_d_parent, *d_pparent; + struct hmdfs_dentry_info_merge *pmdi = NULL; + int ret = 0; + + pmdi = hmdfs_dm(d_parent); + wait_event(pmdi->wait_queue, !has_merge_lookup_work(pmdi)); + lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); + if (!lo_d_parent) { + d_pparent = dget_parent(d_parent); + ret = create_lo_d_parent_recur(d_pparent, d_parent, + d_inode(d_parent)->i_mode, + rec_op_para); + dput(d_pparent); + if (ret) + goto out; + lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); + if (!lo_d_parent) { + ret = -ENOENT; + goto out; + } + } + rec_op_para->is_last = false; + rec_op_para->mode = mode; + ret = hmdfs_create_lower_cloud_dentry(d_inode(d_parent), d_child, lo_d_parent, + true, rec_op_para); +out: + dput(lo_d_parent); + return ret; +} + +int create_lo_d_cloud_child(struct inode *i_parent, struct dentry *d_child, + bool is_dir, struct hmdfs_recursive_para *rec_op_para) +{ + struct dentry *d_pparent, *lo_d_parent, *lo_d_child; + struct dentry *d_parent = dget_parent(d_child); + struct hmdfs_dentry_info_merge *pmdi = hmdfs_dm(d_parent); + int ret = 0; + mode_t d_child_mode = rec_op_para->mode; + + wait_event(pmdi->wait_queue, !has_merge_lookup_work(pmdi)); + + lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); + if (!lo_d_parent) { + d_pparent = dget_parent(d_parent); + ret = create_lo_d_parent_recur(d_pparent, d_parent, + d_inode(d_parent)->i_mode, + rec_op_para); + dput(d_pparent); + if (unlikely(ret)) { + lo_d_child = ERR_PTR(ret); + goto out; + } + lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); + if (!lo_d_parent) { + lo_d_child = ERR_PTR(-ENOENT); + goto out; + } + } + rec_op_para->is_last = true; + rec_op_para->mode = d_child_mode; + ret = hmdfs_create_lower_cloud_dentry(i_parent, d_child, lo_d_parent, is_dir, + rec_op_para); + +out: + dput(d_parent); + dput(lo_d_parent); + return ret; +} + +int hmdfs_mkdir_cloud_merge(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + int ret = 0; + struct hmdfs_recursive_para *rec_op_para = NULL; + + // confict_name & file_type is checked by hmdfs_mkdir_local + if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { + ret = -EACCES; + goto out; + } + rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); + if (!rec_op_para) { + ret = -ENOMEM; + goto out; + } + + hmdfs_init_recursive_para(rec_op_para, F_MKDIR_MERGE, mode, false, + NULL); + ret = create_lo_d_cloud_child(dir, dentry, true, rec_op_para); +out: + hmdfs_trace_merge(trace_hmdfs_mkdir_merge, dir, dentry, ret); + if (ret) + d_drop(dentry); + kfree(rec_op_para); + return ret; +} + +int hmdfs_create_cloud_merge(struct inode *dir, struct dentry *dentry, umode_t mode, + bool want_excl) +{ + struct hmdfs_recursive_para *rec_op_para = NULL; + int ret = 0; + + rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); + if (!rec_op_para) { + ret = -ENOMEM; + goto out; + } + hmdfs_init_recursive_para(rec_op_para, F_CREATE_MERGE, mode, want_excl, + NULL); + // confict_name & file_type is checked by hmdfs_create_local + ret = create_lo_d_cloud_child(dir, dentry, false, rec_op_para); +out: + hmdfs_trace_merge(trace_hmdfs_create_merge, dir, dentry, ret); + if (ret) + d_drop(dentry); + kfree(rec_op_para); + return ret; +} + +const struct inode_operations hmdfs_dir_iops_cloud_merge = { + .lookup = hmdfs_lookup_cloud_merge, + .mkdir = hmdfs_mkdir_cloud_merge, + .create = hmdfs_create_cloud_merge, + .rmdir = hmdfs_rmdir_merge, + .unlink = hmdfs_unlink_merge, + .rename = hmdfs_rename_merge, + .permission = hmdfs_permission, +}; diff --git a/fs/hmdfs/inode_merge.c b/fs/hmdfs/inode_merge.c index c5cd7bdc4905..6c6b4a9232c3 100644 --- a/fs/hmdfs/inode_merge.c +++ b/fs/hmdfs/inode_merge.c @@ -53,7 +53,7 @@ struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id) return d; } -static void update_inode_attr(struct inode *inode, struct dentry *child_dentry) +void update_inode_attr(struct inode *inode, struct dentry *child_dentry) { struct inode *li = NULL; struct hmdfs_dentry_info_merge *cdi = hmdfs_dm(child_dentry); @@ -82,7 +82,7 @@ static void update_inode_attr(struct inode *inode, struct dentry *child_dentry) mutex_unlock(&cdi->comrade_list_lock); } -static int get_num_comrades(struct dentry *dentry) +int get_num_comrades(struct dentry *dentry) { struct list_head *pos; struct hmdfs_dentry_info_merge *dim = hmdfs_dm(dentry); @@ -206,8 +206,8 @@ void link_comrade(struct list_head *onstack_comrades_head, * We tend to setup a local list of all the comrades we found and place the * list onto the dentry_info to achieve atomicity. */ -static void assign_comrades_unlocked(struct dentry *child_dentry, - struct list_head *onstack_comrades_head) +void assign_comrades_unlocked(struct dentry *child_dentry, + struct list_head *onstack_comrades_head) { struct hmdfs_dentry_info_merge *cdi = hmdfs_dm(child_dentry); @@ -217,10 +217,10 @@ static void assign_comrades_unlocked(struct dentry *child_dentry, mutex_unlock(&cdi->comrade_list_lock); } -static struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path, - const char *d_name, - int dev_id, - unsigned int flags) +struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path, + const char *d_name, + int dev_id, + unsigned int flags) { struct path path; struct hmdfs_dentry_comrade *comrade = NULL; @@ -432,7 +432,7 @@ static void merge_lookup_work_func(struct work_struct *work) kfree(ml_work); } -static int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, +int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, struct hmdfs_sb_info *sbi, int devid, const char *name, unsigned int flags) { @@ -462,7 +462,7 @@ static int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi, return err; } -static char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type) +char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type) { char *rname; @@ -597,7 +597,7 @@ static int do_lookup_merge_root(struct path path_dev, } // mkdir -p -static void lock_root_inode_shared(struct inode *root, bool *locked, bool *down) +void lock_root_inode_shared(struct inode *root, bool *locked, bool *down) { struct rw_semaphore *sem = &root->i_rwsem; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0) @@ -627,7 +627,7 @@ static void lock_root_inode_shared(struct inode *root, bool *locked, bool *down) *locked = true; } -static void restore_root_inode_sem(struct inode *root, bool locked, bool down) +void restore_root_inode_sem(struct inode *root, bool locked, bool down) { if (!locked) return; @@ -785,7 +785,7 @@ struct dentry *hmdfs_lookup_merge(struct inode *parent_inode, return err ? ERR_PTR(err) : ret_dentry; } -static int hmdfs_getattr_merge(const struct path *path, struct kstat *stat, +int hmdfs_getattr_merge(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) { int ret; @@ -806,7 +806,7 @@ static int hmdfs_getattr_merge(const struct path *path, struct kstat *stat, return ret; } -static int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia) +int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia) { struct inode *inode = d_inode(dentry); struct dentry *lower_dentry = hmdfs_get_fst_lo_d(dentry); diff --git a/fs/hmdfs/inode_root.c b/fs/hmdfs/inode_root.c index beb1819f7b92..ba3eac8352a9 100644 --- a/fs/hmdfs/inode_root.c +++ b/fs/hmdfs/inode_root.c @@ -254,7 +254,7 @@ struct dentry *hmdfs_root_lookup(struct inode *parent_inode, child_dentry = ret; root_inode = d_inode(child_dentry); } else if (sbi->s_merge_switch && !strcmp(d_name, CLOUD_MERGE_VIEW_ROOT)) { - ret = hmdfs_lookup_merge(parent_inode, child_dentry, flags); + ret = hmdfs_lookup_cloud_merge(parent_inode, child_dentry, flags); if (ret && !IS_ERR(ret)) child_dentry = ret; root_inode = d_inode(child_dentry); -- Gitee