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