diff --git a/fs/hmdfs/dentry.c b/fs/hmdfs/dentry.c index 15e57342f72cfa1a23c8bfd9cb1d3769702ab402..52e2afb4df8e69e4f66d6cdb3a0cdd12711c675a 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: diff --git a/fs/hmdfs/file_cloud.c b/fs/hmdfs/file_cloud.c index 47e0e3a71633534fbb12daac144edf66cfe826f8..9e73a9730deca4c0e4d0a3c2d8a48cc6813bea19 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, @@ -31,19 +30,48 @@ 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; - 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(!gfi) + 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); @@ -97,7 +125,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, diff --git a/fs/hmdfs/hmdfs.h b/fs/hmdfs/hmdfs.h index fd964ecf2e5dc1da740ca577c46deb141abd83f6..cc682d4a61f821f22a4877db4782fbfbeab8b5b2 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; @@ -136,7 +137,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 f9aa6fff9d4c9f2b6d97d10e5fe733be057b7698..a33259d366ca295356dbfcb845c78224f0687988 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, @@ -1197,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)) { @@ -1255,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); @@ -1374,29 +1374,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) @@ -1415,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); } @@ -1621,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); @@ -1847,9 +1913,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); diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index cb9278bbc919954678491c443513b75173f35279..1316cb1996e15c6e41fd29d859824e05e50103e1 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_"); @@ -925,7 +928,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); @@ -961,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 18f222c6d4ccc05293d69445981dfec6a403d685..665d0b684f4fa52138c1e504038c3319270dee34 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;