18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/hmdfs/main.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "hmdfs.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/ctype.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/statfs.h> 148c2ecf20Sopenharmony_ci#include <linux/xattr.h> 158c2ecf20Sopenharmony_ci#include <linux/idr.h> 168c2ecf20Sopenharmony_ci#if KERNEL_VERSION(5, 9, 0) < LINUX_VERSION_CODE 178c2ecf20Sopenharmony_ci#include <linux/prandom.h> 188c2ecf20Sopenharmony_ci#else 198c2ecf20Sopenharmony_ci#include <linux/random.h> 208c2ecf20Sopenharmony_ci#endif 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "authority/authentication.h" 238c2ecf20Sopenharmony_ci#include "hmdfs_server.h" 248c2ecf20Sopenharmony_ci#include "comm/device_node.h" 258c2ecf20Sopenharmony_ci#include "comm/message_verify.h" 268c2ecf20Sopenharmony_ci#include "comm/protocol.h" 278c2ecf20Sopenharmony_ci#include "comm/socket_adapter.h" 288c2ecf20Sopenharmony_ci#include "hmdfs_merge_view.h" 298c2ecf20Sopenharmony_ci#include "server_writeback.h" 308c2ecf20Sopenharmony_ci#include "hmdfs_share.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "comm/node_cb.h" 338c2ecf20Sopenharmony_ci#include "stash.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 368c2ecf20Sopenharmony_ci#include "hmdfs_trace.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define HMDFS_BOOT_COOKIE_RAND_SHIFT 33 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define HMDFS_SB_SEQ_FROM 1 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct hmdfs_mount_priv { 438c2ecf20Sopenharmony_ci const char *dev_name; 448c2ecf20Sopenharmony_ci const char *raw_data; 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistruct syncfs_item { 488c2ecf20Sopenharmony_ci struct list_head list; 498c2ecf20Sopenharmony_ci struct completion done; 508c2ecf20Sopenharmony_ci bool need_abort; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic DEFINE_IDA(hmdfs_sb_seq); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic inline int hmdfs_alloc_sb_seq(void) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci return ida_simple_get(&hmdfs_sb_seq, HMDFS_SB_SEQ_FROM, 0, GFP_KERNEL); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic inline void hmdfs_free_sb_seq(unsigned int seq) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci if (!seq) 638c2ecf20Sopenharmony_ci return; 648c2ecf20Sopenharmony_ci ida_simple_remove(&hmdfs_sb_seq, seq); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int hmdfs_xattr_local_get(struct dentry *dentry, const char *name, 688c2ecf20Sopenharmony_ci void *value, size_t size) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct path lower_path; 718c2ecf20Sopenharmony_ci ssize_t res = 0; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 748c2ecf20Sopenharmony_ci res = vfs_getxattr(lower_path.dentry, name, value, size); 758c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 768c2ecf20Sopenharmony_ci return res; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int hmdfs_xattr_remote_get(struct dentry *dentry, const char *name, 808c2ecf20Sopenharmony_ci void *value, size_t size) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 838c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 848c2ecf20Sopenharmony_ci struct hmdfs_peer *conn = info->conn; 858c2ecf20Sopenharmony_ci char *send_buf = NULL; 868c2ecf20Sopenharmony_ci ssize_t res = 0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci send_buf = hmdfs_get_dentry_relative_path(dentry); 898c2ecf20Sopenharmony_ci if (!send_buf) 908c2ecf20Sopenharmony_ci return -ENOMEM; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci res = hmdfs_send_getxattr(conn, send_buf, name, value, size); 938c2ecf20Sopenharmony_ci kfree(send_buf); 948c2ecf20Sopenharmony_ci return res; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic int hmdfs_xattr_merge_get(struct dentry *dentry, const char *name, 988c2ecf20Sopenharmony_ci void *value, size_t size) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci int err = 0; 1018c2ecf20Sopenharmony_ci struct dentry *lower_dentry = hmdfs_get_lo_d(dentry, HMDFS_DEVID_LOCAL); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (!lower_dentry) { 1048c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 1058c2ecf20Sopenharmony_ci goto out; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci err = hmdfs_xattr_local_get(lower_dentry, name, value, size); 1088c2ecf20Sopenharmony_ciout: 1098c2ecf20Sopenharmony_ci dput(lower_dentry); 1108c2ecf20Sopenharmony_ci return err; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int hmdfs_xattr_get(const struct xattr_handler *handler, 1148c2ecf20Sopenharmony_ci struct dentry *dentry, struct inode *inode, 1158c2ecf20Sopenharmony_ci const char *name, void *value, size_t size) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci int res = 0; 1188c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 1198c2ecf20Sopenharmony_ci size_t r_size = size; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (!hmdfs_support_xattr(dentry)) 1228c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) 1258c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (size > HMDFS_XATTR_SIZE_MAX) 1288c2ecf20Sopenharmony_ci r_size = HMDFS_XATTR_SIZE_MAX; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (info->inode_type == HMDFS_LAYER_OTHER_LOCAL) 1318c2ecf20Sopenharmony_ci res = hmdfs_xattr_local_get(dentry, name, value, r_size); 1328c2ecf20Sopenharmony_ci else if (info->inode_type == HMDFS_LAYER_OTHER_REMOTE) 1338c2ecf20Sopenharmony_ci res = hmdfs_xattr_remote_get(dentry, name, value, r_size); 1348c2ecf20Sopenharmony_ci else if (info->inode_type == HMDFS_LAYER_OTHER_MERGE || 1358c2ecf20Sopenharmony_ci info->inode_type == HMDFS_LAYER_OTHER_MERGE_CLOUD) 1368c2ecf20Sopenharmony_ci res = hmdfs_xattr_merge_get(dentry, name, value, r_size); 1378c2ecf20Sopenharmony_ci else 1388c2ecf20Sopenharmony_ci res = -EOPNOTSUPP; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (res == -ERANGE && r_size != size) { 1418c2ecf20Sopenharmony_ci hmdfs_info("no support xattr value size over than: %d", 1428c2ecf20Sopenharmony_ci HMDFS_XATTR_SIZE_MAX); 1438c2ecf20Sopenharmony_ci res = -E2BIG; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return res; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int hmdfs_xattr_local_set(struct dentry *dentry, const char *name, 1508c2ecf20Sopenharmony_ci const void *value, size_t size, int flags) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct path lower_path; 1538c2ecf20Sopenharmony_ci int res = 0; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 1568c2ecf20Sopenharmony_ci kuid_t tmp_uid = hmdfs_override_inode_uid(d_inode(lower_path.dentry)); 1578c2ecf20Sopenharmony_ci if (value) { 1588c2ecf20Sopenharmony_ci res = vfs_setxattr(lower_path.dentry, name, value, size, flags); 1598c2ecf20Sopenharmony_ci } else { 1608c2ecf20Sopenharmony_ci WARN_ON(flags != XATTR_REPLACE); 1618c2ecf20Sopenharmony_ci res = vfs_removexattr(lower_path.dentry, name); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci hmdfs_revert_inode_uid(d_inode(lower_path.dentry), tmp_uid); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 1668c2ecf20Sopenharmony_ci return res; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int hmdfs_xattr_remote_set(struct dentry *dentry, const char *name, 1708c2ecf20Sopenharmony_ci const void *value, size_t size, int flags) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 1738c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 1748c2ecf20Sopenharmony_ci struct hmdfs_peer *conn = info->conn; 1758c2ecf20Sopenharmony_ci char *send_buf = NULL; 1768c2ecf20Sopenharmony_ci int res = 0; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci send_buf = hmdfs_get_dentry_relative_path(dentry); 1798c2ecf20Sopenharmony_ci if (!send_buf) 1808c2ecf20Sopenharmony_ci return -ENOMEM; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci res = hmdfs_send_setxattr(conn, send_buf, name, value, size, flags); 1838c2ecf20Sopenharmony_ci kfree(send_buf); 1848c2ecf20Sopenharmony_ci return res; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int hmdfs_xattr_merge_set(struct dentry *dentry, const char *name, 1888c2ecf20Sopenharmony_ci const void *value, size_t size, int flags) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int err = 0; 1918c2ecf20Sopenharmony_ci struct dentry *lower_dentry = hmdfs_get_lo_d(dentry, HMDFS_DEVID_LOCAL); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (!lower_dentry) { 1948c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 1958c2ecf20Sopenharmony_ci goto out; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci err = hmdfs_xattr_local_set(lower_dentry, name, value, size, flags); 1988c2ecf20Sopenharmony_ciout: 1998c2ecf20Sopenharmony_ci dput(lower_dentry); 2008c2ecf20Sopenharmony_ci return err; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic int hmdfs_xattr_set(const struct xattr_handler *handler, 2048c2ecf20Sopenharmony_ci struct dentry *dentry, struct inode *inode, 2058c2ecf20Sopenharmony_ci const char *name, const void *value, 2068c2ecf20Sopenharmony_ci size_t size, int flags) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (!hmdfs_support_xattr(dentry)) 2118c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (size > HMDFS_XATTR_SIZE_MAX) { 2148c2ecf20Sopenharmony_ci hmdfs_info("no support too long xattr value: %zu", size); 2158c2ecf20Sopenharmony_ci return -E2BIG; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (info->inode_type == HMDFS_LAYER_OTHER_LOCAL) 2198c2ecf20Sopenharmony_ci return hmdfs_xattr_local_set(dentry, name, value, size, flags); 2208c2ecf20Sopenharmony_ci else if (info->inode_type == HMDFS_LAYER_OTHER_REMOTE) 2218c2ecf20Sopenharmony_ci return hmdfs_xattr_remote_set(dentry, name, value, size, flags); 2228c2ecf20Sopenharmony_ci else if (info->inode_type == HMDFS_LAYER_OTHER_MERGE || 2238c2ecf20Sopenharmony_ci info->inode_type == HMDFS_LAYER_OTHER_MERGE_CLOUD) 2248c2ecf20Sopenharmony_ci return hmdfs_xattr_merge_set(dentry, name, value, size, flags); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ciconst struct xattr_handler hmdfs_xattr_handler = { 2308c2ecf20Sopenharmony_ci .prefix = "", /* catch all */ 2318c2ecf20Sopenharmony_ci .get = hmdfs_xattr_get, 2328c2ecf20Sopenharmony_ci .set = hmdfs_xattr_set, 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic const struct xattr_handler *hmdfs_xattr_handlers[] = { 2368c2ecf20Sopenharmony_ci &hmdfs_xattr_handler, 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#define HMDFS_NODE_EVT_CB_DELAY 2 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistruct kmem_cache *hmdfs_inode_cachep; 2428c2ecf20Sopenharmony_cistruct kmem_cache *hmdfs_dentry_cachep; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic void i_callback(struct rcu_head *head) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct inode *inode = container_of(head, struct inode, i_rcu); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci kmem_cache_free(hmdfs_inode_cachep, 2498c2ecf20Sopenharmony_ci container_of(inode, struct hmdfs_inode_info, 2508c2ecf20Sopenharmony_ci vfs_inode)); 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void hmdfs_destroy_inode(struct inode *inode) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci call_rcu(&inode->i_rcu, i_callback); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic void hmdfs_evict_inode(struct inode *inode) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(inode); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci truncate_inode_pages(&inode->i_data, 0); 2638c2ecf20Sopenharmony_ci clear_inode(inode); 2648c2ecf20Sopenharmony_ci if (info->inode_type == HMDFS_LAYER_FIRST_DEVICE || 2658c2ecf20Sopenharmony_ci info->inode_type == HMDFS_LAYER_SECOND_REMOTE) 2668c2ecf20Sopenharmony_ci return; 2678c2ecf20Sopenharmony_ci if (info->inode_type == HMDFS_LAYER_ZERO || 2688c2ecf20Sopenharmony_ci info->inode_type == HMDFS_LAYER_OTHER_LOCAL || 2698c2ecf20Sopenharmony_ci info->inode_type == HMDFS_LAYER_SECOND_LOCAL) { 2708c2ecf20Sopenharmony_ci iput(info->lower_inode); 2718c2ecf20Sopenharmony_ci info->lower_inode = NULL; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_civoid hmdfs_put_super(struct super_block *sb) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 2788c2ecf20Sopenharmony_ci struct super_block *lower_sb = sbi->lower_sb; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci hmdfs_info("local_dst is %s, local_src is %s", sbi->local_dst, 2818c2ecf20Sopenharmony_ci sbi->local_src); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci hmdfs_cfn_destroy(sbi); 2848c2ecf20Sopenharmony_ci hmdfs_unregister_sysfs(sbi); 2858c2ecf20Sopenharmony_ci hmdfs_connections_stop(sbi); 2868c2ecf20Sopenharmony_ci hmdfs_clear_share_table(sbi); 2878c2ecf20Sopenharmony_ci hmdfs_destroy_server_writeback(sbi); 2888c2ecf20Sopenharmony_ci hmdfs_exit_stash(sbi); 2898c2ecf20Sopenharmony_ci atomic_dec(&lower_sb->s_active); 2908c2ecf20Sopenharmony_ci put_cred(sbi->cred); 2918c2ecf20Sopenharmony_ci if (sbi->system_cred) 2928c2ecf20Sopenharmony_ci put_cred(sbi->system_cred); 2938c2ecf20Sopenharmony_ci hmdfs_destroy_writeback(sbi); 2948c2ecf20Sopenharmony_ci kfree(sbi->local_src); 2958c2ecf20Sopenharmony_ci kfree(sbi->local_dst); 2968c2ecf20Sopenharmony_ci kfree(sbi->real_dst); 2978c2ecf20Sopenharmony_ci kfree(sbi->cache_dir); 2988c2ecf20Sopenharmony_ci kfree(sbi->cloud_dir); 2998c2ecf20Sopenharmony_ci kfifo_free(&sbi->notify_fifo); 3008c2ecf20Sopenharmony_ci sb->s_fs_info = NULL; 3018c2ecf20Sopenharmony_ci sbi->lower_sb = NULL; 3028c2ecf20Sopenharmony_ci hmdfs_release_sysfs(sbi); 3038c2ecf20Sopenharmony_ci /* After all access are completed */ 3048c2ecf20Sopenharmony_ci hmdfs_free_sb_seq(sbi->seq); 3058c2ecf20Sopenharmony_ci kfree(sbi->s_server_statis); 3068c2ecf20Sopenharmony_ci kfree(sbi->s_client_statis); 3078c2ecf20Sopenharmony_ci kfree(sbi); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic struct inode *hmdfs_alloc_inode(struct super_block *sb) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct hmdfs_inode_info *gi = 3138c2ecf20Sopenharmony_ci kmem_cache_alloc(hmdfs_inode_cachep, GFP_KERNEL); 3148c2ecf20Sopenharmony_ci if (!gi) 3158c2ecf20Sopenharmony_ci return NULL; 3168c2ecf20Sopenharmony_ci memset(gi, 0, offsetof(struct hmdfs_inode_info, vfs_inode)); 3178c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&gi->wb_list); 3188c2ecf20Sopenharmony_ci init_rwsem(&gi->wpage_sem); 3198c2ecf20Sopenharmony_ci gi->getattr_isize = HMDFS_STALE_REMOTE_ISIZE; 3208c2ecf20Sopenharmony_ci atomic64_set(&gi->write_counter, 0); 3218c2ecf20Sopenharmony_ci gi->fid.id = HMDFS_INODE_INVALID_FILE_ID; 3228c2ecf20Sopenharmony_ci spin_lock_init(&gi->fid_lock); 3238c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&gi->wr_opened_node); 3248c2ecf20Sopenharmony_ci atomic_set(&gi->wr_opened_cnt, 0); 3258c2ecf20Sopenharmony_ci init_waitqueue_head(&gi->fid_wq); 3268c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&gi->stash_node); 3278c2ecf20Sopenharmony_ci spin_lock_init(&gi->stash_lock); 3288c2ecf20Sopenharmony_ci return &gi->vfs_inode; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic int hmdfs_remote_statfs(struct dentry *dentry, struct kstatfs *buf) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci int error = 0; 3348c2ecf20Sopenharmony_ci int ret = 0; 3358c2ecf20Sopenharmony_ci char *dir_path = NULL; 3368c2ecf20Sopenharmony_ci char *name_path = NULL; 3378c2ecf20Sopenharmony_ci struct hmdfs_peer *con = NULL; 3388c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(dentry->d_inode->i_sb); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci dir_path = hmdfs_get_dentry_relative_path(dentry->d_parent); 3418c2ecf20Sopenharmony_ci if (!dir_path) { 3428c2ecf20Sopenharmony_ci error = -EACCES; 3438c2ecf20Sopenharmony_ci goto rmdir_out; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci name_path = hmdfs_connect_path(dir_path, dentry->d_name.name); 3478c2ecf20Sopenharmony_ci if (!name_path) { 3488c2ecf20Sopenharmony_ci error = -EACCES; 3498c2ecf20Sopenharmony_ci goto rmdir_out; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 3528c2ecf20Sopenharmony_ci list_for_each_entry(con, &sbi->connections.node_list, list) { 3538c2ecf20Sopenharmony_ci if (con->status == NODE_STAT_ONLINE) { 3548c2ecf20Sopenharmony_ci peer_get(con); 3558c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 3568c2ecf20Sopenharmony_ci hmdfs_debug("send MSG to remote devID %llu", 3578c2ecf20Sopenharmony_ci con->device_id); 3588c2ecf20Sopenharmony_ci ret = hmdfs_send_statfs(con, name_path, buf); 3598c2ecf20Sopenharmony_ci if (ret != 0) 3608c2ecf20Sopenharmony_ci error = ret; 3618c2ecf20Sopenharmony_ci peer_put(con); 3628c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cirmdir_out: 3688c2ecf20Sopenharmony_ci kfree(dir_path); 3698c2ecf20Sopenharmony_ci kfree(name_path); 3708c2ecf20Sopenharmony_ci return error; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic int hmdfs_statfs(struct dentry *dentry, struct kstatfs *buf) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci int err = 0; 3768c2ecf20Sopenharmony_ci struct path lower_path; 3778c2ecf20Sopenharmony_ci struct hmdfs_inode_info *info = hmdfs_i(dentry->d_inode); 3788c2ecf20Sopenharmony_ci struct super_block *sb = d_inode(dentry)->i_sb; 3798c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = sb->s_fs_info; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci trace_hmdfs_statfs(dentry, info->inode_type); 3828c2ecf20Sopenharmony_ci // merge_view & merge_view/xxx & device_view assigned src_inode info 3838c2ecf20Sopenharmony_ci if (hmdfs_i_merge(info) || 3848c2ecf20Sopenharmony_ci (info->inode_type == HMDFS_LAYER_SECOND_REMOTE)) { 3858c2ecf20Sopenharmony_ci err = kern_path(sbi->local_src, 0, &lower_path); 3868c2ecf20Sopenharmony_ci if (err) 3878c2ecf20Sopenharmony_ci goto out; 3888c2ecf20Sopenharmony_ci err = vfs_statfs(&lower_path, buf); 3898c2ecf20Sopenharmony_ci path_put(&lower_path); 3908c2ecf20Sopenharmony_ci } else if (!IS_ERR_OR_NULL(info->lower_inode)) { 3918c2ecf20Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 3928c2ecf20Sopenharmony_ci err = vfs_statfs(&lower_path, buf); 3938c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 3948c2ecf20Sopenharmony_ci } else { 3958c2ecf20Sopenharmony_ci err = hmdfs_remote_statfs(dentry, buf); 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci buf->f_type = HMDFS_SUPER_MAGIC; 3998c2ecf20Sopenharmony_ciout: 4008c2ecf20Sopenharmony_ci return err; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic int hmdfs_show_options(struct seq_file *m, struct dentry *root) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(root->d_sb); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci if (sbi->s_case_sensitive) 4088c2ecf20Sopenharmony_ci seq_puts(m, ",sensitive"); 4098c2ecf20Sopenharmony_ci else 4108c2ecf20Sopenharmony_ci seq_puts(m, ",insensitive"); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci if (sbi->s_merge_switch) 4138c2ecf20Sopenharmony_ci seq_puts(m, ",merge_enable"); 4148c2ecf20Sopenharmony_ci else 4158c2ecf20Sopenharmony_ci seq_puts(m, ",merge_disable"); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci seq_printf(m, ",ra_pages=%lu", root->d_sb->s_bdi->ra_pages); 4188c2ecf20Sopenharmony_ci seq_printf(m, ",user_id=%u", sbi->user_id); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci if (sbi->cache_dir) 4218c2ecf20Sopenharmony_ci seq_printf(m, ",cache_dir=%s", sbi->cache_dir); 4228c2ecf20Sopenharmony_ci if (sbi->real_dst) 4238c2ecf20Sopenharmony_ci seq_printf(m, ",real_dst=%s", sbi->real_dst); 4248c2ecf20Sopenharmony_ci if (sbi->cloud_dir) 4258c2ecf20Sopenharmony_ci seq_printf(m, ",cloud_dir=%s", sbi->cloud_dir); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci seq_printf(m, ",%soffline_stash", sbi->s_offline_stash ? "" : "no_"); 4288c2ecf20Sopenharmony_ci seq_printf(m, ",%sdentry_cache", sbi->s_dentry_cache ? "" : "no_"); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci return 0; 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic int hmdfs_sync_fs(struct super_block *sb, int wait) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci int time_left; 4368c2ecf20Sopenharmony_ci int err = 0; 4378c2ecf20Sopenharmony_ci struct hmdfs_peer *con = NULL; 4388c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 4398c2ecf20Sopenharmony_ci int syncfs_timeout = get_cmd_timeout(sbi, F_SYNCFS); 4408c2ecf20Sopenharmony_ci struct syncfs_item item, *entry = NULL, *tmp = NULL; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci if (!wait) 4438c2ecf20Sopenharmony_ci return 0; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci trace_hmdfs_syncfs_enter(sbi); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci spin_lock(&sbi->hsi.list_lock); 4488c2ecf20Sopenharmony_ci if (!sbi->hsi.is_executing) { 4498c2ecf20Sopenharmony_ci sbi->hsi.is_executing = true; 4508c2ecf20Sopenharmony_ci item.need_abort = false; 4518c2ecf20Sopenharmony_ci spin_unlock(&sbi->hsi.list_lock); 4528c2ecf20Sopenharmony_ci } else { 4538c2ecf20Sopenharmony_ci init_completion(&item.done); 4548c2ecf20Sopenharmony_ci list_add_tail(&item.list, &sbi->hsi.wait_list); 4558c2ecf20Sopenharmony_ci spin_unlock(&sbi->hsi.list_lock); 4568c2ecf20Sopenharmony_ci wait_for_completion(&item.done); 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (item.need_abort) 4608c2ecf20Sopenharmony_ci goto out; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* 4638c2ecf20Sopenharmony_ci * Syncfs can not concurrent in hmdfs_sync_fs. Because we should make 4648c2ecf20Sopenharmony_ci * sure all remote syncfs calls return back or timeout by waiting, 4658c2ecf20Sopenharmony_ci * during the waiting period we must protect @sbi->remote_syncfs_count 4668c2ecf20Sopenharmony_ci * and @sbi->remote_syncfs_ret from concurrent executing. 4678c2ecf20Sopenharmony_ci */ 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci spin_lock(&sbi->hsi.v_lock); 4708c2ecf20Sopenharmony_ci sbi->hsi.version++; 4718c2ecf20Sopenharmony_ci /* 4728c2ecf20Sopenharmony_ci * Attention: We put @sbi->hsi.remote_ret and @sbi->hsi.wait_count 4738c2ecf20Sopenharmony_ci * into spinlock protection area to avoid following scenario caused 4748c2ecf20Sopenharmony_ci * by out-of-order execution: 4758c2ecf20Sopenharmony_ci * 4768c2ecf20Sopenharmony_ci * synfs syncfs_cb 4778c2ecf20Sopenharmony_ci * sbi->hsi.remote_ret = 0; 4788c2ecf20Sopenharmony_ci * atomic_set(&sbi->hsi.wait_count, 0); 4798c2ecf20Sopenharmony_ci * lock 4808c2ecf20Sopenharmony_ci * version == old_version 4818c2ecf20Sopenharmony_ci * sbi->hsi.remote_ret = resp->ret_code 4828c2ecf20Sopenharmony_ci * atomic_dec(&sbi->hsi.wait_count); 4838c2ecf20Sopenharmony_ci * unlock 4848c2ecf20Sopenharmony_ci * lock 4858c2ecf20Sopenharmony_ci * version = old_version + 1 4868c2ecf20Sopenharmony_ci * unlock 4878c2ecf20Sopenharmony_ci * 4888c2ecf20Sopenharmony_ci * @sbi->hsi.remote_ret and @sbi->hsi.wait_count can be assigned 4898c2ecf20Sopenharmony_ci * before spin lock which may compete with syncfs_cb(), making 4908c2ecf20Sopenharmony_ci * these two values' assignment protected by spinlock can fix this. 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci sbi->hsi.remote_ret = 0; 4938c2ecf20Sopenharmony_ci atomic_set(&sbi->hsi.wait_count, 0); 4948c2ecf20Sopenharmony_ci spin_unlock(&sbi->hsi.v_lock); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 4978c2ecf20Sopenharmony_ci list_for_each_entry(con, &sbi->connections.node_list, list) { 4988c2ecf20Sopenharmony_ci /* 4998c2ecf20Sopenharmony_ci * Dirty data does not need to be synchronized to remote 5008c2ecf20Sopenharmony_ci * devices that go offline normally. It's okay to drop 5018c2ecf20Sopenharmony_ci * them. 5028c2ecf20Sopenharmony_ci */ 5038c2ecf20Sopenharmony_ci if (con->status != NODE_STAT_ONLINE) 5048c2ecf20Sopenharmony_ci continue; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci peer_get(con); 5078c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* 5108c2ecf20Sopenharmony_ci * There exists a gap between sync_inodes_sb() and sync_fs() 5118c2ecf20Sopenharmony_ci * which may race with remote writing, leading error count 5128c2ecf20Sopenharmony_ci * on @sb_dirty_count. The dirty data produced during the 5138c2ecf20Sopenharmony_ci * gap period won't be synced in next syncfs operation. 5148c2ecf20Sopenharmony_ci * To avoid this, we have to invoke sync_inodes_sb() again 5158c2ecf20Sopenharmony_ci * after getting @con->sb_dirty_count. 5168c2ecf20Sopenharmony_ci */ 5178c2ecf20Sopenharmony_ci con->old_sb_dirty_count = atomic64_read(&con->sb_dirty_count); 5188c2ecf20Sopenharmony_ci sync_inodes_sb(sb); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (!con->old_sb_dirty_count) { 5218c2ecf20Sopenharmony_ci peer_put(con); 5228c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 5238c2ecf20Sopenharmony_ci continue; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci err = hmdfs_send_syncfs(con, syncfs_timeout); 5278c2ecf20Sopenharmony_ci if (err) { 5288c2ecf20Sopenharmony_ci hmdfs_warning("send syncfs failed with %d on node %llu", 5298c2ecf20Sopenharmony_ci err, con->device_id); 5308c2ecf20Sopenharmony_ci sbi->hsi.remote_ret = err; 5318c2ecf20Sopenharmony_ci peer_put(con); 5328c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 5338c2ecf20Sopenharmony_ci continue; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci atomic_inc(&sbi->hsi.wait_count); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci peer_put(con); 5398c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* 5448c2ecf20Sopenharmony_ci * Async work in background will make sure @sbi->remote_syncfs_count 5458c2ecf20Sopenharmony_ci * decreased to zero finally whether syncfs success or fail. 5468c2ecf20Sopenharmony_ci */ 5478c2ecf20Sopenharmony_ci time_left = wait_event_interruptible( 5488c2ecf20Sopenharmony_ci sbi->hsi.wq, atomic_read(&sbi->hsi.wait_count) == 0); 5498c2ecf20Sopenharmony_ci if (time_left < 0) { 5508c2ecf20Sopenharmony_ci hmdfs_warning("syncfs is interrupted by external signal"); 5518c2ecf20Sopenharmony_ci err = -EINTR; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci if (!err && sbi->hsi.remote_ret) 5558c2ecf20Sopenharmony_ci err = sbi->hsi.remote_ret; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /* Abandon syncfs processes in pending_list */ 5588c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, tmp, &sbi->hsi.pending_list, list) { 5598c2ecf20Sopenharmony_ci entry->need_abort = true; 5608c2ecf20Sopenharmony_ci complete(&entry->done); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->hsi.pending_list); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* Pick the last syncfs process in wait_list */ 5658c2ecf20Sopenharmony_ci spin_lock(&sbi->hsi.list_lock); 5668c2ecf20Sopenharmony_ci if (list_empty(&sbi->hsi.wait_list)) { 5678c2ecf20Sopenharmony_ci sbi->hsi.is_executing = false; 5688c2ecf20Sopenharmony_ci } else { 5698c2ecf20Sopenharmony_ci entry = list_last_entry(&sbi->hsi.wait_list, struct syncfs_item, 5708c2ecf20Sopenharmony_ci list); 5718c2ecf20Sopenharmony_ci list_del_init(&entry->list); 5728c2ecf20Sopenharmony_ci list_splice_init(&sbi->hsi.wait_list, &sbi->hsi.pending_list); 5738c2ecf20Sopenharmony_ci entry->need_abort = false; 5748c2ecf20Sopenharmony_ci complete(&entry->done); 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci spin_unlock(&sbi->hsi.list_lock); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ciout: 5798c2ecf20Sopenharmony_ci trace_hmdfs_syncfs_exit(sbi, atomic_read(&sbi->hsi.wait_count), 5808c2ecf20Sopenharmony_ci get_cmd_timeout(sbi, F_SYNCFS), err); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci /* TODO: Return synfs err back to syscall */ 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci return err; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistruct super_operations hmdfs_sops = { 5888c2ecf20Sopenharmony_ci .alloc_inode = hmdfs_alloc_inode, 5898c2ecf20Sopenharmony_ci .destroy_inode = hmdfs_destroy_inode, 5908c2ecf20Sopenharmony_ci .evict_inode = hmdfs_evict_inode, 5918c2ecf20Sopenharmony_ci .put_super = hmdfs_put_super, 5928c2ecf20Sopenharmony_ci .statfs = hmdfs_statfs, 5938c2ecf20Sopenharmony_ci .show_options = hmdfs_show_options, 5948c2ecf20Sopenharmony_ci .sync_fs = hmdfs_sync_fs, 5958c2ecf20Sopenharmony_ci}; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic void init_once(void *obj) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci struct hmdfs_inode_info *i = obj; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci inode_init_once(&i->vfs_inode); 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic int __init hmdfs_init_caches(void) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci int err = -ENOMEM; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci hmdfs_inode_cachep = 6098c2ecf20Sopenharmony_ci kmem_cache_create("hmdfs_inode_cache", 6108c2ecf20Sopenharmony_ci sizeof(struct hmdfs_inode_info), 0, 6118c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT, init_once); 6128c2ecf20Sopenharmony_ci if (unlikely(!hmdfs_inode_cachep)) 6138c2ecf20Sopenharmony_ci goto out; 6148c2ecf20Sopenharmony_ci hmdfs_dentry_cachep = 6158c2ecf20Sopenharmony_ci kmem_cache_create("hmdfs_dentry_cache", 6168c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_info), 0, 6178c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT, NULL); 6188c2ecf20Sopenharmony_ci if (unlikely(!hmdfs_dentry_cachep)) 6198c2ecf20Sopenharmony_ci goto out_des_ino; 6208c2ecf20Sopenharmony_ci hmdfs_dentry_merge_cachep = 6218c2ecf20Sopenharmony_ci kmem_cache_create("hmdfs_dentry_merge_cache", 6228c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_info_merge), 0, 6238c2ecf20Sopenharmony_ci SLAB_RECLAIM_ACCOUNT, NULL); 6248c2ecf20Sopenharmony_ci if (unlikely(!hmdfs_dentry_merge_cachep)) 6258c2ecf20Sopenharmony_ci goto out_des_dc; 6268c2ecf20Sopenharmony_ci return 0; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ciout_des_dc: 6298c2ecf20Sopenharmony_ci kmem_cache_destroy(hmdfs_dentry_cachep); 6308c2ecf20Sopenharmony_ciout_des_ino: 6318c2ecf20Sopenharmony_ci kmem_cache_destroy(hmdfs_inode_cachep); 6328c2ecf20Sopenharmony_ciout: 6338c2ecf20Sopenharmony_ci return err; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void hmdfs_destroy_caches(void) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci rcu_barrier(); 6398c2ecf20Sopenharmony_ci kmem_cache_destroy(hmdfs_inode_cachep); 6408c2ecf20Sopenharmony_ci hmdfs_inode_cachep = NULL; 6418c2ecf20Sopenharmony_ci kmem_cache_destroy(hmdfs_dentry_cachep); 6428c2ecf20Sopenharmony_ci hmdfs_dentry_cachep = NULL; 6438c2ecf20Sopenharmony_ci kmem_cache_destroy(hmdfs_dentry_merge_cachep); 6448c2ecf20Sopenharmony_ci hmdfs_dentry_merge_cachep = NULL; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ciuint64_t path_hash(const char *path, int len, bool case_sense) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci uint64_t res = 0; 6508c2ecf20Sopenharmony_ci const char *kp = path; 6518c2ecf20Sopenharmony_ci char c; 6528c2ecf20Sopenharmony_ci /* Mocklisp hash function. */ 6538c2ecf20Sopenharmony_ci while (*kp) { 6548c2ecf20Sopenharmony_ci c = *kp; 6558c2ecf20Sopenharmony_ci if (!case_sense) 6568c2ecf20Sopenharmony_ci c = tolower(c); 6578c2ecf20Sopenharmony_ci res = (res << 5) - res + (uint64_t)(c); 6588c2ecf20Sopenharmony_ci kp++; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci return res; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic char *get_full_path(struct path *path) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci char *buf, *tmp; 6668c2ecf20Sopenharmony_ci char *ret = NULL; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci buf = kmalloc(PATH_MAX, GFP_KERNEL); 6698c2ecf20Sopenharmony_ci if (!buf) 6708c2ecf20Sopenharmony_ci goto out; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci tmp = d_path(path, buf, PATH_MAX); 6738c2ecf20Sopenharmony_ci if (IS_ERR(tmp)) 6748c2ecf20Sopenharmony_ci goto out; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci ret = kstrdup(tmp, GFP_KERNEL); 6778c2ecf20Sopenharmony_ciout: 6788c2ecf20Sopenharmony_ci kfree(buf); 6798c2ecf20Sopenharmony_ci return ret; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic void hmdfs_init_cmd_timeout(struct hmdfs_sb_info *sbi) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci memset(sbi->s_cmd_timeout, 0xff, sizeof(sbi->s_cmd_timeout)); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_OPEN, TIMEOUT_COMMON); 6878c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_RELEASE, TIMEOUT_NONE); 6888c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_READPAGE, TIMEOUT_COMMON); 6898c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_WRITEPAGE, TIMEOUT_COMMON); 6908c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_ITERATE, TIMEOUT_30S); 6918c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_CREATE, TIMEOUT_COMMON); 6928c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_MKDIR, TIMEOUT_COMMON); 6938c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_RMDIR, TIMEOUT_COMMON); 6948c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_UNLINK, TIMEOUT_COMMON); 6958c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_RENAME, TIMEOUT_COMMON); 6968c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_SETATTR, TIMEOUT_COMMON); 6978c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_STATFS, TIMEOUT_COMMON); 6988c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_CONNECT_REKEY, TIMEOUT_NONE); 6998c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_DROP_PUSH, TIMEOUT_NONE); 7008c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_GETATTR, TIMEOUT_COMMON); 7018c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_FSYNC, TIMEOUT_90S); 7028c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_SYNCFS, TIMEOUT_30S); 7038c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_GETXATTR, TIMEOUT_COMMON); 7048c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_SETXATTR, TIMEOUT_COMMON); 7058c2ecf20Sopenharmony_ci set_cmd_timeout(sbi, F_LISTXATTR, TIMEOUT_COMMON); 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic int hmdfs_init_sbi(struct hmdfs_sb_info *sbi) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci int ret; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci ret = kfifo_alloc(&sbi->notify_fifo, PAGE_SIZE, GFP_KERNEL); 7138c2ecf20Sopenharmony_ci if (ret) 7148c2ecf20Sopenharmony_ci goto out; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* 7178c2ecf20Sopenharmony_ci * We have to use dynamic memory since struct server/client_statistic 7188c2ecf20Sopenharmony_ci * are DECLARED in hmdfs.h but DEFINED in socket_adapter.h. 7198c2ecf20Sopenharmony_ci */ 7208c2ecf20Sopenharmony_ci sbi->s_server_statis = 7218c2ecf20Sopenharmony_ci kzalloc(sizeof(*sbi->s_server_statis) * F_SIZE, GFP_KERNEL); 7228c2ecf20Sopenharmony_ci sbi->s_client_statis = 7238c2ecf20Sopenharmony_ci kzalloc(sizeof(*sbi->s_client_statis) * F_SIZE, GFP_KERNEL); 7248c2ecf20Sopenharmony_ci if (!sbi->s_server_statis || !sbi->s_client_statis) { 7258c2ecf20Sopenharmony_ci ret = -ENOMEM; 7268c2ecf20Sopenharmony_ci goto out; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci ret = hmdfs_alloc_sb_seq(); 7308c2ecf20Sopenharmony_ci if (ret < 0) { 7318c2ecf20Sopenharmony_ci hmdfs_err("no sb seq available err %d", ret); 7328c2ecf20Sopenharmony_ci goto out; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci sbi->seq = ret; 7358c2ecf20Sopenharmony_ci ret = 0; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci spin_lock_init(&sbi->notify_fifo_lock); 7388c2ecf20Sopenharmony_ci mutex_init(&sbi->cmd_handler_mutex); 7398c2ecf20Sopenharmony_ci sbi->s_case_sensitive = false; 7408c2ecf20Sopenharmony_ci sbi->s_features = HMDFS_FEATURE_READPAGES | 7418c2ecf20Sopenharmony_ci HMDFS_FEATURE_READPAGES_OPEN | 7428c2ecf20Sopenharmony_ci HMDFS_ATOMIC_OPEN; 7438c2ecf20Sopenharmony_ci sbi->s_merge_switch = false; 7448c2ecf20Sopenharmony_ci sbi->s_cloud_disk_switch = false; 7458c2ecf20Sopenharmony_ci sbi->dcache_threshold = DEFAULT_DCACHE_THRESHOLD; 7468c2ecf20Sopenharmony_ci sbi->dcache_precision = DEFAULT_DCACHE_PRECISION; 7478c2ecf20Sopenharmony_ci sbi->dcache_timeout = DEFAULT_DCACHE_TIMEOUT; 7488c2ecf20Sopenharmony_ci sbi->write_cache_timeout = DEFAULT_WRITE_CACHE_TIMEOUT; 7498c2ecf20Sopenharmony_ci hmdfs_init_cmd_timeout(sbi); 7508c2ecf20Sopenharmony_ci sbi->async_cb_delay = HMDFS_NODE_EVT_CB_DELAY; 7518c2ecf20Sopenharmony_ci sbi->async_req_max_active = DEFAULT_SRV_REQ_MAX_ACTIVE; 7528c2ecf20Sopenharmony_ci sbi->s_offline_stash = true; 7538c2ecf20Sopenharmony_ci sbi->s_dentry_cache = true; 7548c2ecf20Sopenharmony_ci sbi->wb_timeout_ms = HMDFS_DEF_WB_TIMEOUT_MS; 7558c2ecf20Sopenharmony_ci sbi->s_readpages_nr = HMDFS_READPAGES_NR_DEF; 7568c2ecf20Sopenharmony_ci /* Initialize before hmdfs_register_sysfs() */ 7578c2ecf20Sopenharmony_ci atomic_set(&sbi->connections.conn_seq, 0); 7588c2ecf20Sopenharmony_ci mutex_init(&sbi->connections.node_lock); 7598c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->connections.node_list); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci ret = hmdfs_init_share_table(sbi); 7628c2ecf20Sopenharmony_ci if (ret) 7638c2ecf20Sopenharmony_ci goto out; 7648c2ecf20Sopenharmony_ci init_waitqueue_head(&sbi->async_readdir_wq); 7658c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->async_readdir_msg_list); 7668c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->async_readdir_work_list); 7678c2ecf20Sopenharmony_ci spin_lock_init(&sbi->async_readdir_msg_lock); 7688c2ecf20Sopenharmony_ci spin_lock_init(&sbi->async_readdir_work_lock); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci return 0; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ciout: 7738c2ecf20Sopenharmony_ci return ret; 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_civoid hmdfs_client_resp_statis(struct hmdfs_sb_info *sbi, u8 cmd, 7778c2ecf20Sopenharmony_ci enum hmdfs_resp_type type, unsigned long start, 7788c2ecf20Sopenharmony_ci unsigned long end) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci unsigned long duration; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci switch (type) { 7838c2ecf20Sopenharmony_ci case HMDFS_RESP_DELAY: 7848c2ecf20Sopenharmony_ci sbi->s_client_statis[cmd].delay_resp_cnt++; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci case HMDFS_RESP_TIMEOUT: 7878c2ecf20Sopenharmony_ci sbi->s_client_statis[cmd].timeout_cnt++; 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci case HMDFS_RESP_NORMAL: 7908c2ecf20Sopenharmony_ci duration = end - start; 7918c2ecf20Sopenharmony_ci sbi->s_client_statis[cmd].total += duration; 7928c2ecf20Sopenharmony_ci sbi->s_client_statis[cmd].resp_cnt++; 7938c2ecf20Sopenharmony_ci if (sbi->s_client_statis[cmd].max < duration) 7948c2ecf20Sopenharmony_ci sbi->s_client_statis[cmd].max = duration; 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci default: 7978c2ecf20Sopenharmony_ci hmdfs_err("Wrong cmd %d with resp type %d", cmd, type); 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic int hmdfs_update_dst(struct hmdfs_sb_info *sbi) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci int err = 0; 8048c2ecf20Sopenharmony_ci const char *path_local = UPDATE_LOCAL_DST; 8058c2ecf20Sopenharmony_ci int len = 0; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci sbi->real_dst = kstrdup(sbi->local_dst, GFP_KERNEL); 8088c2ecf20Sopenharmony_ci if (!sbi->real_dst) { 8098c2ecf20Sopenharmony_ci err = -ENOMEM; 8108c2ecf20Sopenharmony_ci goto out_err; 8118c2ecf20Sopenharmony_ci } 8128c2ecf20Sopenharmony_ci kfree(sbi->local_dst); 8138c2ecf20Sopenharmony_ci sbi->local_dst = NULL; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci len = strlen(sbi->real_dst) + strlen(path_local) + 1; 8168c2ecf20Sopenharmony_ci if (len > PATH_MAX) { 8178c2ecf20Sopenharmony_ci err = -EINVAL; 8188c2ecf20Sopenharmony_ci goto out_err; 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci sbi->local_dst = kmalloc(len, GFP_KERNEL); 8218c2ecf20Sopenharmony_ci if (!sbi->local_dst) { 8228c2ecf20Sopenharmony_ci err = -ENOMEM; 8238c2ecf20Sopenharmony_ci goto out_err; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci snprintf(sbi->local_dst, strlen(sbi->real_dst) + strlen(path_local) + 1, 8268c2ecf20Sopenharmony_ci "%s%s", sbi->real_dst, path_local); 8278c2ecf20Sopenharmony_ciout_err: 8288c2ecf20Sopenharmony_ci return err; 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci/* 8328c2ecf20Sopenharmony_ci * Generate boot cookie like following format: 8338c2ecf20Sopenharmony_ci * 8348c2ecf20Sopenharmony_ci * | random | boot time(ms) | 0x00 | 8358c2ecf20Sopenharmony_ci * |--------|-----------------|-------| 8368c2ecf20Sopenharmony_ci * 16 33 15 (bits) 8378c2ecf20Sopenharmony_ci * 8388c2ecf20Sopenharmony_ci * This will make sure boot cookie is unique in a period 8398c2ecf20Sopenharmony_ci * 2^33 / 1000 / 3600 / 24 = 99.4(days). 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ciuint64_t hmdfs_gen_boot_cookie(void) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci uint64_t now; 8448c2ecf20Sopenharmony_ci uint16_t rand; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci now = ktime_to_ms(ktime_get()); 8478c2ecf20Sopenharmony_ci prandom_bytes(&rand, sizeof(rand)); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci now &= (1ULL << HMDFS_BOOT_COOKIE_RAND_SHIFT) - 1; 8508c2ecf20Sopenharmony_ci now |= ((uint64_t)rand << HMDFS_BOOT_COOKIE_RAND_SHIFT); 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci return now << HMDFS_FID_VER_BOOT_COOKIE_SHIFT; 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic int hmdfs_fill_super(struct super_block *sb, void *data, int silent) 8568c2ecf20Sopenharmony_ci{ 8578c2ecf20Sopenharmony_ci struct hmdfs_mount_priv *priv = (struct hmdfs_mount_priv *)data; 8588c2ecf20Sopenharmony_ci const char *dev_name = priv->dev_name; 8598c2ecf20Sopenharmony_ci const char *raw_data = priv->raw_data; 8608c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi; 8618c2ecf20Sopenharmony_ci int err = 0; 8628c2ecf20Sopenharmony_ci struct inode *root_inode; 8638c2ecf20Sopenharmony_ci struct path lower_path; 8648c2ecf20Sopenharmony_ci struct super_block *lower_sb; 8658c2ecf20Sopenharmony_ci struct dentry *root_dentry; 8668c2ecf20Sopenharmony_ci char ctrl_path[CTRL_PATH_MAX_LEN]; 8678c2ecf20Sopenharmony_ci uint64_t ctrl_hash; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (!raw_data) 8708c2ecf20Sopenharmony_ci return -EINVAL; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 8738c2ecf20Sopenharmony_ci if (!sbi) { 8748c2ecf20Sopenharmony_ci err = -ENOMEM; 8758c2ecf20Sopenharmony_ci goto out_err; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci err = hmdfs_init_sbi(sbi); 8788c2ecf20Sopenharmony_ci if (err) 8798c2ecf20Sopenharmony_ci goto out_freesbi; 8808c2ecf20Sopenharmony_ci sbi->sb = sb; 8818c2ecf20Sopenharmony_ci err = hmdfs_parse_options(sbi, raw_data); 8828c2ecf20Sopenharmony_ci if (err) 8838c2ecf20Sopenharmony_ci goto out_freesbi; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci sb->s_fs_info = sbi; 8868c2ecf20Sopenharmony_ci sb->s_magic = HMDFS_SUPER_MAGIC; 8878c2ecf20Sopenharmony_ci sb->s_xattr = hmdfs_xattr_handlers; 8888c2ecf20Sopenharmony_ci sb->s_op = &hmdfs_sops; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci sbi->boot_cookie = hmdfs_gen_boot_cookie(); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci err = hmdfs_init_writeback(sbi); 8938c2ecf20Sopenharmony_ci if (err) 8948c2ecf20Sopenharmony_ci goto out_freesbi; 8958c2ecf20Sopenharmony_ci err = hmdfs_init_server_writeback(sbi); 8968c2ecf20Sopenharmony_ci if (err) 8978c2ecf20Sopenharmony_ci goto out_freesbi; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci err = hmdfs_init_stash(sbi); 9008c2ecf20Sopenharmony_ci if (err) 9018c2ecf20Sopenharmony_ci goto out_freesbi; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci // add ctrl sysfs node 9048c2ecf20Sopenharmony_ci ctrl_hash = path_hash(sbi->local_dst, strlen(sbi->local_dst), true); 9058c2ecf20Sopenharmony_ci scnprintf(ctrl_path, CTRL_PATH_MAX_LEN, "%llu", ctrl_hash); 9068c2ecf20Sopenharmony_ci hmdfs_debug("hash %llu", ctrl_hash); 9078c2ecf20Sopenharmony_ci err = hmdfs_register_sysfs(ctrl_path, sbi); 9088c2ecf20Sopenharmony_ci if (err) 9098c2ecf20Sopenharmony_ci goto out_freesbi; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci err = hmdfs_update_dst(sbi); 9128c2ecf20Sopenharmony_ci if (err) 9138c2ecf20Sopenharmony_ci goto out_unreg_sysfs; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, 9168c2ecf20Sopenharmony_ci &lower_path); 9178c2ecf20Sopenharmony_ci if (err) { 9188c2ecf20Sopenharmony_ci hmdfs_err("open dev failed, errno = %d", err); 9198c2ecf20Sopenharmony_ci goto out_unreg_sysfs; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci lower_sb = lower_path.dentry->d_sb; 9238c2ecf20Sopenharmony_ci atomic_inc(&lower_sb->s_active); 9248c2ecf20Sopenharmony_ci sbi->lower_sb = lower_sb; 9258c2ecf20Sopenharmony_ci sbi->local_src = get_full_path(&lower_path); 9268c2ecf20Sopenharmony_ci if (!sbi->local_src) { 9278c2ecf20Sopenharmony_ci hmdfs_err("get local_src failed!"); 9288c2ecf20Sopenharmony_ci goto out_sput; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci sb->s_time_gran = lower_sb->s_time_gran; 9328c2ecf20Sopenharmony_ci sb->s_maxbytes = lower_sb->s_maxbytes; 9338c2ecf20Sopenharmony_ci sb->s_stack_depth = lower_sb->s_stack_depth + 1; 9348c2ecf20Sopenharmony_ci if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { 9358c2ecf20Sopenharmony_ci hmdfs_err("maximum fs stacking depth exceeded"); 9368c2ecf20Sopenharmony_ci err = -EINVAL; 9378c2ecf20Sopenharmony_ci goto out_sput; 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci root_inode = fill_root_inode(sb, sbi, d_inode(lower_path.dentry)); 9408c2ecf20Sopenharmony_ci if (IS_ERR(root_inode)) { 9418c2ecf20Sopenharmony_ci err = PTR_ERR(root_inode); 9428c2ecf20Sopenharmony_ci goto out_sput; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci hmdfs_root_inode_perm_init(root_inode); 9458c2ecf20Sopenharmony_ci sb->s_root = root_dentry = d_make_root(root_inode); 9468c2ecf20Sopenharmony_ci if (!root_dentry) { 9478c2ecf20Sopenharmony_ci err = -ENOMEM; 9488c2ecf20Sopenharmony_ci goto out_sput; 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci if (sbi->s_cloud_disk_switch) 9518c2ecf20Sopenharmony_ci err = init_hmdfs_dentry_info(sbi, root_dentry, HMDFS_LAYER_SECOND_LOCAL); 9528c2ecf20Sopenharmony_ci else 9538c2ecf20Sopenharmony_ci err = init_hmdfs_dentry_info(sbi, root_dentry, HMDFS_LAYER_ZERO); 9548c2ecf20Sopenharmony_ci if (err) 9558c2ecf20Sopenharmony_ci goto out_freeroot; 9568c2ecf20Sopenharmony_ci hmdfs_set_lower_path(root_dentry, &lower_path); 9578c2ecf20Sopenharmony_ci sbi->cred = get_cred(current_cred()); 9588c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->client_cache); 9598c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->server_cache); 9608c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->to_delete); 9618c2ecf20Sopenharmony_ci mutex_init(&sbi->cache_list_lock); 9628c2ecf20Sopenharmony_ci hmdfs_cfn_load(sbi); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* Initialize syncfs info */ 9658c2ecf20Sopenharmony_ci spin_lock_init(&sbi->hsi.v_lock); 9668c2ecf20Sopenharmony_ci init_waitqueue_head(&sbi->hsi.wq); 9678c2ecf20Sopenharmony_ci sbi->hsi.version = 0; 9688c2ecf20Sopenharmony_ci sbi->hsi.is_executing = false; 9698c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->hsi.wait_list); 9708c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sbi->hsi.pending_list); 9718c2ecf20Sopenharmony_ci spin_lock_init(&sbi->hsi.list_lock); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci return err; 9748c2ecf20Sopenharmony_ciout_freeroot: 9758c2ecf20Sopenharmony_ci dput(sb->s_root); 9768c2ecf20Sopenharmony_ci sb->s_root = NULL; 9778c2ecf20Sopenharmony_ciout_sput: 9788c2ecf20Sopenharmony_ci atomic_dec(&lower_sb->s_active); 9798c2ecf20Sopenharmony_ci path_put(&lower_path); 9808c2ecf20Sopenharmony_ciout_unreg_sysfs: 9818c2ecf20Sopenharmony_ci hmdfs_unregister_sysfs(sbi); 9828c2ecf20Sopenharmony_ci hmdfs_release_sysfs(sbi); 9838c2ecf20Sopenharmony_ciout_freesbi: 9848c2ecf20Sopenharmony_ci if (sbi) { 9858c2ecf20Sopenharmony_ci sb->s_fs_info = NULL; 9868c2ecf20Sopenharmony_ci hmdfs_clear_share_table(sbi); 9878c2ecf20Sopenharmony_ci hmdfs_exit_stash(sbi); 9888c2ecf20Sopenharmony_ci hmdfs_destroy_writeback(sbi); 9898c2ecf20Sopenharmony_ci hmdfs_destroy_server_writeback(sbi); 9908c2ecf20Sopenharmony_ci kfifo_free(&sbi->notify_fifo); 9918c2ecf20Sopenharmony_ci hmdfs_free_sb_seq(sbi->seq); 9928c2ecf20Sopenharmony_ci kfree(sbi->local_src); 9938c2ecf20Sopenharmony_ci kfree(sbi->local_dst); 9948c2ecf20Sopenharmony_ci kfree(sbi->real_dst); 9958c2ecf20Sopenharmony_ci kfree(sbi->cache_dir); 9968c2ecf20Sopenharmony_ci kfree(sbi->cloud_dir); 9978c2ecf20Sopenharmony_ci kfree(sbi->s_server_statis); 9988c2ecf20Sopenharmony_ci kfree(sbi->s_client_statis); 9998c2ecf20Sopenharmony_ci kfree(sbi); 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ciout_err: 10028c2ecf20Sopenharmony_ci return err; 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic struct dentry *hmdfs_mount(struct file_system_type *fs_type, int flags, 10068c2ecf20Sopenharmony_ci const char *dev_name, void *raw_data) 10078c2ecf20Sopenharmony_ci{ 10088c2ecf20Sopenharmony_ci struct hmdfs_mount_priv priv = { 10098c2ecf20Sopenharmony_ci .dev_name = dev_name, 10108c2ecf20Sopenharmony_ci .raw_data = raw_data, 10118c2ecf20Sopenharmony_ci }; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci /* hmdfs needs a valid dev_name to get the lower_sb's metadata */ 10148c2ecf20Sopenharmony_ci if (!dev_name || !*dev_name) 10158c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10168c2ecf20Sopenharmony_ci return mount_nodev(fs_type, flags, &priv, hmdfs_fill_super); 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_cistatic void hmdfs_cancel_async_readdir(struct hmdfs_sb_info *sbi) 10218c2ecf20Sopenharmony_ci{ 10228c2ecf20Sopenharmony_ci struct sendmsg_wait_queue *msg_wq = NULL; 10238c2ecf20Sopenharmony_ci struct hmdfs_readdir_work *rw = NULL; 10248c2ecf20Sopenharmony_ci struct hmdfs_readdir_work *tmp = NULL; 10258c2ecf20Sopenharmony_ci struct list_head del_work; 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* cancel work that are not running */ 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&del_work); 10308c2ecf20Sopenharmony_ci spin_lock(&sbi->async_readdir_work_lock); 10318c2ecf20Sopenharmony_ci list_for_each_entry_safe(rw, tmp, &sbi->async_readdir_work_list, head) { 10328c2ecf20Sopenharmony_ci if (cancel_delayed_work(&rw->dwork)) 10338c2ecf20Sopenharmony_ci list_move(&rw->head, &del_work); 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci spin_unlock(&sbi->async_readdir_work_lock); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci list_for_each_entry_safe(rw, tmp, &del_work, head) { 10388c2ecf20Sopenharmony_ci dput(rw->dentry); 10398c2ecf20Sopenharmony_ci peer_put(rw->con); 10408c2ecf20Sopenharmony_ci kfree(rw); 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci /* wake up async readdir that are waiting for remote */ 10448c2ecf20Sopenharmony_ci spin_lock(&sbi->async_readdir_msg_lock); 10458c2ecf20Sopenharmony_ci sbi->async_readdir_prohibit = true; 10468c2ecf20Sopenharmony_ci list_for_each_entry(msg_wq, &sbi->async_readdir_msg_list, async_msg) 10478c2ecf20Sopenharmony_ci hmdfs_response_wakeup(msg_wq, -EINTR, 0, NULL); 10488c2ecf20Sopenharmony_ci spin_unlock(&sbi->async_readdir_msg_lock); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* wait for all async readdir to finish */ 10518c2ecf20Sopenharmony_ci if (!list_empty(&sbi->async_readdir_work_list)) 10528c2ecf20Sopenharmony_ci wait_event_interruptible_timeout(sbi->async_readdir_wq, 10538c2ecf20Sopenharmony_ci (list_empty(&sbi->async_readdir_work_list)), HZ); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci WARN_ON(!(list_empty(&sbi->async_readdir_work_list))); 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic void hmdfs_kill_super(struct super_block *sb) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci /* 10638c2ecf20Sopenharmony_ci * async readdir is holding ref for dentry, not for vfsmount. Thus 10648c2ecf20Sopenharmony_ci * shrink_dcache_for_umount() will warn about dentry still in use 10658c2ecf20Sopenharmony_ci * if async readdir is not done. 10668c2ecf20Sopenharmony_ci */ 10678c2ecf20Sopenharmony_ci if (sbi) 10688c2ecf20Sopenharmony_ci hmdfs_cancel_async_readdir(sbi); 10698c2ecf20Sopenharmony_ci kill_anon_super(sb); 10708c2ecf20Sopenharmony_ci} 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_cistatic struct file_system_type hmdfs_fs_type = { 10738c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10748c2ecf20Sopenharmony_ci .name = "hmdfs", 10758c2ecf20Sopenharmony_ci .mount = hmdfs_mount, 10768c2ecf20Sopenharmony_ci .kill_sb = hmdfs_kill_super, 10778c2ecf20Sopenharmony_ci}; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_cistatic int __init hmdfs_init(void) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci int err = 0; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci err = hmdfs_init_caches(); 10848c2ecf20Sopenharmony_ci if (err) 10858c2ecf20Sopenharmony_ci goto out_err; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci hmdfs_node_evt_cb_init(); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci hmdfs_stash_add_node_evt_cb(); 10908c2ecf20Sopenharmony_ci hmdfs_client_add_node_evt_cb(); 10918c2ecf20Sopenharmony_ci hmdfs_server_add_node_evt_cb(); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci err = register_filesystem(&hmdfs_fs_type); 10948c2ecf20Sopenharmony_ci if (err) { 10958c2ecf20Sopenharmony_ci hmdfs_err("hmdfs register failed!"); 10968c2ecf20Sopenharmony_ci goto out_err; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci err = hmdfs_init_configfs(); 11008c2ecf20Sopenharmony_ci if (err) 11018c2ecf20Sopenharmony_ci goto out_err; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci err = hmdfs_sysfs_init(); 11048c2ecf20Sopenharmony_ci if (err) 11058c2ecf20Sopenharmony_ci goto out_err; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci hmdfs_message_verify_init(); 11088c2ecf20Sopenharmony_ci return 0; 11098c2ecf20Sopenharmony_ciout_err: 11108c2ecf20Sopenharmony_ci hmdfs_sysfs_exit(); 11118c2ecf20Sopenharmony_ci hmdfs_exit_configfs(); 11128c2ecf20Sopenharmony_ci unregister_filesystem(&hmdfs_fs_type); 11138c2ecf20Sopenharmony_ci hmdfs_destroy_caches(); 11148c2ecf20Sopenharmony_ci hmdfs_err("hmdfs init failed!"); 11158c2ecf20Sopenharmony_ci return err; 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic void __exit hmdfs_exit(void) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci hmdfs_sysfs_exit(); 11218c2ecf20Sopenharmony_ci hmdfs_exit_configfs(); 11228c2ecf20Sopenharmony_ci unregister_filesystem(&hmdfs_fs_type); 11238c2ecf20Sopenharmony_ci ida_destroy(&hmdfs_sb_seq); 11248c2ecf20Sopenharmony_ci hmdfs_destroy_caches(); 11258c2ecf20Sopenharmony_ci hmdfs_info("hmdfs exited!"); 11268c2ecf20Sopenharmony_ci} 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_cimodule_init(hmdfs_init); 11298c2ecf20Sopenharmony_cimodule_exit(hmdfs_exit); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ciEXPORT_TRACEPOINT_SYMBOL_GPL(hmdfs_recv_mesg_callback); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 11348c2ecf20Sopenharmony_ciMODULE_AUTHOR("LongPing.WEI, Jingjing.Mao"); 11358c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Harmony distributed file system"); 1136