From 00c66e87cca8e392b0b9a1b38343074ee548f76e Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Sun, 23 Apr 2023 15:41:29 +0800 Subject: [PATCH 1/5] hmdfs: load cloud dentryfile dynamically Since there is a lot of cloud dentryfile, load the dentryfile dynamically, By the way, rename function 'hmdfs_cache_file_create()' to 'concat_cachefile_name()'. Signed-off-by: ChenXiaoSong --- fs/hmdfs/hmdfs_dentryfile.c | 117 +++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 22 deletions(-) diff --git a/fs/hmdfs/hmdfs_dentryfile.c b/fs/hmdfs/hmdfs_dentryfile.c index f9aa6fff9d4c..1d3d3ce4404b 100644 --- a/fs/hmdfs/hmdfs_dentryfile.c +++ b/fs/hmdfs/hmdfs_dentryfile.c @@ -1132,7 +1132,7 @@ static void hmdfs_cache_path_create(char *s, const char *dir, bool server) snprintf(s, PATH_MAX, "%s/dentry_cache/client/", dir); } -static void hmdfs_cache_file_create(char *s, uint64_t hash, const char *id, +static void concat_cachefile_name(char *s, uint64_t hash, const char *id, bool server) { int offset = strlen(s); @@ -1164,7 +1164,7 @@ int cache_file_name_generate(char *fullname, struct hmdfs_peer *con, hash = path_hash(relative_path, strlen(relative_path), sbi->s_case_sensitive); - hmdfs_cache_file_create(fullname, hash, cid, server); + concat_cachefile_name(fullname, hash, cid, server); return 0; } @@ -1178,17 +1178,23 @@ static void free_cfn(struct cache_file_node *cfn) kfree(cfn); } -static bool dentry_file_match(struct cache_file_node *cfn, const char *id, - const char *path) +static bool path_cmp(const char *path1, const char *path2, bool case_sensitive) { int ret; - if (cfn->sbi->s_case_sensitive) - ret = strcmp(cfn->relative_path, path); + if (case_sensitive) + ret = strcmp(path1, path2); else - ret = strcasecmp(cfn->relative_path, path); + ret = strcasecmp(path1, path2); - return (!ret && !strncmp((cfn)->cid, id, HMDFS_CFN_CID_SIZE - 1)); + return !ret; +} + +static bool dentry_file_match(struct cache_file_node *cfn, const char *id, + const char *path) +{ + return (path_cmp(cfn->relative_path, path, cfn->sbi->s_case_sensitive) && + !strncmp((cfn)->cid, id, HMDFS_CFN_CID_SIZE - 1)); } struct cache_file_node *__find_cfn(struct hmdfs_sb_info *sbi, const char *cid, @@ -1374,29 +1380,99 @@ struct file *cache_file_persistent(struct hmdfs_peer *con, struct file *filp, int get_cloud_cache_file(struct dentry *dentry, struct hmdfs_sb_info *sbi) { + int ret; + ssize_t res; struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); - char *relative_path = NULL; - struct cache_file_node *cfn = NULL; - char *cid = CLOUD_CID; + struct clearcache_item *item; struct file *filp = NULL; + uint64_t hash; + char *relative_path = NULL; + char *dirname = NULL; + char *fullname = NULL; + char *cache_file_name = NULL; + char *kvalue = NULL; + + item = hmdfs_find_cache_item(CLOUD_DEVICE, dentry); + if (item) { + kref_put(&item->ref, release_cache_item); + return 0; + } relative_path = hmdfs_get_dentry_relative_path(dentry); if (unlikely(!relative_path)) { hmdfs_err("get relative path failed %d", -ENOMEM); - return -ENOMEM; + ret = -ENOMEM; + goto out; } - 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); + dirname = kzalloc(PATH_MAX, GFP_KERNEL); + if (!dirname) { + ret = -ENOMEM; + goto out; + } + + cache_file_name = kzalloc(PATH_MAX, GFP_KERNEL); + if (!cache_file_name) { + ret = -ENOMEM; + goto out; } + + fullname = kzalloc(PATH_MAX, GFP_KERNEL); + if (!fullname) { + ret = -ENOMEM; + goto out; + } + + kvalue = kzalloc(PATH_MAX, GFP_KERNEL); + if (!kvalue) { + ret = -ENOMEM; + goto out; + } + + hash = path_hash(relative_path, strlen(relative_path), + sbi->s_case_sensitive); + concat_cachefile_name(cache_file_name, hash, CLOUD_CID, false); + snprintf(dirname, PATH_MAX, "%s/dentry_cache/cloud/", + sbi->cache_dir); + snprintf(fullname, PATH_MAX, "%s%s", dirname, cache_file_name); + + filp = filp_open(fullname, O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + hmdfs_err("open fail %ld", PTR_ERR(filp)); + ret = PTR_ERR(filp); + goto out; + } + + res = __vfs_getxattr(file_dentry(filp), file_inode(filp), + DENTRY_FILE_XATTR_NAME, kvalue, PATH_MAX); + if (res <= 0 || res >= PATH_MAX) { + hmdfs_err("getxattr return: %zd", res); + filp_close(filp, NULL); + ret = -ENOENT; + goto out; + } + kvalue[res] = '\0'; + + if (!path_cmp(relative_path, kvalue, sbi->s_case_sensitive)) { + hmdfs_err("relative path from xattr do not match"); + filp_close(filp, NULL); + ret = -ENOENT; + goto out; + } + + mutex_lock(&d_info->cache_pull_lock); + hmdfs_add_cache_list(CLOUD_DEVICE, dentry, filp); mutex_unlock(&d_info->cache_pull_lock); + ret = 0; +out: kfree(relative_path); - return 0; + kfree(dirname); + kfree(fullname); + kfree(cache_file_name); + kfree(kvalue); + + return ret; } void __destroy_cfn(struct list_head *head) @@ -1847,9 +1923,6 @@ void hmdfs_cfn_load(struct hmdfs_sb_info *sbi) 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); -- Gitee From 2c8f873ab939c71435b698255474780c0cd84d10 Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Sun, 23 Apr 2023 15:47:47 +0800 Subject: [PATCH 2/5] hmdfs: remove useless 'cloud_cache' in 'struct hmdfs_sb_info' Since dentryfile don't link to 'struct cache_file_node', remove the useless list. Signed-off-by: ChenXiaoSong --- fs/hmdfs/hmdfs.h | 1 - fs/hmdfs/hmdfs_dentryfile.c | 16 +++------------- fs/hmdfs/main.c | 1 - 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/fs/hmdfs/hmdfs.h b/fs/hmdfs/hmdfs.h index fd964ecf2e5d..45fcf9f9b3f3 100644 --- a/fs/hmdfs/hmdfs.h +++ b/fs/hmdfs/hmdfs.h @@ -136,7 +136,6 @@ 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 1d3d3ce4404b..a33259d366ca 100644 --- a/fs/hmdfs/hmdfs_dentryfile.c +++ b/fs/hmdfs/hmdfs_dentryfile.c @@ -1203,10 +1203,7 @@ struct cache_file_node *__find_cfn(struct hmdfs_sb_info *sbi, const char *cid, struct cache_file_node *cfn = NULL; struct list_head *head = NULL; - if (!strcmp(cid, CLOUD_CID)) - head = &sbi->cloud_cache; - else - head = get_list_head(sbi, server); + head = get_list_head(sbi, server); list_for_each_entry(cfn, head, list) { if (dentry_file_match(cfn, cid, path)) { @@ -1261,10 +1258,7 @@ static struct file *insert_cfn(struct hmdfs_sb_info *sbi, const char *filename, goto out; } - if (!strcmp(cid, CLOUD_CID)) - head = &sbi->cloud_cache; - else - head = get_list_head(sbi, server); + head = get_list_head(sbi, server); mutex_lock(&sbi->cache_list_lock); exist = __find_cfn(sbi, cid, path, server); @@ -1491,7 +1485,6 @@ 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); } @@ -1697,10 +1690,7 @@ void load_cfn(struct hmdfs_sb_info *sbi, const char *fullname, const char *path, return; } - if (!strcmp(cid, CLOUD_CID)) - head = &sbi->cloud_cache; - else - head = get_list_head(sbi, server); + head = get_list_head(sbi, server); mutex_lock(&sbi->cache_list_lock); cfn1 = __find_cfn(sbi, cid, path, server); diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index cb9278bbc919..f57d67562486 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -925,7 +925,6 @@ 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 b191abd13abe4559bb9d3998f326c9450c596dc7 Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Sun, 23 Apr 2023 15:24:53 +0800 Subject: [PATCH 3/5] hmdfs: close cloud dentryfile when release dentry Cloud dentryfile will never be closed in 'free_cfn()', so should close it before 'hmdfs_clear_cache_dents()'. Signed-off-by: ChenXiaoSong --- fs/hmdfs/dentry.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/hmdfs/dentry.c b/fs/hmdfs/dentry.c index 15e57342f72c..52e2afb4df8e 100644 --- a/fs/hmdfs/dentry.c +++ b/fs/hmdfs/dentry.c @@ -169,6 +169,7 @@ static int hmdfs_d_revalidate(struct dentry *direntry, unsigned int flags) static void hmdfs_dev_d_release(struct dentry *dentry) { + struct clearcache_item *item; if (!dentry || !dentry->d_fsdata) return; @@ -187,6 +188,14 @@ static void hmdfs_dev_d_release(struct dentry *dentry) hmdfs_clear_cache_dents(dentry, false); break; case HMDFS_LAYER_SECOND_CLOUD: + item = hmdfs_find_cache_item(CLOUD_DEVICE, dentry); + if (item) { + /* cloud dentryfile didn't link to + 'struct cache_file_node', so close file here. + */ + filp_close(item->filp, NULL); + kref_put(&item->ref, release_cache_item); + } hmdfs_clear_cache_dents(dentry, false); break; default: -- Gitee From 27f810c35ebb09e8c4c22937dab20815636db1ec Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Mon, 24 Apr 2023 17:17:33 +0800 Subject: [PATCH 4/5] hmdfs: implement 'read_iter' interface in 'hmdfs_dev_file_fops_cloud' Signed-off-by: ChenXiaoSong --- fs/hmdfs/file_cloud.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c index 47e0e3a71633..c50ed16d8917 100644 --- a/fs/hmdfs/file_cloud.c +++ b/fs/hmdfs/file_cloud.c @@ -31,6 +31,30 @@ static const struct vm_operations_struct hmdfs_cloud_vm_ops = { .page_mkwrite = NULL, }; +static ssize_t hmdfs_file_read_iter_cloud(struct kiocb *iocb, + struct iov_iter *iter) +{ + ssize_t ret = -ENOENT; + const struct iovec *iov; + struct file *filp = iocb->ki_filp; + struct hmdfs_file_info *gfi = filp->private_data; + struct file *lower_file = NULL; + + if (gfi) + lower_file = gfi->lower_file; + + if (uaccess_kernel()) + iov = (struct iovec *)iter->kvec; + else + iov = iter->iov; + + if (lower_file) + ret = vfs_read(lower_file, iov->iov_base, iov->iov_len, + &iocb->ki_pos); + + return ret; +} + int hmdfs_file_open_cloud(struct inode *inode, struct file *file) { const char *dir_path; @@ -40,7 +64,7 @@ int hmdfs_file_open_cloud(struct inode *inode, struct file *file) struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL); int err = 0; - if(!gfi) + if (!gfi) return -ENOMEM; err = kern_path(root_name, 0, &root_path); @@ -97,7 +121,7 @@ static int hmdfs_file_flush_cloud(struct file *file, fl_owner_t id) const struct file_operations hmdfs_dev_file_fops_cloud = { .owner = THIS_MODULE, .llseek = generic_file_llseek, - .read_iter = NULL, + .read_iter = hmdfs_file_read_iter_cloud, .write_iter = NULL, .mmap = NULL, .open = hmdfs_file_open_cloud, -- Gitee From 2338ec71d69537cf33ece4deef2998941dfca312 Mon Sep 17 00:00:00 2001 From: ChenXiaoSong Date: Mon, 24 Apr 2023 21:17:16 +0800 Subject: [PATCH 5/5] hmdfs: add 'cloud_dir' mount option Signed-off-by: ChenXiaoSong --- fs/hmdfs/file_cloud.c | 10 +++++++--- fs/hmdfs/hmdfs.h | 1 + fs/hmdfs/main.c | 4 ++++ fs/hmdfs/super.c | 7 +++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c index c50ed16d8917..9e73a9730dec 100644 --- a/fs/hmdfs/file_cloud.c +++ b/fs/hmdfs/file_cloud.c @@ -23,7 +23,6 @@ #include "hmdfs_client.h" #include "hmdfs_dentryfile.h" #include "hmdfs_trace.h" -#define DATA_CLOUD "/mnt/hmdfs/100/cloud" static const struct vm_operations_struct hmdfs_cloud_vm_ops = { .fault = filemap_fault, @@ -58,16 +57,21 @@ static ssize_t hmdfs_file_read_iter_cloud(struct kiocb *iocb, int hmdfs_file_open_cloud(struct inode *inode, struct file *file) { const char *dir_path; - const char *root_name = DATA_CLOUD; + struct hmdfs_sb_info *sbi = inode->i_sb->s_fs_info; struct path root_path; struct file *lower_file; struct hmdfs_file_info *gfi = kzalloc(sizeof(*gfi), GFP_KERNEL); int err = 0; + if (!sbi->cloud_dir) { + hmdfs_info("no cloud_dir"); + return -EPERM; + } + if (!gfi) return -ENOMEM; - err = kern_path(root_name, 0, &root_path); + err = kern_path(sbi->cloud_dir, 0, &root_path); if (err) { hmdfs_info("kern_path failed: %d", err); kfree(gfi); diff --git a/fs/hmdfs/hmdfs.h b/fs/hmdfs/hmdfs.h index 45fcf9f9b3f3..cc682d4a61f8 100644 --- a/fs/hmdfs/hmdfs.h +++ b/fs/hmdfs/hmdfs.h @@ -122,6 +122,7 @@ struct hmdfs_sb_info { char *real_dst; char *local_src; char *cache_dir; + char *cloud_dir; /* seq number for hmdfs super block */ unsigned int seq; diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index f57d67562486..1316cb1996e1 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -272,6 +272,7 @@ void hmdfs_put_super(struct super_block *sb) kfree(sbi->local_dst); kfree(sbi->real_dst); kfree(sbi->cache_dir); + kfree(sbi->cloud_dir); kfifo_free(&sbi->notify_fifo); sb->s_fs_info = NULL; sbi->lower_sb = NULL; @@ -398,6 +399,8 @@ static int hmdfs_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",cache_dir=%s", sbi->cache_dir); if (sbi->real_dst) seq_printf(m, ",real_dst=%s", sbi->real_dst); + if (sbi->cloud_dir) + seq_printf(m, ",cloud_dir=%s", sbi->cloud_dir); seq_printf(m, ",%soffline_stash", sbi->s_offline_stash ? "" : "no_"); seq_printf(m, ",%sdentry_cache", sbi->s_dentry_cache ? "" : "no_"); @@ -960,6 +963,7 @@ static int hmdfs_fill_super(struct super_block *sb, void *data, int silent) kfree(sbi->local_dst); kfree(sbi->real_dst); kfree(sbi->cache_dir); + kfree(sbi->cloud_dir); kfree(sbi->s_server_statis); kfree(sbi->s_client_statis); kfree(sbi); diff --git a/fs/hmdfs/super.c b/fs/hmdfs/super.c index 18f222c6d4cc..665d0b684f4f 100644 --- a/fs/hmdfs/super.c +++ b/fs/hmdfs/super.c @@ -16,6 +16,7 @@ enum { OPT_RA_PAGES, OPT_LOCAL_DST, OPT_CACHE_DIR, + OPT_CLOUD_DIR, OPT_S_CASE, OPT_VIEW_TYPE, OPT_NO_OFFLINE_STASH, @@ -28,6 +29,7 @@ static match_table_t hmdfs_tokens = { { OPT_RA_PAGES, "ra_pages=%s" }, { OPT_LOCAL_DST, "local_dst=%s" }, { OPT_CACHE_DIR, "cache_dir=%s" }, + { OPT_CLOUD_DIR, "cloud_dir=%s" }, { OPT_S_CASE, "sensitive" }, { OPT_VIEW_TYPE, "merge" }, { OPT_NO_OFFLINE_STASH, "no_offline_stash" }, @@ -127,6 +129,11 @@ int hmdfs_parse_options(struct hmdfs_sb_info *sbi, const char *data) if (err) goto out; break; + case OPT_CLOUD_DIR: + err = hmdfs_match_strdup(&args[0], &sbi->cloud_dir); + if (err) + goto out; + break; case OPT_S_CASE: sbi->s_case_sensitive = true; break; -- Gitee