18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/hmdfs/hmdfs_dentryfile.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "hmdfs_dentryfile.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/ctype.h>
118c2ecf20Sopenharmony_ci#include <linux/file.h>
128c2ecf20Sopenharmony_ci#include <linux/mount.h>
138c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/xattr.h>
168c2ecf20Sopenharmony_ci#include <linux/err.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "authority/authentication.h"
198c2ecf20Sopenharmony_ci#include "comm/transport.h"
208c2ecf20Sopenharmony_ci#include "hmdfs_client.h"
218c2ecf20Sopenharmony_ci#include "hmdfs_device_view.h"
228c2ecf20Sopenharmony_ci#include "hmdfs_merge_view.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* Hashing code copied from f2fs */
258c2ecf20Sopenharmony_ci#define HMDFS_HASH_COL_BIT ((0x1ULL) << 63)
268c2ecf20Sopenharmony_ci#define DELTA		   0x9E3779B9
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic bool is_dot_dotdot(const unsigned char *name, __u32 len)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	if (len == 1 && name[0] == '.')
318c2ecf20Sopenharmony_ci		return true;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	if (len == 2 && name[0] == '.' && name[1] == '.')
348c2ecf20Sopenharmony_ci		return true;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	return false;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic void str2hashbuf(const unsigned char *msg, size_t len, unsigned int *buf,
408c2ecf20Sopenharmony_ci			int num, bool case_sense)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	unsigned int pad, val;
438c2ecf20Sopenharmony_ci	int i;
448c2ecf20Sopenharmony_ci	unsigned char c;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	pad = (__u32)len | ((__u32)len << 8);
478c2ecf20Sopenharmony_ci	pad |= pad << 16;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	val = pad;
508c2ecf20Sopenharmony_ci	if (len > (size_t)num * 4)
518c2ecf20Sopenharmony_ci		len = (size_t)num * 4;
528c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++) {
538c2ecf20Sopenharmony_ci		if ((i % 4) == 0)
548c2ecf20Sopenharmony_ci			val = pad;
558c2ecf20Sopenharmony_ci		c = msg[i];
568c2ecf20Sopenharmony_ci		if (!case_sense)
578c2ecf20Sopenharmony_ci			c = tolower(c);
588c2ecf20Sopenharmony_ci		val = c + (val << 8);
598c2ecf20Sopenharmony_ci		if ((i % 4) == 3) {
608c2ecf20Sopenharmony_ci			*buf++ = val;
618c2ecf20Sopenharmony_ci			val = pad;
628c2ecf20Sopenharmony_ci			num--;
638c2ecf20Sopenharmony_ci		}
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci	if (--num >= 0)
668c2ecf20Sopenharmony_ci		*buf++ = val;
678c2ecf20Sopenharmony_ci	while (--num >= 0)
688c2ecf20Sopenharmony_ci		*buf++ = pad;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic void tea_transform(unsigned int buf[4], unsigned int const in[])
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	__u32 sum = 0;
748c2ecf20Sopenharmony_ci	__u32 b0 = buf[0], b1 = buf[1];
758c2ecf20Sopenharmony_ci	__u32 a = in[0], b = in[1], c = in[2], d = in[3];
768c2ecf20Sopenharmony_ci	int n = 16;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	do {
798c2ecf20Sopenharmony_ci		sum += DELTA;
808c2ecf20Sopenharmony_ci		b0 += ((b1 << 4) + a) ^ (b1 + sum) ^ ((b1 >> 5) + b);
818c2ecf20Sopenharmony_ci		b1 += ((b0 << 4) + c) ^ (b0 + sum) ^ ((b0 >> 5) + d);
828c2ecf20Sopenharmony_ci	} while (--n);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	buf[0] += b0;
858c2ecf20Sopenharmony_ci	buf[1] += b1;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci__u32 hmdfs_dentry_hash(const struct qstr *qstr, bool case_sense)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	__u32 hash;
918c2ecf20Sopenharmony_ci	__u32 hmdfs_hash;
928c2ecf20Sopenharmony_ci	const unsigned char *p = qstr->name;
938c2ecf20Sopenharmony_ci	__u32 len = qstr->len;
948c2ecf20Sopenharmony_ci	__u32 in[8], buf[4];
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if (is_dot_dotdot(p, len))
978c2ecf20Sopenharmony_ci		return 0;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* Initialize the default seed for the hash checksum functions */
1008c2ecf20Sopenharmony_ci	buf[0] = 0x67452301;
1018c2ecf20Sopenharmony_ci	buf[1] = 0xefcdab89;
1028c2ecf20Sopenharmony_ci	buf[2] = 0x98badcfe;
1038c2ecf20Sopenharmony_ci	buf[3] = 0x10325476;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	while (1) {
1068c2ecf20Sopenharmony_ci		str2hashbuf(p, len, in, 4, case_sense);
1078c2ecf20Sopenharmony_ci		tea_transform(buf, in);
1088c2ecf20Sopenharmony_ci		p += 16;
1098c2ecf20Sopenharmony_ci		if (len <= 16)
1108c2ecf20Sopenharmony_ci			break;
1118c2ecf20Sopenharmony_ci		len -= 16;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci	hash = buf[0];
1148c2ecf20Sopenharmony_ci	hmdfs_hash = hash & ~HMDFS_HASH_COL_BIT;
1158c2ecf20Sopenharmony_ci	return hmdfs_hash;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic atomic_t curr_ino = ATOMIC_INIT(INUNUMBER_START);
1198c2ecf20Sopenharmony_ciint get_inonumber(void)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	return atomic_inc_return(&curr_ino);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic int hmdfs_get_root_dentry_type(struct dentry *dentry, int *is_root)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	*is_root = 1;
1298c2ecf20Sopenharmony_ci	switch (d_info->dentry_type) {
1308c2ecf20Sopenharmony_ci	case HMDFS_LAYER_OTHER_LOCAL:
1318c2ecf20Sopenharmony_ci		*is_root = 0;
1328c2ecf20Sopenharmony_ci		fallthrough;
1338c2ecf20Sopenharmony_ci	case HMDFS_LAYER_SECOND_LOCAL:
1348c2ecf20Sopenharmony_ci		return HMDFS_LAYER_SECOND_LOCAL;
1358c2ecf20Sopenharmony_ci	case HMDFS_LAYER_OTHER_CLOUD:
1368c2ecf20Sopenharmony_ci		*is_root = 0;
1378c2ecf20Sopenharmony_ci		fallthrough;
1388c2ecf20Sopenharmony_ci	case HMDFS_LAYER_SECOND_CLOUD:
1398c2ecf20Sopenharmony_ci		return HMDFS_LAYER_SECOND_CLOUD;
1408c2ecf20Sopenharmony_ci	case HMDFS_LAYER_OTHER_REMOTE:
1418c2ecf20Sopenharmony_ci		*is_root = 0;
1428c2ecf20Sopenharmony_ci		fallthrough;
1438c2ecf20Sopenharmony_ci	case HMDFS_LAYER_SECOND_REMOTE:
1448c2ecf20Sopenharmony_ci		return HMDFS_LAYER_SECOND_REMOTE;
1458c2ecf20Sopenharmony_ci	default:
1468c2ecf20Sopenharmony_ci		hmdfs_info("Unexpected dentry type %d", d_info->dentry_type);
1478c2ecf20Sopenharmony_ci		return -EINVAL;
1488c2ecf20Sopenharmony_ci	}
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic int prepend(char **buffer, int *buflen, const char *str, int namelen)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	*buflen -= namelen;
1548c2ecf20Sopenharmony_ci	if (*buflen < 0)
1558c2ecf20Sopenharmony_ci		return -ENAMETOOLONG;
1568c2ecf20Sopenharmony_ci	*buffer -= namelen;
1578c2ecf20Sopenharmony_ci	memcpy(*buffer, str, namelen);
1588c2ecf20Sopenharmony_ci	return 0;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic int prepend_name(char **buffer, int *buflen, const struct qstr *name)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	const char *dname = name->name;
1648c2ecf20Sopenharmony_ci	u32 dlen = name->len;
1658c2ecf20Sopenharmony_ci	char *p = NULL;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	*buflen -= dlen + 1;
1688c2ecf20Sopenharmony_ci	if (*buflen < 0)
1698c2ecf20Sopenharmony_ci		return -ENAMETOOLONG;
1708c2ecf20Sopenharmony_ci	p = *buffer -= dlen + 1;
1718c2ecf20Sopenharmony_ci	*p++ = '/';
1728c2ecf20Sopenharmony_ci	while (dlen--) {
1738c2ecf20Sopenharmony_ci		char c = *dname++;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		if (!c)
1768c2ecf20Sopenharmony_ci			break;
1778c2ecf20Sopenharmony_ci		*p++ = c;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci	return 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic char *hmdfs_dentry_path_raw(struct dentry *d, char *buf, int buflen)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct dentry *dentry = NULL;
1858c2ecf20Sopenharmony_ci	char *end = NULL;
1868c2ecf20Sopenharmony_ci	char *retval = NULL;
1878c2ecf20Sopenharmony_ci	unsigned int len;
1888c2ecf20Sopenharmony_ci	unsigned int seq = 0;
1898c2ecf20Sopenharmony_ci	int root_flag = 0;
1908c2ecf20Sopenharmony_ci	int error = 0;
1918c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *di = hmdfs_d(d);
1928c2ecf20Sopenharmony_ci	int hmdfs_root_dentry_type = 0;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	di->time = jiffies;
1958c2ecf20Sopenharmony_ci	hmdfs_root_dentry_type = hmdfs_get_root_dentry_type(d, &root_flag);
1968c2ecf20Sopenharmony_ci	if (hmdfs_root_dentry_type < 0)
1978c2ecf20Sopenharmony_ci		return NULL;
1988c2ecf20Sopenharmony_ci	if (root_flag) {
1998c2ecf20Sopenharmony_ci		strcpy(buf, "/");
2008c2ecf20Sopenharmony_ci		return buf;
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci	rcu_read_lock();
2038c2ecf20Sopenharmony_cirestart:
2048c2ecf20Sopenharmony_ci	dentry = d;
2058c2ecf20Sopenharmony_ci	di = hmdfs_d(dentry);
2068c2ecf20Sopenharmony_ci	di->time = jiffies;
2078c2ecf20Sopenharmony_ci	end = buf + buflen;
2088c2ecf20Sopenharmony_ci	len = buflen;
2098c2ecf20Sopenharmony_ci	prepend(&end, &len, "\0", 1);
2108c2ecf20Sopenharmony_ci	retval = end - 1;
2118c2ecf20Sopenharmony_ci	*retval = '/';
2128c2ecf20Sopenharmony_ci	read_seqbegin_or_lock(&rename_lock, &seq);
2138c2ecf20Sopenharmony_ci	while (di->dentry_type != hmdfs_root_dentry_type) {
2148c2ecf20Sopenharmony_ci		struct dentry *parent = dentry->d_parent;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		prefetch(parent);
2178c2ecf20Sopenharmony_ci		error = prepend_name(&end, &len, &dentry->d_name);
2188c2ecf20Sopenharmony_ci		if (error)
2198c2ecf20Sopenharmony_ci			break;
2208c2ecf20Sopenharmony_ci		retval = end;
2218c2ecf20Sopenharmony_ci		dentry = parent;
2228c2ecf20Sopenharmony_ci		di = hmdfs_d(dentry);
2238c2ecf20Sopenharmony_ci		di->time = jiffies;
2248c2ecf20Sopenharmony_ci	}
2258c2ecf20Sopenharmony_ci	if (!(seq & 1))
2268c2ecf20Sopenharmony_ci		rcu_read_unlock();
2278c2ecf20Sopenharmony_ci	if (need_seqretry(&rename_lock, seq)) {
2288c2ecf20Sopenharmony_ci		seq = 1;
2298c2ecf20Sopenharmony_ci		goto restart;
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci	done_seqretry(&rename_lock, seq);
2328c2ecf20Sopenharmony_ci	if (error)
2338c2ecf20Sopenharmony_ci		goto Elong;
2348c2ecf20Sopenharmony_ci	return retval;
2358c2ecf20Sopenharmony_ciElong:
2368c2ecf20Sopenharmony_ci	return ERR_PTR(-ENAMETOOLONG);
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cichar *hmdfs_get_dentry_relative_path(struct dentry *dentry)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	char *final_buf = NULL;
2428c2ecf20Sopenharmony_ci	char *buf = NULL;
2438c2ecf20Sopenharmony_ci	char *p = NULL;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	buf = kzalloc(PATH_MAX, GFP_KERNEL);
2468c2ecf20Sopenharmony_ci	if (!buf)
2478c2ecf20Sopenharmony_ci		return NULL;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	final_buf = kzalloc(PATH_MAX, GFP_KERNEL);
2508c2ecf20Sopenharmony_ci	if (!final_buf) {
2518c2ecf20Sopenharmony_ci		kfree(buf);
2528c2ecf20Sopenharmony_ci		return NULL;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	/* NULL dentry return root dir */
2568c2ecf20Sopenharmony_ci	if (!dentry) {
2578c2ecf20Sopenharmony_ci		strcpy(final_buf, "/");
2588c2ecf20Sopenharmony_ci		kfree(buf);
2598c2ecf20Sopenharmony_ci		return final_buf;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci	p = hmdfs_dentry_path_raw(dentry, buf, PATH_MAX);
2628c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(p)) {
2638c2ecf20Sopenharmony_ci		kfree(buf);
2648c2ecf20Sopenharmony_ci		kfree(final_buf);
2658c2ecf20Sopenharmony_ci		return NULL;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if (strlen(p) >= PATH_MAX) {
2698c2ecf20Sopenharmony_ci		kfree(buf);
2708c2ecf20Sopenharmony_ci		kfree(final_buf);
2718c2ecf20Sopenharmony_ci		return NULL;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci	strcpy(final_buf, p);
2748c2ecf20Sopenharmony_ci	kfree(buf);
2758c2ecf20Sopenharmony_ci	return final_buf;
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_cistatic char *hmdfs_merge_dentry_path_raw(struct dentry *d, char *buf, int buflen)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	struct dentry *dentry = NULL;
2818c2ecf20Sopenharmony_ci	char *end = NULL;
2828c2ecf20Sopenharmony_ci	char *retval = NULL;
2838c2ecf20Sopenharmony_ci	unsigned int len;
2848c2ecf20Sopenharmony_ci	unsigned int seq = 0;
2858c2ecf20Sopenharmony_ci	int error = 0;
2868c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info_merge *mdi = NULL;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	rcu_read_lock();
2898c2ecf20Sopenharmony_cirestart:
2908c2ecf20Sopenharmony_ci	mdi = hmdfs_dm(d);
2918c2ecf20Sopenharmony_ci	dentry = d;
2928c2ecf20Sopenharmony_ci	end = buf + buflen;
2938c2ecf20Sopenharmony_ci	len = buflen;
2948c2ecf20Sopenharmony_ci	prepend(&end, &len, "\0", 1);
2958c2ecf20Sopenharmony_ci	retval = end - 1;
2968c2ecf20Sopenharmony_ci	*retval = '/';
2978c2ecf20Sopenharmony_ci	read_seqbegin_or_lock(&rename_lock, &seq);
2988c2ecf20Sopenharmony_ci	while (mdi->dentry_type != HMDFS_LAYER_FIRST_MERGE &&
2998c2ecf20Sopenharmony_ci	       mdi->dentry_type != HMDFS_LAYER_FIRST_MERGE_CLOUD) {
3008c2ecf20Sopenharmony_ci		struct dentry *parent = dentry->d_parent;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		prefetch(parent);
3038c2ecf20Sopenharmony_ci		error = prepend_name(&end, &len, &dentry->d_name);
3048c2ecf20Sopenharmony_ci		if (error)
3058c2ecf20Sopenharmony_ci			break;
3068c2ecf20Sopenharmony_ci		retval = end;
3078c2ecf20Sopenharmony_ci		dentry = parent;
3088c2ecf20Sopenharmony_ci		mdi = hmdfs_dm(dentry);
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci	if (!(seq & 1))
3118c2ecf20Sopenharmony_ci		rcu_read_unlock();
3128c2ecf20Sopenharmony_ci	if (need_seqretry(&rename_lock, seq)) {
3138c2ecf20Sopenharmony_ci		seq = 1;
3148c2ecf20Sopenharmony_ci		goto restart;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci	done_seqretry(&rename_lock, seq);
3178c2ecf20Sopenharmony_ci	if (error)
3188c2ecf20Sopenharmony_ci		goto Elong;
3198c2ecf20Sopenharmony_ci	return retval;
3208c2ecf20Sopenharmony_ciElong:
3218c2ecf20Sopenharmony_ci	return ERR_PTR(-ENAMETOOLONG);
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cichar *hmdfs_merge_get_dentry_relative_path(struct dentry *dentry)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	char *final_buf = NULL;
3278c2ecf20Sopenharmony_ci	char *buf = NULL;
3288c2ecf20Sopenharmony_ci	char *p = NULL;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	buf = kzalloc(PATH_MAX, GFP_KERNEL);
3318c2ecf20Sopenharmony_ci	if (!buf)
3328c2ecf20Sopenharmony_ci		return NULL;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	final_buf = kzalloc(PATH_MAX, GFP_KERNEL);
3358c2ecf20Sopenharmony_ci	if (!final_buf) {
3368c2ecf20Sopenharmony_ci		kfree(buf);
3378c2ecf20Sopenharmony_ci		return NULL;
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	/* NULL dentry return root dir */
3418c2ecf20Sopenharmony_ci	if (!dentry) {
3428c2ecf20Sopenharmony_ci		strcpy(final_buf, "/");
3438c2ecf20Sopenharmony_ci		kfree(buf);
3448c2ecf20Sopenharmony_ci		return final_buf;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci	p = hmdfs_merge_dentry_path_raw(dentry, buf, PATH_MAX);
3478c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(p)) {
3488c2ecf20Sopenharmony_ci		kfree(buf);
3498c2ecf20Sopenharmony_ci		kfree(final_buf);
3508c2ecf20Sopenharmony_ci		return NULL;
3518c2ecf20Sopenharmony_ci	}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	if (strlen(p) >= PATH_MAX) {
3548c2ecf20Sopenharmony_ci		kfree(buf);
3558c2ecf20Sopenharmony_ci		kfree(final_buf);
3568c2ecf20Sopenharmony_ci		return NULL;
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci	strcpy(final_buf, p);
3598c2ecf20Sopenharmony_ci	kfree(buf);
3608c2ecf20Sopenharmony_ci	return final_buf;
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cichar *hmdfs_get_dentry_absolute_path(const char *rootdir,
3648c2ecf20Sopenharmony_ci				     const char *relative_path)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	char *buf = 0;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	if (!rootdir || !relative_path)
3698c2ecf20Sopenharmony_ci		return NULL;
3708c2ecf20Sopenharmony_ci	if (strlen(rootdir) + strlen(relative_path) >= PATH_MAX)
3718c2ecf20Sopenharmony_ci		return NULL;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	buf = kzalloc(PATH_MAX, GFP_KERNEL);
3748c2ecf20Sopenharmony_ci	if (!buf)
3758c2ecf20Sopenharmony_ci		return NULL;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	strcpy(buf, rootdir);
3788c2ecf20Sopenharmony_ci	strcat(buf, relative_path);
3798c2ecf20Sopenharmony_ci	return buf;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cichar *hmdfs_connect_path(const char *path, const char *name)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	char *buf = 0;
3858c2ecf20Sopenharmony_ci	size_t path_len, name_len;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	if (!path || !name)
3888c2ecf20Sopenharmony_ci		return NULL;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	path_len = strnlen(path, PATH_MAX);
3918c2ecf20Sopenharmony_ci	name_len = strnlen(name, PATH_MAX);
3928c2ecf20Sopenharmony_ci	if (path_len + name_len + 1 >= PATH_MAX)
3938c2ecf20Sopenharmony_ci		return NULL;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	buf = kzalloc(PATH_MAX, GFP_KERNEL);
3968c2ecf20Sopenharmony_ci	if (!buf)
3978c2ecf20Sopenharmony_ci		return NULL;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	strncpy(buf, path, path_len);
4008c2ecf20Sopenharmony_ci	strcat(buf, "/");
4018c2ecf20Sopenharmony_ci	strncat(buf, name, name_len);
4028c2ecf20Sopenharmony_ci	return buf;
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ciint hmdfs_metainfo_read_nocred(struct file *filp,
4068c2ecf20Sopenharmony_ci		void *buffer, int size, int bidx)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	loff_t pos = get_dentry_group_pos(bidx);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	return kernel_read(filp, buffer, (size_t)size, &pos);
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ciint hmdfs_metainfo_read(struct hmdfs_sb_info *sbi, struct file *filp,
4148c2ecf20Sopenharmony_ci			void *buffer, int size, int bidx)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	loff_t pos = get_dentry_group_pos(bidx);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return cache_file_read(sbi, filp, buffer, (size_t)size, &pos);
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ciint hmdfs_metainfo_write(struct hmdfs_sb_info *sbi, struct file *filp,
4228c2ecf20Sopenharmony_ci			 const void *buffer, int size, int bidx)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	loff_t pos = get_dentry_group_pos(bidx);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	return cache_file_write(sbi, filp, buffer, (size_t)size, &pos);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci/* for each level */
4308c2ecf20Sopenharmony_ci/* bucketseq start offset by 0,for example
4318c2ecf20Sopenharmony_ci * level0  bucket0(0)
4328c2ecf20Sopenharmony_ci * level1  bucket0(1) bucket1(2)
4338c2ecf20Sopenharmony_ci * level2  bucket0(3) bucket1(4) bucket2(5) bucket3(6)
4348c2ecf20Sopenharmony_ci * return bucket number.
4358c2ecf20Sopenharmony_ci */
4368c2ecf20Sopenharmony_ci__u64 get_bucketaddr(unsigned int level, __u64 buckoffset)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	__u64 all_level_bucketaddr = 0;
4398c2ecf20Sopenharmony_ci	__u64 curlevelmaxbucks;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if (level >= MAX_BUCKET_LEVEL) {
4428c2ecf20Sopenharmony_ci		hmdfs_err("level = %d overflow", level);
4438c2ecf20Sopenharmony_ci		return all_level_bucketaddr;
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci	curlevelmaxbucks = ((__u64)1 << level);
4468c2ecf20Sopenharmony_ci	if (buckoffset >= curlevelmaxbucks) {
4478c2ecf20Sopenharmony_ci		hmdfs_err("buckoffset %llu overflow, level %d has %llu buckets max",
4488c2ecf20Sopenharmony_ci			  buckoffset, level, curlevelmaxbucks);
4498c2ecf20Sopenharmony_ci		return all_level_bucketaddr;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci	all_level_bucketaddr = curlevelmaxbucks + buckoffset - 1;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	return all_level_bucketaddr;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci__u64 get_bucket_by_level(unsigned int level)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	__u64 buckets = 0;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	if (level >= MAX_BUCKET_LEVEL) {
4618c2ecf20Sopenharmony_ci		hmdfs_err("level = %d overflow", level);
4628c2ecf20Sopenharmony_ci		return buckets;
4638c2ecf20Sopenharmony_ci	}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	buckets = ((__u64)1 << level);
4668c2ecf20Sopenharmony_ci	return buckets;
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_cistatic __u64 get_overall_bucket(unsigned int level)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	__u64 buckets = 0;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	if (level >= MAX_BUCKET_LEVEL) {
4748c2ecf20Sopenharmony_ci		hmdfs_err("level = %d overflow", level);
4758c2ecf20Sopenharmony_ci		return buckets;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci	buckets = ((__u64)1 << (level + 1)) - 1;
4788c2ecf20Sopenharmony_ci	return buckets;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic inline loff_t get_dcache_file_size(unsigned int level)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	loff_t buckets = get_overall_bucket(level);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	return buckets * DENTRYGROUP_SIZE * BUCKET_BLOCKS + DENTRYGROUP_HEADER;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic char *get_relative_path(struct hmdfs_sb_info *sbi, char *from)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	char *relative;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	if (strncmp(from, sbi->local_src, strlen(sbi->local_src))) {
4938c2ecf20Sopenharmony_ci		hmdfs_warning("orig path do not start with local_src");
4948c2ecf20Sopenharmony_ci		return NULL;
4958c2ecf20Sopenharmony_ci	}
4968c2ecf20Sopenharmony_ci	relative = from + strlen(sbi->local_src);
4978c2ecf20Sopenharmony_ci	if (*relative == '/')
4988c2ecf20Sopenharmony_ci		relative++;
4998c2ecf20Sopenharmony_ci	return relative;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistruct file *hmdfs_get_or_create_dents(struct hmdfs_sb_info *sbi, char *name)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct path root_path, path;
5058c2ecf20Sopenharmony_ci	struct file *filp = NULL;
5068c2ecf20Sopenharmony_ci	char *relative;
5078c2ecf20Sopenharmony_ci	int err;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	err = kern_path(sbi->local_src, 0, &root_path);
5108c2ecf20Sopenharmony_ci	if (err) {
5118c2ecf20Sopenharmony_ci		hmdfs_err("kern_path failed err = %d", err);
5128c2ecf20Sopenharmony_ci		return NULL;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci	relative = get_relative_path(sbi, name);
5158c2ecf20Sopenharmony_ci	if (!relative) {
5168c2ecf20Sopenharmony_ci		hmdfs_err("get relative path failed");
5178c2ecf20Sopenharmony_ci		goto err_root_path;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci	err = vfs_path_lookup(root_path.dentry, root_path.mnt, relative, 0,
5208c2ecf20Sopenharmony_ci			      &path);
5218c2ecf20Sopenharmony_ci	if (err) {
5228c2ecf20Sopenharmony_ci		hmdfs_err("lookup failed err = %d", err);
5238c2ecf20Sopenharmony_ci		goto err_root_path;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	filp = hmdfs_server_cache_revalidate(sbi, relative, &path);
5278c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(filp)) {
5288c2ecf20Sopenharmony_ci		filp = hmdfs_server_rebuild_dents(sbi, &path, NULL, relative);
5298c2ecf20Sopenharmony_ci		if (IS_ERR_OR_NULL(filp))
5308c2ecf20Sopenharmony_ci			goto err_lookup_path;
5318c2ecf20Sopenharmony_ci	}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cierr_lookup_path:
5348c2ecf20Sopenharmony_ci	path_put(&path);
5358c2ecf20Sopenharmony_cierr_root_path:
5368c2ecf20Sopenharmony_ci	path_put(&root_path);
5378c2ecf20Sopenharmony_ci	return filp;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci/* read all dentry in target path directory */
5418c2ecf20Sopenharmony_ciint read_dentry(struct hmdfs_sb_info *sbi, char *file_name,
5428c2ecf20Sopenharmony_ci		struct dir_context *ctx)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	unsigned long pos = (unsigned long)(ctx->pos);
5458c2ecf20Sopenharmony_ci	unsigned long group_id = (pos << (1 + DEV_ID_BIT_NUM)) >>
5468c2ecf20Sopenharmony_ci				 (POS_BIT_NUM - GROUP_ID_BIT_NUM);
5478c2ecf20Sopenharmony_ci	unsigned long offset = pos & OFFSET_BIT_MASK;
5488c2ecf20Sopenharmony_ci	struct hmdfs_dentry_group *dentry_group = NULL;
5498c2ecf20Sopenharmony_ci	struct file *handler = NULL;
5508c2ecf20Sopenharmony_ci	int group_num = 0;
5518c2ecf20Sopenharmony_ci	int iterate_result = 0;
5528c2ecf20Sopenharmony_ci	int i, j;
5538c2ecf20Sopenharmony_ci	const struct cred *saved_cred;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	saved_cred = hmdfs_override_fsids(false);
5568c2ecf20Sopenharmony_ci	if (!saved_cred) {
5578c2ecf20Sopenharmony_ci		hmdfs_err("prepare cred failed!");
5588c2ecf20Sopenharmony_ci		return -ENOMEM;
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (!file_name)
5638c2ecf20Sopenharmony_ci		return -EINVAL;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL);
5668c2ecf20Sopenharmony_ci	if (!dentry_group)
5678c2ecf20Sopenharmony_ci		return -ENOMEM;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	handler = hmdfs_get_or_create_dents(sbi, file_name);
5708c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(handler)) {
5718c2ecf20Sopenharmony_ci		kfree(dentry_group);
5728c2ecf20Sopenharmony_ci		return -ENOENT;
5738c2ecf20Sopenharmony_ci	}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	group_num = get_dentry_group_cnt(file_inode(handler));
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	for (i = group_id; i < group_num; i++) {
5788c2ecf20Sopenharmony_ci		hmdfs_metainfo_read(sbi, handler, dentry_group,
5798c2ecf20Sopenharmony_ci				    sizeof(struct hmdfs_dentry_group), i);
5808c2ecf20Sopenharmony_ci		for (j = offset; j < DENTRY_PER_GROUP; j++) {
5818c2ecf20Sopenharmony_ci			int len;
5828c2ecf20Sopenharmony_ci			int file_type = 0;
5838c2ecf20Sopenharmony_ci			bool is_continue;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci			len = le16_to_cpu(dentry_group->nsl[j].namelen);
5868c2ecf20Sopenharmony_ci			if (!test_bit_le(j, dentry_group->bitmap) || len == 0)
5878c2ecf20Sopenharmony_ci				continue;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci			if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode)))
5908c2ecf20Sopenharmony_ci				file_type = DT_DIR;
5918c2ecf20Sopenharmony_ci			else if (S_ISREG(le16_to_cpu(
5928c2ecf20Sopenharmony_ci					 dentry_group->nsl[j].i_mode)))
5938c2ecf20Sopenharmony_ci				file_type = DT_REG;
5948c2ecf20Sopenharmony_ci			else if (S_ISLNK(le16_to_cpu(
5958c2ecf20Sopenharmony_ci					 dentry_group->nsl[j].i_mode)))
5968c2ecf20Sopenharmony_ci				file_type = DT_LNK;
5978c2ecf20Sopenharmony_ci			else
5988c2ecf20Sopenharmony_ci				continue;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci			pos = hmdfs_set_pos(0, i, j);
6018c2ecf20Sopenharmony_ci			is_continue = dir_emit(
6028c2ecf20Sopenharmony_ci				ctx, dentry_group->filename[j], len,
6038c2ecf20Sopenharmony_ci				le64_to_cpu(dentry_group->nsl[j].i_ino),
6048c2ecf20Sopenharmony_ci				file_type);
6058c2ecf20Sopenharmony_ci			if (!is_continue) {
6068c2ecf20Sopenharmony_ci				ctx->pos = pos;
6078c2ecf20Sopenharmony_ci				iterate_result = 1;
6088c2ecf20Sopenharmony_ci				goto done;
6098c2ecf20Sopenharmony_ci			}
6108c2ecf20Sopenharmony_ci		}
6118c2ecf20Sopenharmony_ci		offset = 0;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cidone:
6158c2ecf20Sopenharmony_ci	hmdfs_revert_fsids(saved_cred);
6168c2ecf20Sopenharmony_ci	kfree(dentry_group);
6178c2ecf20Sopenharmony_ci	fput(handler);
6188c2ecf20Sopenharmony_ci	return iterate_result;
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ciunsigned int get_max_depth(struct file *filp)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	size_t isize;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	isize = get_dentry_group_cnt(file_inode(filp)) / BUCKET_BLOCKS;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	return get_count_order(isize + 1);
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_cistruct hmdfs_dentry_group *find_dentry_page(struct hmdfs_sb_info *sbi,
6318c2ecf20Sopenharmony_ci					    pgoff_t index, struct file *filp)
6328c2ecf20Sopenharmony_ci{
6338c2ecf20Sopenharmony_ci	int size;
6348c2ecf20Sopenharmony_ci	struct hmdfs_dentry_group *dentry_blk = NULL;
6358c2ecf20Sopenharmony_ci	loff_t pos = get_dentry_group_pos(index);
6368c2ecf20Sopenharmony_ci	int err;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	dentry_blk = kmalloc(sizeof(*dentry_blk), GFP_KERNEL);
6398c2ecf20Sopenharmony_ci	if (!dentry_blk)
6408c2ecf20Sopenharmony_ci		return NULL;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	err = hmdfs_wlock_file(filp, pos, DENTRYGROUP_SIZE);
6438c2ecf20Sopenharmony_ci	if (err) {
6448c2ecf20Sopenharmony_ci		hmdfs_err("lock file pos %lld failed", pos);
6458c2ecf20Sopenharmony_ci		kfree(dentry_blk);
6468c2ecf20Sopenharmony_ci		return NULL;
6478c2ecf20Sopenharmony_ci	}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	size = cache_file_read(sbi, filp, dentry_blk, (size_t)DENTRYGROUP_SIZE,
6508c2ecf20Sopenharmony_ci			       &pos);
6518c2ecf20Sopenharmony_ci	if (size != DENTRYGROUP_SIZE) {
6528c2ecf20Sopenharmony_ci		hmdfs_unlock_file(filp, pos, DENTRYGROUP_SIZE);
6538c2ecf20Sopenharmony_ci		kfree(dentry_blk);
6548c2ecf20Sopenharmony_ci		dentry_blk = NULL;
6558c2ecf20Sopenharmony_ci	}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	return dentry_blk;
6588c2ecf20Sopenharmony_ci}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_cistatic ssize_t write_dentry_page(struct file *filp, const void *buffer,
6618c2ecf20Sopenharmony_ci				 int buffersize, loff_t position)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	ssize_t size;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	size = kernel_write(filp, buffer, (size_t)buffersize, &position);
6668c2ecf20Sopenharmony_ci	if (size != buffersize)
6678c2ecf20Sopenharmony_ci		hmdfs_err("write failed, ret = %zd", size);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	return size;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic struct hmdfs_dentry *find_in_block(struct hmdfs_dentry_group *dentry_blk,
6738c2ecf20Sopenharmony_ci					  __u32 namehash,
6748c2ecf20Sopenharmony_ci					  const struct qstr *qstr,
6758c2ecf20Sopenharmony_ci					  struct hmdfs_dentry **insense_de,
6768c2ecf20Sopenharmony_ci					  bool case_sense)
6778c2ecf20Sopenharmony_ci{
6788c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de;
6798c2ecf20Sopenharmony_ci	unsigned long bit_pos = 0;
6808c2ecf20Sopenharmony_ci	int max_len = 0;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	while (bit_pos < DENTRY_PER_GROUP) {
6838c2ecf20Sopenharmony_ci		if (!test_bit_le(bit_pos, dentry_blk->bitmap)) {
6848c2ecf20Sopenharmony_ci			bit_pos++;
6858c2ecf20Sopenharmony_ci			max_len++;
6868c2ecf20Sopenharmony_ci			continue;
6878c2ecf20Sopenharmony_ci		}
6888c2ecf20Sopenharmony_ci		de = &dentry_blk->nsl[bit_pos];
6898c2ecf20Sopenharmony_ci		if (unlikely(!de->namelen)) {
6908c2ecf20Sopenharmony_ci			bit_pos++;
6918c2ecf20Sopenharmony_ci			continue;
6928c2ecf20Sopenharmony_ci		}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci		if (le32_to_cpu(de->hash) == namehash &&
6958c2ecf20Sopenharmony_ci		    le16_to_cpu(de->namelen) == qstr->len &&
6968c2ecf20Sopenharmony_ci		    !memcmp(qstr->name, dentry_blk->filename[bit_pos],
6978c2ecf20Sopenharmony_ci			    le16_to_cpu(de->namelen)))
6988c2ecf20Sopenharmony_ci			goto found;
6998c2ecf20Sopenharmony_ci		if (!(*insense_de) && !case_sense &&
7008c2ecf20Sopenharmony_ci		    le32_to_cpu(de->hash) == namehash &&
7018c2ecf20Sopenharmony_ci		    le16_to_cpu(de->namelen) == qstr->len &&
7028c2ecf20Sopenharmony_ci		    str_n_case_eq(qstr->name, dentry_blk->filename[bit_pos],
7038c2ecf20Sopenharmony_ci				  le16_to_cpu(de->namelen)))
7048c2ecf20Sopenharmony_ci			*insense_de = de;
7058c2ecf20Sopenharmony_ci		max_len = 0;
7068c2ecf20Sopenharmony_ci		bit_pos += get_dentry_slots(le16_to_cpu(de->namelen));
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci	de = NULL;
7098c2ecf20Sopenharmony_cifound:
7108c2ecf20Sopenharmony_ci	return de;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic struct hmdfs_dentry *hmdfs_in_level(struct dentry *child_dentry,
7148c2ecf20Sopenharmony_ci					   unsigned int level,
7158c2ecf20Sopenharmony_ci					   struct hmdfs_dcache_lookup_ctx *ctx)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	unsigned long nbucket;
7188c2ecf20Sopenharmony_ci	unsigned long bidx, end_block;
7198c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de = NULL;
7208c2ecf20Sopenharmony_ci	struct hmdfs_dentry *tmp_insense_de = NULL;
7218c2ecf20Sopenharmony_ci	struct hmdfs_dentry_group *dentry_blk;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	nbucket = get_bucket_by_level(level);
7248c2ecf20Sopenharmony_ci	if (!nbucket)
7258c2ecf20Sopenharmony_ci		return de;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	bidx = get_bucketaddr(level, ctx->hash % nbucket) * BUCKET_BLOCKS;
7288c2ecf20Sopenharmony_ci	end_block = bidx + BUCKET_BLOCKS;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	for (; bidx < end_block; bidx++) {
7318c2ecf20Sopenharmony_ci		dentry_blk = find_dentry_page(ctx->sbi, bidx, ctx->filp);
7328c2ecf20Sopenharmony_ci		if (!dentry_blk)
7338c2ecf20Sopenharmony_ci			break;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci		de = find_in_block(dentry_blk, ctx->hash, ctx->name,
7368c2ecf20Sopenharmony_ci				   &tmp_insense_de, ctx->sbi->s_case_sensitive);
7378c2ecf20Sopenharmony_ci		if (!de && !(ctx->insense_de) && tmp_insense_de) {
7388c2ecf20Sopenharmony_ci			ctx->insense_de = tmp_insense_de;
7398c2ecf20Sopenharmony_ci			ctx->insense_page = dentry_blk;
7408c2ecf20Sopenharmony_ci			ctx->insense_bidx = bidx;
7418c2ecf20Sopenharmony_ci		} else if (!de) {
7428c2ecf20Sopenharmony_ci			hmdfs_unlock_file(ctx->filp, get_dentry_group_pos(bidx),
7438c2ecf20Sopenharmony_ci					  DENTRYGROUP_SIZE);
7448c2ecf20Sopenharmony_ci			kfree(dentry_blk);
7458c2ecf20Sopenharmony_ci		} else {
7468c2ecf20Sopenharmony_ci			ctx->page = dentry_blk;
7478c2ecf20Sopenharmony_ci			break;
7488c2ecf20Sopenharmony_ci		}
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci	ctx->bidx = bidx;
7518c2ecf20Sopenharmony_ci	return de;
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistruct hmdfs_dentry *hmdfs_find_dentry(struct dentry *child_dentry,
7558c2ecf20Sopenharmony_ci				       struct hmdfs_dcache_lookup_ctx *ctx)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de = NULL;
7588c2ecf20Sopenharmony_ci	unsigned int max_depth;
7598c2ecf20Sopenharmony_ci	unsigned int level;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	if (!ctx->filp)
7628c2ecf20Sopenharmony_ci		return NULL;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	ctx->hash = hmdfs_dentry_hash(ctx->name, ctx->sbi->s_case_sensitive);
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	max_depth = get_max_depth(ctx->filp);
7678c2ecf20Sopenharmony_ci	for (level = 0; level < max_depth; level++) {
7688c2ecf20Sopenharmony_ci		de = hmdfs_in_level(child_dentry, level, ctx);
7698c2ecf20Sopenharmony_ci		if (de) {
7708c2ecf20Sopenharmony_ci			if (ctx->insense_page) {
7718c2ecf20Sopenharmony_ci				hmdfs_unlock_file(ctx->filp,
7728c2ecf20Sopenharmony_ci					get_dentry_group_pos(ctx->insense_bidx),
7738c2ecf20Sopenharmony_ci					DENTRYGROUP_SIZE);
7748c2ecf20Sopenharmony_ci				kfree(ctx->insense_page);
7758c2ecf20Sopenharmony_ci				ctx->insense_page = NULL;
7768c2ecf20Sopenharmony_ci			}
7778c2ecf20Sopenharmony_ci			return de;
7788c2ecf20Sopenharmony_ci		}
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci	if (ctx->insense_de) {
7818c2ecf20Sopenharmony_ci		ctx->bidx = ctx->insense_bidx;
7828c2ecf20Sopenharmony_ci		ctx->page = ctx->insense_page;
7838c2ecf20Sopenharmony_ci		ctx->insense_bidx = 0;
7848c2ecf20Sopenharmony_ci		ctx->insense_page = NULL;
7858c2ecf20Sopenharmony_ci	}
7868c2ecf20Sopenharmony_ci	return ctx->insense_de;
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_civoid update_dentry(struct hmdfs_dentry_group *d, struct dentry *child_dentry,
7908c2ecf20Sopenharmony_ci		   		   struct inode *inode, struct super_block *hmdfs_sb,
7918c2ecf20Sopenharmony_ci		  		   __u32 name_hash, unsigned int bit_pos)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de;
7948c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *gdi;
7958c2ecf20Sopenharmony_ci	const struct qstr name = child_dentry->d_name;
7968c2ecf20Sopenharmony_ci	int slots = get_dentry_slots(name.len);
7978c2ecf20Sopenharmony_ci	int i;
7988c2ecf20Sopenharmony_ci	unsigned long ino;
7998c2ecf20Sopenharmony_ci	__u32 igen;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	gdi = hmdfs_sb == child_dentry->d_sb ? hmdfs_d(child_dentry) : NULL;
8028c2ecf20Sopenharmony_ci	if (!gdi && S_ISLNK(d_inode(child_dentry)->i_mode)) {
8038c2ecf20Sopenharmony_ci		ino = d_inode(child_dentry)->i_ino;
8048c2ecf20Sopenharmony_ci		igen = d_inode(child_dentry)->i_generation;
8058c2ecf20Sopenharmony_ci	} else {
8068c2ecf20Sopenharmony_ci		ino = inode->i_ino;
8078c2ecf20Sopenharmony_ci		igen = inode->i_generation;
8088c2ecf20Sopenharmony_ci	}
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	de = &d->nsl[bit_pos];
8118c2ecf20Sopenharmony_ci	de->hash = cpu_to_le32(name_hash);
8128c2ecf20Sopenharmony_ci	de->namelen = cpu_to_le16(name.len);
8138c2ecf20Sopenharmony_ci	memcpy(d->filename[bit_pos], name.name, name.len);
8148c2ecf20Sopenharmony_ci	de->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
8158c2ecf20Sopenharmony_ci	de->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
8168c2ecf20Sopenharmony_ci	de->i_size = cpu_to_le64(inode->i_size);
8178c2ecf20Sopenharmony_ci	de->i_ino = cpu_to_le64(generate_u64_ino(ino, igen));
8188c2ecf20Sopenharmony_ci	de->i_flag = 0;
8198c2ecf20Sopenharmony_ci	if (gdi && hm_islnk(gdi->file_type))
8208c2ecf20Sopenharmony_ci		de->i_mode = cpu_to_le16(S_IFLNK);
8218c2ecf20Sopenharmony_ci	else if (!gdi && S_ISLNK(d_inode(child_dentry)->i_mode))
8228c2ecf20Sopenharmony_ci		de->i_mode = d_inode(child_dentry)->i_mode;
8238c2ecf20Sopenharmony_ci	else
8248c2ecf20Sopenharmony_ci		de->i_mode = cpu_to_le16(inode->i_mode);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	for (i = 0; i < slots; i++) {
8278c2ecf20Sopenharmony_ci		__set_bit_le(bit_pos + i, d->bitmap);
8288c2ecf20Sopenharmony_ci		/* avoid wrong garbage data for readdir */
8298c2ecf20Sopenharmony_ci		if (i)
8308c2ecf20Sopenharmony_ci			(de + i)->namelen = 0;
8318c2ecf20Sopenharmony_ci	}
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ciint room_for_filename(const void *bitmap, int slots, int max_slots)
8358c2ecf20Sopenharmony_ci{
8368c2ecf20Sopenharmony_ci	int bit_start = 0;
8378c2ecf20Sopenharmony_ci	int zero_start, zero_end;
8388c2ecf20Sopenharmony_cinext:
8398c2ecf20Sopenharmony_ci	zero_start = find_next_zero_bit_le(bitmap, max_slots, bit_start);
8408c2ecf20Sopenharmony_ci	if (zero_start >= max_slots)
8418c2ecf20Sopenharmony_ci		return max_slots;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	zero_end = find_next_bit_le(bitmap, max_slots, zero_start);
8448c2ecf20Sopenharmony_ci	if (zero_end - zero_start >= slots)
8458c2ecf20Sopenharmony_ci		return zero_start;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	bit_start = zero_end + 1;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (zero_end + 1 >= max_slots)
8508c2ecf20Sopenharmony_ci		return max_slots;
8518c2ecf20Sopenharmony_ci	goto next;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_civoid create_in_cache_file(uint64_t dev_id, struct dentry *dentry)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	item = hmdfs_find_cache_item(dev_id, dentry->d_parent);
8598c2ecf20Sopenharmony_ci	if (item) {
8608c2ecf20Sopenharmony_ci		if (d_inode(dentry))
8618c2ecf20Sopenharmony_ci			create_dentry(dentry, d_inode(dentry), item->filp,
8628c2ecf20Sopenharmony_ci				      hmdfs_sb(dentry->d_sb));
8638c2ecf20Sopenharmony_ci		else
8648c2ecf20Sopenharmony_ci			hmdfs_err("inode is null!");
8658c2ecf20Sopenharmony_ci		kref_put(&item->ref, release_cache_item);
8668c2ecf20Sopenharmony_ci	} else {
8678c2ecf20Sopenharmony_ci		hmdfs_info("find cache item failed, device_id:%llu", dev_id);
8688c2ecf20Sopenharmony_ci	}
8698c2ecf20Sopenharmony_ci}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ciint create_dentry(struct dentry *child_dentry, struct inode *inode,
8728c2ecf20Sopenharmony_ci		  struct file *file, struct hmdfs_sb_info *sbi)
8738c2ecf20Sopenharmony_ci{
8748c2ecf20Sopenharmony_ci	unsigned int bit_pos, level;
8758c2ecf20Sopenharmony_ci	unsigned long bidx, end_block;
8768c2ecf20Sopenharmony_ci	const struct qstr qstr = child_dentry->d_name;
8778c2ecf20Sopenharmony_ci	__u32 namehash;
8788c2ecf20Sopenharmony_ci	loff_t pos;
8798c2ecf20Sopenharmony_ci	ssize_t size;
8808c2ecf20Sopenharmony_ci	int ret = 0;
8818c2ecf20Sopenharmony_ci	struct hmdfs_dentry_group *dentry_blk = NULL;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	level = 0;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	namehash = hmdfs_dentry_hash(&qstr, sbi->s_case_sensitive);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	dentry_blk = kmalloc(sizeof(*dentry_blk), GFP_KERNEL);
8888c2ecf20Sopenharmony_ci	if (!dentry_blk) {
8898c2ecf20Sopenharmony_ci		ret = -ENOMEM;
8908c2ecf20Sopenharmony_ci		goto out_err;
8918c2ecf20Sopenharmony_ci	}
8928c2ecf20Sopenharmony_cifind:
8938c2ecf20Sopenharmony_ci	if (level == MAX_BUCKET_LEVEL) {
8948c2ecf20Sopenharmony_ci		ret = -ENOSPC;
8958c2ecf20Sopenharmony_ci		goto out;
8968c2ecf20Sopenharmony_ci	}
8978c2ecf20Sopenharmony_ci	bidx = BUCKET_BLOCKS *
8988c2ecf20Sopenharmony_ci	       get_bucketaddr(level, namehash % get_bucket_by_level(level));
8998c2ecf20Sopenharmony_ci	end_block = bidx + BUCKET_BLOCKS;
9008c2ecf20Sopenharmony_ci	if (end_block > get_dentry_group_cnt(file_inode(file))) {
9018c2ecf20Sopenharmony_ci		if (cache_file_truncate(sbi, &(file->f_path),
9028c2ecf20Sopenharmony_ci					get_dcache_file_size(level))) {
9038c2ecf20Sopenharmony_ci			ret = -ENOSPC;
9048c2ecf20Sopenharmony_ci			goto out;
9058c2ecf20Sopenharmony_ci		}
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	for (; bidx < end_block; bidx++) {
9098c2ecf20Sopenharmony_ci		int size;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		pos = get_dentry_group_pos(bidx);
9128c2ecf20Sopenharmony_ci		ret = hmdfs_wlock_file(file, pos, DENTRYGROUP_SIZE);
9138c2ecf20Sopenharmony_ci		if (ret)
9148c2ecf20Sopenharmony_ci			goto out;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci		size = cache_file_read(sbi, file, dentry_blk,
9178c2ecf20Sopenharmony_ci				       (size_t)DENTRYGROUP_SIZE, &pos);
9188c2ecf20Sopenharmony_ci		if (size != DENTRYGROUP_SIZE) {
9198c2ecf20Sopenharmony_ci			ret = -ENOSPC;
9208c2ecf20Sopenharmony_ci			hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE);
9218c2ecf20Sopenharmony_ci			goto out;
9228c2ecf20Sopenharmony_ci		}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci		bit_pos = room_for_filename(&dentry_blk->bitmap,
9258c2ecf20Sopenharmony_ci					    get_dentry_slots(qstr.len),
9268c2ecf20Sopenharmony_ci					    DENTRY_PER_GROUP);
9278c2ecf20Sopenharmony_ci		if (bit_pos < DENTRY_PER_GROUP)
9288c2ecf20Sopenharmony_ci			goto add;
9298c2ecf20Sopenharmony_ci		hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE);
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci	++level;
9328c2ecf20Sopenharmony_ci	goto find;
9338c2ecf20Sopenharmony_ciadd:
9348c2ecf20Sopenharmony_ci	pos = get_dentry_group_pos(bidx);
9358c2ecf20Sopenharmony_ci	update_dentry(dentry_blk, child_dentry, inode, sbi->sb, namehash,
9368c2ecf20Sopenharmony_ci				  bit_pos);
9378c2ecf20Sopenharmony_ci	size = cache_file_write(sbi, file, dentry_blk,
9388c2ecf20Sopenharmony_ci				sizeof(struct hmdfs_dentry_group), &pos);
9398c2ecf20Sopenharmony_ci	if (size != sizeof(struct hmdfs_dentry_group))
9408c2ecf20Sopenharmony_ci		hmdfs_err("cache file write failed!, ret = %zd", size);
9418c2ecf20Sopenharmony_ci	hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE);
9428c2ecf20Sopenharmony_ciout:
9438c2ecf20Sopenharmony_ci	kfree(dentry_blk);
9448c2ecf20Sopenharmony_ciout_err:
9458c2ecf20Sopenharmony_ci	return ret;
9468c2ecf20Sopenharmony_ci}
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_civoid hmdfs_init_dcache_lookup_ctx(struct hmdfs_dcache_lookup_ctx *ctx,
9498c2ecf20Sopenharmony_ci				  struct hmdfs_sb_info *sbi,
9508c2ecf20Sopenharmony_ci				  const struct qstr *qstr, struct file *filp)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	ctx->sbi = sbi;
9538c2ecf20Sopenharmony_ci	ctx->name = qstr;
9548c2ecf20Sopenharmony_ci	ctx->filp = filp;
9558c2ecf20Sopenharmony_ci	ctx->bidx = 0;
9568c2ecf20Sopenharmony_ci	ctx->page = NULL;
9578c2ecf20Sopenharmony_ci	ctx->insense_de = NULL;
9588c2ecf20Sopenharmony_ci	ctx->insense_bidx = 0;
9598c2ecf20Sopenharmony_ci	ctx->insense_page = NULL;
9608c2ecf20Sopenharmony_ci}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ciint update_inode_to_dentry(struct dentry *child_dentry, struct inode *inode)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = d_inode(child_dentry)->i_sb->s_fs_info;
9658c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de = NULL;
9668c2ecf20Sopenharmony_ci	loff_t ipos;
9678c2ecf20Sopenharmony_ci	struct dentry *parent_dentry;
9688c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
9698c2ecf20Sopenharmony_ci	char *relative_path = NULL;
9708c2ecf20Sopenharmony_ci	struct hmdfs_dcache_lookup_ctx ctx;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	parent_dentry = child_dentry->d_parent;
9738c2ecf20Sopenharmony_ci	if (hmdfs_d(parent_dentry)->dentry_type == HMDFS_LAYER_FIRST_DEVICE)
9748c2ecf20Sopenharmony_ci		return 0;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	relative_path = hmdfs_get_dentry_relative_path(parent_dentry);
9778c2ecf20Sopenharmony_ci	if (!relative_path)
9788c2ecf20Sopenharmony_ci		return -ENOMEM;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	cfn = find_cfn(sbi, HMDFS_SERVER_CID, relative_path, true);
9818c2ecf20Sopenharmony_ci	if (!cfn)
9828c2ecf20Sopenharmony_ci		goto out;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	hmdfs_init_dcache_lookup_ctx(&ctx, sbi, &child_dentry->d_name,
9858c2ecf20Sopenharmony_ci				     cfn->filp);
9868c2ecf20Sopenharmony_ci	de = hmdfs_find_dentry(child_dentry, &ctx);
9878c2ecf20Sopenharmony_ci	if (!de)
9888c2ecf20Sopenharmony_ci		goto out_cfn;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	de->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
9918c2ecf20Sopenharmony_ci	de->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
9928c2ecf20Sopenharmony_ci	de->i_size = cpu_to_le64(inode->i_size);
9938c2ecf20Sopenharmony_ci	de->i_ino = cpu_to_le64(
9948c2ecf20Sopenharmony_ci		generate_u64_ino(inode->i_ino, inode->i_generation));
9958c2ecf20Sopenharmony_ci	de->i_flag = 0;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	ipos = get_dentry_group_pos(ctx.bidx);
9988c2ecf20Sopenharmony_ci	write_dentry_page(cfn->filp, ctx.page,
9998c2ecf20Sopenharmony_ci			  sizeof(struct hmdfs_dentry_group), ipos);
10008c2ecf20Sopenharmony_ci	hmdfs_unlock_file(cfn->filp, ipos, DENTRYGROUP_SIZE);
10018c2ecf20Sopenharmony_ci	kfree(ctx.page);
10028c2ecf20Sopenharmony_ciout_cfn:
10038c2ecf20Sopenharmony_ci	release_cfn(cfn);
10048c2ecf20Sopenharmony_ciout:
10058c2ecf20Sopenharmony_ci	kfree(relative_path);
10068c2ecf20Sopenharmony_ci	return 0;
10078c2ecf20Sopenharmony_ci}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_civoid hmdfs_delete_dentry(struct dentry *d, struct file *filp)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	struct hmdfs_dentry *de = NULL;
10128c2ecf20Sopenharmony_ci	unsigned int bit_pos;
10138c2ecf20Sopenharmony_ci	int slots, i;
10148c2ecf20Sopenharmony_ci	loff_t ipos;
10158c2ecf20Sopenharmony_ci	ssize_t size;
10168c2ecf20Sopenharmony_ci	struct hmdfs_dcache_lookup_ctx ctx;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	hmdfs_init_dcache_lookup_ctx(&ctx, hmdfs_sb(d->d_sb), &d->d_name, filp);
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	de = hmdfs_find_dentry(d, &ctx);
10218c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(de)) {
10228c2ecf20Sopenharmony_ci		hmdfs_info("find dentry failed!, err=%ld", PTR_ERR(de));
10238c2ecf20Sopenharmony_ci		return;
10248c2ecf20Sopenharmony_ci	}
10258c2ecf20Sopenharmony_ci	slots = get_dentry_slots(le16_to_cpu(de->namelen));
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	bit_pos = de - ctx.page->nsl;
10288c2ecf20Sopenharmony_ci	for (i = 0; i < slots; i++)
10298c2ecf20Sopenharmony_ci		__clear_bit_le(bit_pos + i, &ctx.page->bitmap);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	ipos = get_dentry_group_pos(ctx.bidx);
10328c2ecf20Sopenharmony_ci	size = cache_file_write(hmdfs_sb(d->d_sb), filp, ctx.page,
10338c2ecf20Sopenharmony_ci				sizeof(struct hmdfs_dentry_group), &ipos);
10348c2ecf20Sopenharmony_ci	if (size != sizeof(struct hmdfs_dentry_group))
10358c2ecf20Sopenharmony_ci		hmdfs_err("cache file write failed!, ret = %zd", size);
10368c2ecf20Sopenharmony_ci	hmdfs_unlock_file(filp, ipos, DENTRYGROUP_SIZE);
10378c2ecf20Sopenharmony_ci	kfree(ctx.page);
10388c2ecf20Sopenharmony_ci}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_cistatic int hmdfs_get_cache_path(struct hmdfs_sb_info *sbi, struct path *dir)
10418c2ecf20Sopenharmony_ci{
10428c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *di = hmdfs_d(sbi->sb->s_root);
10438c2ecf20Sopenharmony_ci	int err;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	if (!sbi->s_dentry_cache) {
10468c2ecf20Sopenharmony_ci		*dir = di->lower_path;
10478c2ecf20Sopenharmony_ci		return 0;
10488c2ecf20Sopenharmony_ci	}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	err = kern_path(sbi->cache_dir, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, dir);
10518c2ecf20Sopenharmony_ci	if (err)
10528c2ecf20Sopenharmony_ci		hmdfs_err("open failed, errno = %d", err);
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	return err;
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_cistatic void hmdfs_put_cache_path(struct hmdfs_sb_info *sbi, struct path *dir)
10588c2ecf20Sopenharmony_ci{
10598c2ecf20Sopenharmony_ci	if (!sbi->s_dentry_cache)
10608c2ecf20Sopenharmony_ci		return;
10618c2ecf20Sopenharmony_ci	path_put(dir);
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_cistruct file *create_local_dentry_file_cache(struct hmdfs_sb_info *sbi)
10658c2ecf20Sopenharmony_ci{
10668c2ecf20Sopenharmony_ci	struct file *filp = NULL;
10678c2ecf20Sopenharmony_ci	const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred);
10688c2ecf20Sopenharmony_ci	struct path cache_dir;
10698c2ecf20Sopenharmony_ci	int err;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	err = hmdfs_get_cache_path(sbi, &cache_dir);
10728c2ecf20Sopenharmony_ci	if (err) {
10738c2ecf20Sopenharmony_ci		filp = ERR_PTR(err);
10748c2ecf20Sopenharmony_ci		goto out;
10758c2ecf20Sopenharmony_ci	}
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	filp = file_open_root(&cache_dir, ".",
10788c2ecf20Sopenharmony_ci			      O_RDWR | O_LARGEFILE | O_TMPFILE,
10798c2ecf20Sopenharmony_ci			      DENTRY_FILE_PERM);
10808c2ecf20Sopenharmony_ci	if (IS_ERR(filp))
10818c2ecf20Sopenharmony_ci		hmdfs_err("dentryfile open failed and exit err=%ld",
10828c2ecf20Sopenharmony_ci			  PTR_ERR(filp));
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	hmdfs_put_cache_path(sbi, &cache_dir);
10858c2ecf20Sopenharmony_ciout:
10868c2ecf20Sopenharmony_ci	hmdfs_revert_creds(old_cred);
10878c2ecf20Sopenharmony_ci	return filp;
10888c2ecf20Sopenharmony_ci}
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_cistatic int hmdfs_linkat(struct path *old_path, const char *newname)
10918c2ecf20Sopenharmony_ci{
10928c2ecf20Sopenharmony_ci	struct dentry *new_dentry = NULL;
10938c2ecf20Sopenharmony_ci	struct path new_path;
10948c2ecf20Sopenharmony_ci	int error;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
10978c2ecf20Sopenharmony_ci	if (IS_ERR(new_dentry)) {
10988c2ecf20Sopenharmony_ci		hmdfs_err("create kernel path failed, error: %ld",
10998c2ecf20Sopenharmony_ci			  PTR_ERR(new_dentry));
11008c2ecf20Sopenharmony_ci		return PTR_ERR(new_dentry);
11018c2ecf20Sopenharmony_ci	}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	error = -EXDEV;
11048c2ecf20Sopenharmony_ci	if (old_path->mnt != new_path.mnt)
11058c2ecf20Sopenharmony_ci		goto out_dput;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	error = vfs_link(old_path->dentry, new_path.dentry->d_inode, new_dentry,
11088c2ecf20Sopenharmony_ci			 NULL);
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ciout_dput:
11118c2ecf20Sopenharmony_ci	done_path_create(&new_path, new_dentry);
11128c2ecf20Sopenharmony_ci	return error;
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic int cache_file_mkdir(const char *name, umode_t mode)
11168c2ecf20Sopenharmony_ci{
11178c2ecf20Sopenharmony_ci	struct dentry *dentry;
11188c2ecf20Sopenharmony_ci	struct path path;
11198c2ecf20Sopenharmony_ci	int err;
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
11228c2ecf20Sopenharmony_ci	if (IS_ERR(dentry))
11238c2ecf20Sopenharmony_ci		return PTR_ERR(dentry);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	err = vfs_mkdir(d_inode(path.dentry), dentry, mode);
11268c2ecf20Sopenharmony_ci	if (err && err != -EEXIST)
11278c2ecf20Sopenharmony_ci		hmdfs_err("vfs_mkdir failed, err = %d", err);
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	done_path_create(&path, dentry);
11308c2ecf20Sopenharmony_ci	return err;
11318c2ecf20Sopenharmony_ci}
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_cistatic int cache_file_create_path(const char *fullpath)
11348c2ecf20Sopenharmony_ci{
11358c2ecf20Sopenharmony_ci	char *path;
11368c2ecf20Sopenharmony_ci	char *s;
11378c2ecf20Sopenharmony_ci	int err = 0;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	path = kstrdup(fullpath, GFP_KERNEL);
11408c2ecf20Sopenharmony_ci	if (!path)
11418c2ecf20Sopenharmony_ci		return -ENOMEM;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	s = path + 1;
11448c2ecf20Sopenharmony_ci	while (true) {
11458c2ecf20Sopenharmony_ci		s = strchr(s, '/');
11468c2ecf20Sopenharmony_ci		if (!s)
11478c2ecf20Sopenharmony_ci			break;
11488c2ecf20Sopenharmony_ci		s[0] = '\0';
11498c2ecf20Sopenharmony_ci		err = cache_file_mkdir(path, 0755);
11508c2ecf20Sopenharmony_ci		if (err && err != -EEXIST)
11518c2ecf20Sopenharmony_ci			break;
11528c2ecf20Sopenharmony_ci		s[0] = '/';
11538c2ecf20Sopenharmony_ci		s++;
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci	kfree(path);
11568c2ecf20Sopenharmony_ci	return err;
11578c2ecf20Sopenharmony_ci}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_cistatic void hmdfs_cache_path_create(char *s, const char *dir, bool server)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	if (server)
11628c2ecf20Sopenharmony_ci		snprintf(s, PATH_MAX, "%s/dentry_cache/server/", dir);
11638c2ecf20Sopenharmony_ci	else
11648c2ecf20Sopenharmony_ci		snprintf(s, PATH_MAX, "%s/dentry_cache/client/", dir);
11658c2ecf20Sopenharmony_ci}
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_cistatic void concat_cachefile_name(char *s, uint64_t hash, const char *id,
11688c2ecf20Sopenharmony_ci				    bool server)
11698c2ecf20Sopenharmony_ci{
11708c2ecf20Sopenharmony_ci	int offset = strlen(s);
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	if (server)
11738c2ecf20Sopenharmony_ci		snprintf(s + offset, PATH_MAX - offset, "%016llx", hash);
11748c2ecf20Sopenharmony_ci	else
11758c2ecf20Sopenharmony_ci		snprintf(s + offset, PATH_MAX - offset, "%s_%016llx", id, hash);
11768c2ecf20Sopenharmony_ci}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ciint cache_file_name_generate(char *fullname, struct hmdfs_peer *con,
11798c2ecf20Sopenharmony_ci			     const char *relative_path, bool server)
11808c2ecf20Sopenharmony_ci{
11818c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = con->sbi;
11828c2ecf20Sopenharmony_ci	uint64_t  hash;
11838c2ecf20Sopenharmony_ci	char cid[HMDFS_CFN_CID_SIZE];
11848c2ecf20Sopenharmony_ci	int err;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	hmdfs_cache_path_create(fullname, sbi->cache_dir, server);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	err = cache_file_create_path(fullname);
11898c2ecf20Sopenharmony_ci	if (err && err != -EEXIST) {
11908c2ecf20Sopenharmony_ci		hmdfs_err("making dir failed %d", err);
11918c2ecf20Sopenharmony_ci		return err;
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	strncpy(cid, con->cid, HMDFS_CFN_CID_SIZE - 1);
11958c2ecf20Sopenharmony_ci	cid[HMDFS_CFN_CID_SIZE - 1] = '\0';
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	hash = path_hash(relative_path, strlen(relative_path),
11988c2ecf20Sopenharmony_ci			 sbi->s_case_sensitive);
11998c2ecf20Sopenharmony_ci	concat_cachefile_name(fullname, hash, cid, server);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	return 0;
12028c2ecf20Sopenharmony_ci}
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_cistatic void free_cfn(struct cache_file_node *cfn)
12058c2ecf20Sopenharmony_ci{
12068c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(cfn->filp))
12078c2ecf20Sopenharmony_ci		filp_close(cfn->filp, NULL);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	kfree(cfn->relative_path);
12108c2ecf20Sopenharmony_ci	kfree(cfn);
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic bool path_cmp(const char *path1, const char *path2, bool case_sensitive)
12148c2ecf20Sopenharmony_ci{
12158c2ecf20Sopenharmony_ci	int ret;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	if (case_sensitive)
12188c2ecf20Sopenharmony_ci		ret = strcmp(path1, path2);
12198c2ecf20Sopenharmony_ci	else
12208c2ecf20Sopenharmony_ci		ret = strcasecmp(path1, path2);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	return !ret;
12238c2ecf20Sopenharmony_ci}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_cistatic bool dentry_file_match(struct cache_file_node *cfn, const char *id,
12268c2ecf20Sopenharmony_ci			      const char *path)
12278c2ecf20Sopenharmony_ci{
12288c2ecf20Sopenharmony_ci	return (path_cmp(cfn->relative_path, path, cfn->sbi->s_case_sensitive) &&
12298c2ecf20Sopenharmony_ci		!strncmp((cfn)->cid, id, HMDFS_CFN_CID_SIZE - 1));
12308c2ecf20Sopenharmony_ci}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_cistruct cache_file_node *__find_cfn(struct hmdfs_sb_info *sbi, const char *cid,
12338c2ecf20Sopenharmony_ci				   const char *path, bool server)
12348c2ecf20Sopenharmony_ci{
12358c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
12368c2ecf20Sopenharmony_ci	struct list_head *head = NULL;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	head = get_list_head(sbi, server);
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	list_for_each_entry(cfn, head, list) {
12418c2ecf20Sopenharmony_ci		if (dentry_file_match(cfn, cid, path)) {
12428c2ecf20Sopenharmony_ci			refcount_inc(&cfn->ref);
12438c2ecf20Sopenharmony_ci			return cfn;
12448c2ecf20Sopenharmony_ci		}
12458c2ecf20Sopenharmony_ci	}
12468c2ecf20Sopenharmony_ci	return NULL;
12478c2ecf20Sopenharmony_ci}
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_cistruct cache_file_node *create_cfn(struct hmdfs_sb_info *sbi, const char *path,
12508c2ecf20Sopenharmony_ci				   const char *cid, bool server)
12518c2ecf20Sopenharmony_ci{
12528c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = kzalloc(sizeof(*cfn), GFP_KERNEL);
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	if (!cfn)
12558c2ecf20Sopenharmony_ci		return NULL;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	cfn->relative_path = kstrdup(path, GFP_KERNEL);
12588c2ecf20Sopenharmony_ci	if (!cfn->relative_path)
12598c2ecf20Sopenharmony_ci		goto out;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	refcount_set(&cfn->ref, 1);
12628c2ecf20Sopenharmony_ci	strncpy(cfn->cid, cid, HMDFS_CFN_CID_SIZE - 1);
12638c2ecf20Sopenharmony_ci	cfn->cid[HMDFS_CFN_CID_SIZE - 1] = '\0';
12648c2ecf20Sopenharmony_ci	cfn->sbi = sbi;
12658c2ecf20Sopenharmony_ci	cfn->server = server;
12668c2ecf20Sopenharmony_ci	return cfn;
12678c2ecf20Sopenharmony_ciout:
12688c2ecf20Sopenharmony_ci	free_cfn(cfn);
12698c2ecf20Sopenharmony_ci	return NULL;
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_cistatic struct file *insert_cfn(struct hmdfs_sb_info *sbi, const char *filename,
12738c2ecf20Sopenharmony_ci	       const char *path, const char *cid, bool server)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	const struct cred *old_cred = NULL;
12768c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
12778c2ecf20Sopenharmony_ci	struct cache_file_node *exist = NULL;
12788c2ecf20Sopenharmony_ci	struct list_head *head = NULL;
12798c2ecf20Sopenharmony_ci	struct file *filp = NULL;
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	cfn = create_cfn(sbi, path, cid, server);
12828c2ecf20Sopenharmony_ci	if (!cfn)
12838c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	old_cred = hmdfs_override_creds(sbi->system_cred);
12868c2ecf20Sopenharmony_ci	filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
12878c2ecf20Sopenharmony_ci	hmdfs_revert_creds(old_cred);
12888c2ecf20Sopenharmony_ci	if (IS_ERR(filp)) {
12898c2ecf20Sopenharmony_ci		hmdfs_err("open file failed, err=%ld", PTR_ERR(filp));
12908c2ecf20Sopenharmony_ci		goto out;
12918c2ecf20Sopenharmony_ci	}
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	head = get_list_head(sbi, server);
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
12968c2ecf20Sopenharmony_ci	exist = __find_cfn(sbi, cid, path, server);
12978c2ecf20Sopenharmony_ci	if (!exist) {
12988c2ecf20Sopenharmony_ci		cfn->filp = filp;
12998c2ecf20Sopenharmony_ci		list_add_tail(&cfn->list, head);
13008c2ecf20Sopenharmony_ci	} else {
13018c2ecf20Sopenharmony_ci		mutex_unlock(&sbi->cache_list_lock);
13028c2ecf20Sopenharmony_ci		release_cfn(exist);
13038c2ecf20Sopenharmony_ci		filp_close(filp, NULL);
13048c2ecf20Sopenharmony_ci		filp = ERR_PTR(-EEXIST);
13058c2ecf20Sopenharmony_ci		goto out;
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
13088c2ecf20Sopenharmony_ci	return filp;
13098c2ecf20Sopenharmony_ciout:
13108c2ecf20Sopenharmony_ci	free_cfn(cfn);
13118c2ecf20Sopenharmony_ci	return filp;
13128c2ecf20Sopenharmony_ci}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ciint hmdfs_rename_dentry(struct dentry *old_dentry, struct dentry *new_dentry,
13158c2ecf20Sopenharmony_ci			struct file *old_filp, struct file *new_filp)
13168c2ecf20Sopenharmony_ci{
13178c2ecf20Sopenharmony_ci	int ret;
13188c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = hmdfs_sb(new_dentry->d_sb);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	/*
13218c2ecf20Sopenharmony_ci	 * Try to delete first, because stale dentry might exist after
13228c2ecf20Sopenharmony_ci	 * coverwrite.
13238c2ecf20Sopenharmony_ci	 */
13248c2ecf20Sopenharmony_ci	hmdfs_delete_dentry(new_dentry, new_filp);
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	ret = create_dentry(new_dentry, d_inode(old_dentry), new_filp, sbi);
13278c2ecf20Sopenharmony_ci	if (ret) {
13288c2ecf20Sopenharmony_ci		hmdfs_err("create dentry failed!, err=%d", ret);
13298c2ecf20Sopenharmony_ci		return ret;
13308c2ecf20Sopenharmony_ci	}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	hmdfs_delete_dentry(old_dentry, old_filp);
13338c2ecf20Sopenharmony_ci	return 0;
13348c2ecf20Sopenharmony_ci}
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci/**
13378c2ecf20Sopenharmony_ci * cache_file_persistent - link the tmpfile to the cache dir
13388c2ecf20Sopenharmony_ci * @con:	the connection peer
13398c2ecf20Sopenharmony_ci * @filp:	the file handler of the tmpfile
13408c2ecf20Sopenharmony_ci * @relative_path: the relative path which the tmpfile belongs
13418c2ecf20Sopenharmony_ci * @server:	server or client
13428c2ecf20Sopenharmony_ci *
13438c2ecf20Sopenharmony_ci * Return value: the new file handler of the persistent file if the
13448c2ecf20Sopenharmony_ci * persistent operation succeed. Otherwise will return the original handler
13458c2ecf20Sopenharmony_ci * of the tmpfile passed in, so that the caller does not have to check
13468c2ecf20Sopenharmony_ci * the returned handler.
13478c2ecf20Sopenharmony_ci *
13488c2ecf20Sopenharmony_ci */
13498c2ecf20Sopenharmony_cistruct file *cache_file_persistent(struct hmdfs_peer *con, struct file *filp,
13508c2ecf20Sopenharmony_ci			   const char *relative_path, bool server)
13518c2ecf20Sopenharmony_ci{
13528c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
13538c2ecf20Sopenharmony_ci	char *fullname = NULL;
13548c2ecf20Sopenharmony_ci	char *cid = server ? HMDFS_SERVER_CID : (char *)con->cid;
13558c2ecf20Sopenharmony_ci	struct file *newf = NULL;
13568c2ecf20Sopenharmony_ci	int i = 0;
13578c2ecf20Sopenharmony_ci	int len;
13588c2ecf20Sopenharmony_ci	int err;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	if (!con->sbi->s_dentry_cache)
13618c2ecf20Sopenharmony_ci		return filp;
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	cfn = find_cfn(con->sbi, cid, relative_path, server);
13648c2ecf20Sopenharmony_ci	if (cfn) {
13658c2ecf20Sopenharmony_ci		release_cfn(cfn);
13668c2ecf20Sopenharmony_ci		return filp;
13678c2ecf20Sopenharmony_ci	}
13688c2ecf20Sopenharmony_ci	fullname = kzalloc(PATH_MAX, GFP_KERNEL);
13698c2ecf20Sopenharmony_ci	if (!fullname)
13708c2ecf20Sopenharmony_ci		return filp;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	err = cache_file_name_generate(fullname, con, relative_path, server);
13738c2ecf20Sopenharmony_ci	if (err)
13748c2ecf20Sopenharmony_ci		goto out;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	err = __vfs_setxattr(file_dentry(filp), file_inode(filp),
13778c2ecf20Sopenharmony_ci			     DENTRY_FILE_XATTR_NAME, relative_path,
13788c2ecf20Sopenharmony_ci			     strlen(relative_path), 0);
13798c2ecf20Sopenharmony_ci	if (err) {
13808c2ecf20Sopenharmony_ci		hmdfs_err("setxattr for file failed, err=%d", err);
13818c2ecf20Sopenharmony_ci		goto out;
13828c2ecf20Sopenharmony_ci	}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	len = strlen(fullname);
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	do {
13878c2ecf20Sopenharmony_ci		err = hmdfs_linkat(&filp->f_path, fullname);
13888c2ecf20Sopenharmony_ci		if (!err)
13898c2ecf20Sopenharmony_ci			break;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci		snprintf(fullname + len, PATH_MAX - len, "_%d", i);
13928c2ecf20Sopenharmony_ci	} while (i++ < DENTRY_FILE_NAME_RETRY);
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	if (err) {
13958c2ecf20Sopenharmony_ci		hmdfs_err("link for file failed, err=%d", err);
13968c2ecf20Sopenharmony_ci		goto out;
13978c2ecf20Sopenharmony_ci	}
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	newf = insert_cfn(con->sbi, fullname, relative_path, cid, server);
14008c2ecf20Sopenharmony_ci	if (!IS_ERR(newf))
14018c2ecf20Sopenharmony_ci		filp = newf;
14028c2ecf20Sopenharmony_ciout:
14038c2ecf20Sopenharmony_ci	kfree(fullname);
14048c2ecf20Sopenharmony_ci	return filp;
14058c2ecf20Sopenharmony_ci}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ciint get_cloud_cache_file(struct dentry *dentry, struct hmdfs_sb_info *sbi)
14088c2ecf20Sopenharmony_ci{
14098c2ecf20Sopenharmony_ci	int ret;
14108c2ecf20Sopenharmony_ci	ssize_t res;
14118c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
14128c2ecf20Sopenharmony_ci	struct clearcache_item *item;
14138c2ecf20Sopenharmony_ci	struct file *filp = NULL;
14148c2ecf20Sopenharmony_ci	uint64_t  hash;
14158c2ecf20Sopenharmony_ci	char *relative_path = NULL;
14168c2ecf20Sopenharmony_ci	char *dirname = NULL;
14178c2ecf20Sopenharmony_ci	char *fullname = NULL;
14188c2ecf20Sopenharmony_ci	char *cache_file_name = NULL;
14198c2ecf20Sopenharmony_ci	char *kvalue = NULL;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	item = hmdfs_find_cache_item(CLOUD_DEVICE, dentry);
14228c2ecf20Sopenharmony_ci	if (item) {
14238c2ecf20Sopenharmony_ci		kref_put(&item->ref, release_cache_item);
14248c2ecf20Sopenharmony_ci		return 0;
14258c2ecf20Sopenharmony_ci	}
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	relative_path = hmdfs_get_dentry_relative_path(dentry);
14288c2ecf20Sopenharmony_ci	if (unlikely(!relative_path)) {
14298c2ecf20Sopenharmony_ci		hmdfs_err("get relative path failed %d", -ENOMEM);
14308c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14318c2ecf20Sopenharmony_ci		goto out;
14328c2ecf20Sopenharmony_ci	}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	dirname = kzalloc(PATH_MAX, GFP_KERNEL);
14358c2ecf20Sopenharmony_ci	if (!dirname) {
14368c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14378c2ecf20Sopenharmony_ci		goto out;
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	cache_file_name = kzalloc(PATH_MAX, GFP_KERNEL);
14418c2ecf20Sopenharmony_ci	if (!cache_file_name) {
14428c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14438c2ecf20Sopenharmony_ci		goto out;
14448c2ecf20Sopenharmony_ci	}
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	fullname = kzalloc(PATH_MAX, GFP_KERNEL);
14478c2ecf20Sopenharmony_ci	if (!fullname) {
14488c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14498c2ecf20Sopenharmony_ci		goto out;
14508c2ecf20Sopenharmony_ci	}
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	kvalue = kzalloc(PATH_MAX, GFP_KERNEL);
14538c2ecf20Sopenharmony_ci	if (!kvalue) {
14548c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14558c2ecf20Sopenharmony_ci		goto out;
14568c2ecf20Sopenharmony_ci	}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	hash = path_hash(relative_path, strlen(relative_path),
14598c2ecf20Sopenharmony_ci			 sbi->s_case_sensitive);
14608c2ecf20Sopenharmony_ci	concat_cachefile_name(cache_file_name, hash, CLOUD_CID, false);
14618c2ecf20Sopenharmony_ci	snprintf(dirname, PATH_MAX, "%s/dentry_cache/cloud/",
14628c2ecf20Sopenharmony_ci		 sbi->cache_dir);
14638c2ecf20Sopenharmony_ci	snprintf(fullname, PATH_MAX, "%s%s", dirname, cache_file_name);
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	filp = filp_open(fullname, O_RDWR | O_LARGEFILE, 0);
14668c2ecf20Sopenharmony_ci	if (IS_ERR(filp)) {
14678c2ecf20Sopenharmony_ci		hmdfs_debug("open fail %ld", PTR_ERR(filp));
14688c2ecf20Sopenharmony_ci		ret = PTR_ERR(filp);
14698c2ecf20Sopenharmony_ci		goto out;
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	res = __vfs_getxattr(file_dentry(filp), file_inode(filp),
14738c2ecf20Sopenharmony_ci			       DENTRY_FILE_XATTR_NAME, kvalue, PATH_MAX);
14748c2ecf20Sopenharmony_ci	if (res <= 0 || res >= PATH_MAX) {
14758c2ecf20Sopenharmony_ci		hmdfs_err("getxattr return: %zd", res);
14768c2ecf20Sopenharmony_ci		filp_close(filp, NULL);
14778c2ecf20Sopenharmony_ci		ret = -ENOENT;
14788c2ecf20Sopenharmony_ci		goto out;
14798c2ecf20Sopenharmony_ci	}
14808c2ecf20Sopenharmony_ci	kvalue[res] = '\0';
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	if (!path_cmp(relative_path, kvalue, sbi->s_case_sensitive)) {
14838c2ecf20Sopenharmony_ci		hmdfs_err("relative path from xattr do not match");
14848c2ecf20Sopenharmony_ci		filp_close(filp, NULL);
14858c2ecf20Sopenharmony_ci		ret = -ENOENT;
14868c2ecf20Sopenharmony_ci		goto out;
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	mutex_lock(&d_info->cache_pull_lock);
14908c2ecf20Sopenharmony_ci	hmdfs_add_cache_list(CLOUD_DEVICE, dentry, filp);
14918c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->cache_pull_lock);
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	ret = 0;
14948c2ecf20Sopenharmony_ciout:
14958c2ecf20Sopenharmony_ci	kfree(relative_path);
14968c2ecf20Sopenharmony_ci	kfree(dirname);
14978c2ecf20Sopenharmony_ci	kfree(fullname);
14988c2ecf20Sopenharmony_ci	kfree(cache_file_name);
14998c2ecf20Sopenharmony_ci	kfree(kvalue);
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	return ret;
15028c2ecf20Sopenharmony_ci}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_civoid __destroy_cfn(struct list_head *head)
15058c2ecf20Sopenharmony_ci{
15068c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
15078c2ecf20Sopenharmony_ci	struct cache_file_node *n = NULL;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	list_for_each_entry_safe(cfn, n, head, list) {
15108c2ecf20Sopenharmony_ci		list_del_init(&cfn->list);
15118c2ecf20Sopenharmony_ci		release_cfn(cfn);
15128c2ecf20Sopenharmony_ci	}
15138c2ecf20Sopenharmony_ci}
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_civoid hmdfs_cfn_destroy(struct hmdfs_sb_info *sbi)
15168c2ecf20Sopenharmony_ci{
15178c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
15188c2ecf20Sopenharmony_ci	__destroy_cfn(&sbi->client_cache);
15198c2ecf20Sopenharmony_ci	__destroy_cfn(&sbi->server_cache);
15208c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
15218c2ecf20Sopenharmony_ci}
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_cistruct cache_file_node *find_cfn(struct hmdfs_sb_info *sbi, const char *cid,
15248c2ecf20Sopenharmony_ci				 const char *path, bool server)
15258c2ecf20Sopenharmony_ci{
15268c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
15298c2ecf20Sopenharmony_ci	cfn = __find_cfn(sbi, cid, path, server);
15308c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
15318c2ecf20Sopenharmony_ci	return cfn;
15328c2ecf20Sopenharmony_ci}
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_civoid release_cfn(struct cache_file_node *cfn)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	if (refcount_dec_and_test(&cfn->ref))
15378c2ecf20Sopenharmony_ci		free_cfn(cfn);
15388c2ecf20Sopenharmony_ci}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_civoid remove_cfn(struct cache_file_node *cfn)
15418c2ecf20Sopenharmony_ci{
15428c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = cfn->sbi;
15438c2ecf20Sopenharmony_ci	bool deleted;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
15468c2ecf20Sopenharmony_ci	deleted = list_empty(&cfn->list);
15478c2ecf20Sopenharmony_ci	if (!deleted)
15488c2ecf20Sopenharmony_ci		list_del_init(&cfn->list);
15498c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
15508c2ecf20Sopenharmony_ci	if (!deleted) {
15518c2ecf20Sopenharmony_ci		delete_dentry_file(cfn->filp);
15528c2ecf20Sopenharmony_ci		release_cfn(cfn);
15538c2ecf20Sopenharmony_ci	}
15548c2ecf20Sopenharmony_ci}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ciint hmdfs_do_lock_file(struct file *filp, unsigned char fl_type, loff_t start,
15578c2ecf20Sopenharmony_ci		       loff_t len)
15588c2ecf20Sopenharmony_ci{
15598c2ecf20Sopenharmony_ci	struct file_lock fl;
15608c2ecf20Sopenharmony_ci	int err;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	locks_init_lock(&fl);
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	fl.fl_type = fl_type;
15658c2ecf20Sopenharmony_ci	fl.fl_flags = FL_POSIX | FL_CLOSE | FL_SLEEP;
15668c2ecf20Sopenharmony_ci	fl.fl_start = start;
15678c2ecf20Sopenharmony_ci	fl.fl_end = start + len - 1;
15688c2ecf20Sopenharmony_ci	fl.fl_owner = filp;
15698c2ecf20Sopenharmony_ci	fl.fl_pid = current->tgid;
15708c2ecf20Sopenharmony_ci	fl.fl_file = filp;
15718c2ecf20Sopenharmony_ci	fl.fl_ops = NULL;
15728c2ecf20Sopenharmony_ci	fl.fl_lmops = NULL;
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ci	err = locks_lock_file_wait(filp, &fl);
15758c2ecf20Sopenharmony_ci	if (err)
15768c2ecf20Sopenharmony_ci		hmdfs_err("lock file wait failed: %d", err);
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	return err;
15798c2ecf20Sopenharmony_ci}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ciint hmdfs_wlock_file(struct file *filp, loff_t start, loff_t len)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	return hmdfs_do_lock_file(filp, F_WRLCK, start, len);
15848c2ecf20Sopenharmony_ci}
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ciint hmdfs_rlock_file(struct file *filp, loff_t start, loff_t len)
15878c2ecf20Sopenharmony_ci{
15888c2ecf20Sopenharmony_ci	return hmdfs_do_lock_file(filp, F_RDLCK, start, len);
15898c2ecf20Sopenharmony_ci}
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ciint hmdfs_unlock_file(struct file *filp, loff_t start, loff_t len)
15928c2ecf20Sopenharmony_ci{
15938c2ecf20Sopenharmony_ci	return hmdfs_do_lock_file(filp, F_UNLCK, start, len);
15948c2ecf20Sopenharmony_ci}
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_cilong cache_file_truncate(struct hmdfs_sb_info *sbi, const struct path *path,
15978c2ecf20Sopenharmony_ci			 loff_t length)
15988c2ecf20Sopenharmony_ci{
15998c2ecf20Sopenharmony_ci	const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred);
16008c2ecf20Sopenharmony_ci	long ret = vfs_truncate(path, length);
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	hmdfs_revert_creds(old_cred);
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	return ret;
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_cissize_t cache_file_read(struct hmdfs_sb_info *sbi, struct file *filp, void *buf,
16088c2ecf20Sopenharmony_ci			size_t count, loff_t *pos)
16098c2ecf20Sopenharmony_ci{
16108c2ecf20Sopenharmony_ci	const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred);
16118c2ecf20Sopenharmony_ci	ssize_t ret = kernel_read(filp, buf, count, pos);
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci	hmdfs_revert_creds(old_cred);
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	return ret;
16168c2ecf20Sopenharmony_ci}
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_cissize_t cache_file_write(struct hmdfs_sb_info *sbi, struct file *filp,
16198c2ecf20Sopenharmony_ci			 const void *buf, size_t count, loff_t *pos)
16208c2ecf20Sopenharmony_ci{
16218c2ecf20Sopenharmony_ci	const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred);
16228c2ecf20Sopenharmony_ci	ssize_t ret = kernel_write(filp, buf, count, pos);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	hmdfs_revert_creds(old_cred);
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	return ret;
16278c2ecf20Sopenharmony_ci}
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ciint read_header(struct hmdfs_sb_info *sbi, struct file *filp,
16318c2ecf20Sopenharmony_ci		struct hmdfs_dcache_header *header)
16328c2ecf20Sopenharmony_ci{
16338c2ecf20Sopenharmony_ci	ssize_t bytes;
16348c2ecf20Sopenharmony_ci	loff_t pos = 0;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	bytes = cache_file_read(sbi, filp, header, sizeof(*header), &pos);
16378c2ecf20Sopenharmony_ci	if (bytes != sizeof(*header)) {
16388c2ecf20Sopenharmony_ci		hmdfs_err("read file failed, err:%zd", bytes);
16398c2ecf20Sopenharmony_ci		return -EIO;
16408c2ecf20Sopenharmony_ci	}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	return 0;
16438c2ecf20Sopenharmony_ci}
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_cistatic unsigned long long cache_get_dentry_count(struct hmdfs_sb_info *sbi,
16468c2ecf20Sopenharmony_ci						 struct file *filp)
16478c2ecf20Sopenharmony_ci{
16488c2ecf20Sopenharmony_ci	struct hmdfs_dcache_header header;
16498c2ecf20Sopenharmony_ci	int overallpage;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	overallpage = get_dentry_group_cnt(file_inode(filp));
16528c2ecf20Sopenharmony_ci	if (overallpage == 0)
16538c2ecf20Sopenharmony_ci		return 0;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	if (read_header(sbi, filp, &header))
16568c2ecf20Sopenharmony_ci		return 0;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	return le64_to_cpu(header.num);
16598c2ecf20Sopenharmony_ci}
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_cistatic int cache_check_case_sensitive(struct hmdfs_sb_info *sbi,
16628c2ecf20Sopenharmony_ci				struct file *filp)
16638c2ecf20Sopenharmony_ci{
16648c2ecf20Sopenharmony_ci	struct hmdfs_dcache_header header;
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci	if (read_header(sbi, filp, &header))
16678c2ecf20Sopenharmony_ci		return 0;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	if (sbi->s_case_sensitive != (bool)header.case_sensitive) {
16708c2ecf20Sopenharmony_ci		hmdfs_info("Case sensitive inconsistent, current fs is: %d, cache is %d, will drop cache",
16718c2ecf20Sopenharmony_ci			   sbi->s_case_sensitive, header.case_sensitive);
16728c2ecf20Sopenharmony_ci		return 0;
16738c2ecf20Sopenharmony_ci	}
16748c2ecf20Sopenharmony_ci	return 1;
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ciint write_header(struct file *filp, struct hmdfs_dcache_header *header)
16788c2ecf20Sopenharmony_ci{
16798c2ecf20Sopenharmony_ci	loff_t pos = 0;
16808c2ecf20Sopenharmony_ci	ssize_t size;
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	size = kernel_write(filp, header, sizeof(*header), &pos);
16838c2ecf20Sopenharmony_ci	if (size != sizeof(*header)) {
16848c2ecf20Sopenharmony_ci		hmdfs_err("update dcache header failed %zd", size);
16858c2ecf20Sopenharmony_ci		return -EIO;
16868c2ecf20Sopenharmony_ci	}
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	return 0;
16898c2ecf20Sopenharmony_ci}
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_civoid add_to_delete_list(struct hmdfs_sb_info *sbi, struct cache_file_node *cfn)
16928c2ecf20Sopenharmony_ci{
16938c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
16948c2ecf20Sopenharmony_ci	list_add_tail(&cfn->list, &sbi->to_delete);
16958c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
16968c2ecf20Sopenharmony_ci}
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_civoid load_cfn(struct hmdfs_sb_info *sbi, const char *fullname, const char *path,
16998c2ecf20Sopenharmony_ci	      const char *cid, bool server)
17008c2ecf20Sopenharmony_ci{
17018c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
17028c2ecf20Sopenharmony_ci	struct cache_file_node *cfn1 = NULL;
17038c2ecf20Sopenharmony_ci	struct list_head *head = NULL;
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	cfn = create_cfn(sbi, path, cid, server);
17068c2ecf20Sopenharmony_ci	if (!cfn)
17078c2ecf20Sopenharmony_ci		return;
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	cfn->filp = filp_open(fullname, O_RDWR | O_LARGEFILE, 0);
17108c2ecf20Sopenharmony_ci	if (IS_ERR(cfn->filp)) {
17118c2ecf20Sopenharmony_ci		hmdfs_err("open fail %ld", PTR_ERR(cfn->filp));
17128c2ecf20Sopenharmony_ci		goto out;
17138c2ecf20Sopenharmony_ci	}
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	if (cache_get_dentry_count(sbi, cfn->filp) < sbi->dcache_threshold && strcmp(cid, CLOUD_CID)) {
17168c2ecf20Sopenharmony_ci		add_to_delete_list(sbi, cfn);
17178c2ecf20Sopenharmony_ci		return;
17188c2ecf20Sopenharmony_ci	}
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci	if (!cache_check_case_sensitive(sbi, cfn->filp) && strcmp(cid, CLOUD_CID)) {
17218c2ecf20Sopenharmony_ci		add_to_delete_list(sbi, cfn);
17228c2ecf20Sopenharmony_ci		return;
17238c2ecf20Sopenharmony_ci	}
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	head = get_list_head(sbi, server);
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
17288c2ecf20Sopenharmony_ci	cfn1 = __find_cfn(sbi, cid, path, server);
17298c2ecf20Sopenharmony_ci	if (!cfn1) {
17308c2ecf20Sopenharmony_ci		list_add_tail(&cfn->list, head);
17318c2ecf20Sopenharmony_ci	} else {
17328c2ecf20Sopenharmony_ci		release_cfn(cfn1);
17338c2ecf20Sopenharmony_ci		mutex_unlock(&sbi->cache_list_lock);
17348c2ecf20Sopenharmony_ci		add_to_delete_list(sbi, cfn);
17358c2ecf20Sopenharmony_ci		return;
17368c2ecf20Sopenharmony_ci	}
17378c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	return;
17408c2ecf20Sopenharmony_ciout:
17418c2ecf20Sopenharmony_ci	free_cfn(cfn);
17428c2ecf20Sopenharmony_ci}
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_cistatic int get_cid_and_hash(const char *name, uint64_t *hash, char *cid)
17458c2ecf20Sopenharmony_ci{
17468c2ecf20Sopenharmony_ci	int len;
17478c2ecf20Sopenharmony_ci	char *p = strstr(name, "_");
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci	if (!p)
17508c2ecf20Sopenharmony_ci		return -EINVAL;
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci	len = p - name;
17538c2ecf20Sopenharmony_ci	if (len >= HMDFS_CFN_CID_SIZE)
17548c2ecf20Sopenharmony_ci		return -EINVAL;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	memcpy(cid, name, len);
17578c2ecf20Sopenharmony_ci	cid[len] = '\0';
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	if (sscanf(++p, "%llx", hash) != 1)
17608c2ecf20Sopenharmony_ci		return -EINVAL;
17618c2ecf20Sopenharmony_ci	return 0;
17628c2ecf20Sopenharmony_ci}
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_cistatic void store_one(const char *name, struct cache_file_callback *cb)
17658c2ecf20Sopenharmony_ci{
17668c2ecf20Sopenharmony_ci	struct file *file = NULL;
17678c2ecf20Sopenharmony_ci	char *fullname = NULL;
17688c2ecf20Sopenharmony_ci	char *kvalue = NULL;
17698c2ecf20Sopenharmony_ci	char cid[HMDFS_CFN_CID_SIZE];
17708c2ecf20Sopenharmony_ci	uint64_t hash;
17718c2ecf20Sopenharmony_ci	ssize_t error;
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	if (strlen(name) + strlen(cb->dirname) >= PATH_MAX)
17748c2ecf20Sopenharmony_ci		return;
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci	fullname = kzalloc(PATH_MAX, GFP_KERNEL);
17778c2ecf20Sopenharmony_ci	if (!fullname)
17788c2ecf20Sopenharmony_ci		return;
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	snprintf(fullname, PATH_MAX, "%s%s", cb->dirname, name);
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	file = filp_open(fullname, O_RDWR | O_LARGEFILE, 0);
17838c2ecf20Sopenharmony_ci	if (IS_ERR(file)) {
17848c2ecf20Sopenharmony_ci		hmdfs_err("open fail %ld", PTR_ERR(file));
17858c2ecf20Sopenharmony_ci		goto out;
17868c2ecf20Sopenharmony_ci	}
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	kvalue = kzalloc(PATH_MAX, GFP_KERNEL);
17898c2ecf20Sopenharmony_ci	if (!kvalue)
17908c2ecf20Sopenharmony_ci		goto out_file;
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ci	error = __vfs_getxattr(file_dentry(file), file_inode(file),
17938c2ecf20Sopenharmony_ci			       DENTRY_FILE_XATTR_NAME, kvalue, PATH_MAX);
17948c2ecf20Sopenharmony_ci	if (error <= 0 || error >= PATH_MAX) {
17958c2ecf20Sopenharmony_ci		hmdfs_err("getxattr return: %zd", error);
17968c2ecf20Sopenharmony_ci		goto out_kvalue;
17978c2ecf20Sopenharmony_ci	}
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	kvalue[error] = '\0';
18008c2ecf20Sopenharmony_ci	cid[0] = '\0';
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci	if (!cb->server) {
18038c2ecf20Sopenharmony_ci		if (get_cid_and_hash(name, &hash, cid)) {
18048c2ecf20Sopenharmony_ci			hmdfs_err("get cid and hash fail");
18058c2ecf20Sopenharmony_ci			goto out_kvalue;
18068c2ecf20Sopenharmony_ci		}
18078c2ecf20Sopenharmony_ci	}
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	load_cfn(cb->sbi, fullname, kvalue, cid, cb->server);
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ciout_kvalue:
18128c2ecf20Sopenharmony_ci	kfree(kvalue);
18138c2ecf20Sopenharmony_ciout_file:
18148c2ecf20Sopenharmony_ci	filp_close(file, NULL);
18158c2ecf20Sopenharmony_ciout:
18168c2ecf20Sopenharmony_ci	kfree(fullname);
18178c2ecf20Sopenharmony_ci}
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_cistatic int cache_file_iterate(struct dir_context *ctx, const char *name,
18208c2ecf20Sopenharmony_ci			      int name_len, loff_t offset, u64 ino,
18218c2ecf20Sopenharmony_ci			      unsigned int d_type)
18228c2ecf20Sopenharmony_ci{
18238c2ecf20Sopenharmony_ci	struct cache_file_item *cfi = NULL;
18248c2ecf20Sopenharmony_ci	struct cache_file_callback *cb =
18258c2ecf20Sopenharmony_ci			container_of(ctx, struct cache_file_callback, ctx);
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	if (name_len > NAME_MAX) {
18288c2ecf20Sopenharmony_ci		hmdfs_err("name_len:%d NAME_MAX:%u", name_len, NAME_MAX);
18298c2ecf20Sopenharmony_ci		return 0;
18308c2ecf20Sopenharmony_ci	}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	if (d_type != DT_REG)
18338c2ecf20Sopenharmony_ci		return 0;
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	cfi = kmalloc(sizeof(*cfi), GFP_KERNEL);
18368c2ecf20Sopenharmony_ci	if (!cfi)
18378c2ecf20Sopenharmony_ci		return -ENOMEM;
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci	cfi->name = kstrndup(name, name_len, GFP_KERNEL);
18408c2ecf20Sopenharmony_ci	if (!cfi->name) {
18418c2ecf20Sopenharmony_ci		kfree(cfi);
18428c2ecf20Sopenharmony_ci		return -ENOMEM;
18438c2ecf20Sopenharmony_ci	}
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	list_add_tail(&cfi->list, &cb->list);
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	return 0;
18488c2ecf20Sopenharmony_ci}
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_civoid hmdfs_do_load(struct hmdfs_sb_info *sbi, const char *fullname, bool server)
18518c2ecf20Sopenharmony_ci{
18528c2ecf20Sopenharmony_ci	struct file *file = NULL;
18538c2ecf20Sopenharmony_ci	struct path dirpath;
18548c2ecf20Sopenharmony_ci	int err;
18558c2ecf20Sopenharmony_ci	struct cache_file_item *cfi = NULL;
18568c2ecf20Sopenharmony_ci	struct cache_file_item *n = NULL;
18578c2ecf20Sopenharmony_ci	struct cache_file_callback cb = {
18588c2ecf20Sopenharmony_ci		.ctx.actor = cache_file_iterate,
18598c2ecf20Sopenharmony_ci		.ctx.pos = 0,
18608c2ecf20Sopenharmony_ci		.dirname = fullname,
18618c2ecf20Sopenharmony_ci		.sbi = sbi,
18628c2ecf20Sopenharmony_ci		.server = server,
18638c2ecf20Sopenharmony_ci	};
18648c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cb.list);
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	err = kern_path(fullname, LOOKUP_DIRECTORY, &dirpath);
18688c2ecf20Sopenharmony_ci	if (err) {
18698c2ecf20Sopenharmony_ci		hmdfs_info("No file path");
18708c2ecf20Sopenharmony_ci		return;
18718c2ecf20Sopenharmony_ci	}
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci	file = dentry_open(&dirpath, O_RDONLY, current_cred());
18748c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(file)) {
18758c2ecf20Sopenharmony_ci		hmdfs_err("dentry_open failed, error: %ld", PTR_ERR(file));
18768c2ecf20Sopenharmony_ci		path_put(&dirpath);
18778c2ecf20Sopenharmony_ci		return;
18788c2ecf20Sopenharmony_ci	}
18798c2ecf20Sopenharmony_ci
18808c2ecf20Sopenharmony_ci	err = iterate_dir(file, &cb.ctx);
18818c2ecf20Sopenharmony_ci	if (err)
18828c2ecf20Sopenharmony_ci		hmdfs_err("iterate_dir failed, err: %d", err);
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci	list_for_each_entry_safe(cfi, n, &cb.list, list) {
18858c2ecf20Sopenharmony_ci		store_one(cfi->name, &cb);
18868c2ecf20Sopenharmony_ci		list_del_init(&cfi->list);
18878c2ecf20Sopenharmony_ci		kfree(cfi->name);
18888c2ecf20Sopenharmony_ci		kfree(cfi);
18898c2ecf20Sopenharmony_ci	}
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	fput(file);
18928c2ecf20Sopenharmony_ci	path_put(&dirpath);
18938c2ecf20Sopenharmony_ci}
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_ci/**
18968c2ecf20Sopenharmony_ci * This function just used for delete dentryfile.dat
18978c2ecf20Sopenharmony_ci */
18988c2ecf20Sopenharmony_ciint delete_dentry_file(struct file *filp)
18998c2ecf20Sopenharmony_ci{
19008c2ecf20Sopenharmony_ci	int err = 0;
19018c2ecf20Sopenharmony_ci	struct dentry *dentry = file_dentry(filp);
19028c2ecf20Sopenharmony_ci	struct dentry *parent = lock_parent(dentry);
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	if (dentry->d_parent == parent) {
19058c2ecf20Sopenharmony_ci		dget(dentry);
19068c2ecf20Sopenharmony_ci		err = vfs_unlink(d_inode(parent), dentry, NULL);
19078c2ecf20Sopenharmony_ci		dput(dentry);
19088c2ecf20Sopenharmony_ci	}
19098c2ecf20Sopenharmony_ci	unlock_dir(parent);
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	return err;
19128c2ecf20Sopenharmony_ci}
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_civoid hmdfs_delete_useless_cfn(struct hmdfs_sb_info *sbi)
19158c2ecf20Sopenharmony_ci{
19168c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
19178c2ecf20Sopenharmony_ci	struct cache_file_node *n = NULL;
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	list_for_each_entry_safe(cfn, n, &sbi->to_delete, list) {
19228c2ecf20Sopenharmony_ci		delete_dentry_file(cfn->filp);
19238c2ecf20Sopenharmony_ci		list_del_init(&cfn->list);
19248c2ecf20Sopenharmony_ci		release_cfn(cfn);
19258c2ecf20Sopenharmony_ci	}
19268c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
19278c2ecf20Sopenharmony_ci}
19288c2ecf20Sopenharmony_ci
19298c2ecf20Sopenharmony_civoid hmdfs_cfn_load(struct hmdfs_sb_info *sbi)
19308c2ecf20Sopenharmony_ci{
19318c2ecf20Sopenharmony_ci	char *fullname = NULL;
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	if (!sbi->s_dentry_cache)
19348c2ecf20Sopenharmony_ci		return;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	fullname = kzalloc(PATH_MAX, GFP_KERNEL);
19378c2ecf20Sopenharmony_ci	if (!fullname)
19388c2ecf20Sopenharmony_ci		return;
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	snprintf(fullname, PATH_MAX, "%s/dentry_cache/client/",
19418c2ecf20Sopenharmony_ci		 sbi->cache_dir);
19428c2ecf20Sopenharmony_ci	hmdfs_do_load(sbi, fullname, false);
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	snprintf(fullname, PATH_MAX, "%s/dentry_cache/server/",
19458c2ecf20Sopenharmony_ci		 sbi->cache_dir);
19468c2ecf20Sopenharmony_ci	hmdfs_do_load(sbi, fullname, true);
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	kfree(fullname);
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	hmdfs_delete_useless_cfn(sbi);
19518c2ecf20Sopenharmony_ci}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_cistatic void __cache_file_destroy_by_path(struct list_head *head,
19548c2ecf20Sopenharmony_ci					 const char *path)
19558c2ecf20Sopenharmony_ci{
19568c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
19578c2ecf20Sopenharmony_ci	struct cache_file_node *n = NULL;
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	list_for_each_entry_safe(cfn, n, head, list) {
19608c2ecf20Sopenharmony_ci		if (strcmp(path, cfn->relative_path) != 0)
19618c2ecf20Sopenharmony_ci			continue;
19628c2ecf20Sopenharmony_ci		list_del_init(&cfn->list);
19638c2ecf20Sopenharmony_ci		delete_dentry_file(cfn->filp);
19648c2ecf20Sopenharmony_ci		release_cfn(cfn);
19658c2ecf20Sopenharmony_ci	}
19668c2ecf20Sopenharmony_ci}
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_cistatic void cache_file_destroy_by_path(struct hmdfs_sb_info *sbi,
19698c2ecf20Sopenharmony_ci				       const char *path)
19708c2ecf20Sopenharmony_ci{
19718c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cache_list_lock);
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	__cache_file_destroy_by_path(&sbi->server_cache, path);
19748c2ecf20Sopenharmony_ci	__cache_file_destroy_by_path(&sbi->client_cache, path);
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cache_list_lock);
19778c2ecf20Sopenharmony_ci}
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_cistatic void cache_file_find_and_delete(struct hmdfs_peer *con,
19808c2ecf20Sopenharmony_ci				       const char *relative_path)
19818c2ecf20Sopenharmony_ci{
19828c2ecf20Sopenharmony_ci	struct cache_file_node *cfn;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	cfn = find_cfn(con->sbi, con->cid, relative_path, false);
19858c2ecf20Sopenharmony_ci	if (!cfn)
19868c2ecf20Sopenharmony_ci		return;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	remove_cfn(cfn);
19898c2ecf20Sopenharmony_ci	release_cfn(cfn);
19908c2ecf20Sopenharmony_ci}
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_civoid cache_file_delete_by_dentry(struct hmdfs_peer *con, struct dentry *dentry)
19938c2ecf20Sopenharmony_ci{
19948c2ecf20Sopenharmony_ci	char *relative_path = NULL;
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci	relative_path = hmdfs_get_dentry_relative_path(dentry);
19978c2ecf20Sopenharmony_ci	if (unlikely(!relative_path)) {
19988c2ecf20Sopenharmony_ci		hmdfs_err("get relative path failed %d", -ENOMEM);
19998c2ecf20Sopenharmony_ci		return;
20008c2ecf20Sopenharmony_ci	}
20018c2ecf20Sopenharmony_ci	cache_file_find_and_delete(con, relative_path);
20028c2ecf20Sopenharmony_ci	kfree(relative_path);
20038c2ecf20Sopenharmony_ci}
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_cistruct file *hmdfs_get_new_dentry_file(struct hmdfs_peer *con,
20068c2ecf20Sopenharmony_ci				       const char *relative_path,
20078c2ecf20Sopenharmony_ci				       struct hmdfs_dcache_header *header)
20088c2ecf20Sopenharmony_ci{
20098c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = con->sbi;
20108c2ecf20Sopenharmony_ci	int len = strlen(relative_path);
20118c2ecf20Sopenharmony_ci	struct file *filp = NULL;
20128c2ecf20Sopenharmony_ci	int err;
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	filp = create_local_dentry_file_cache(sbi);
20158c2ecf20Sopenharmony_ci	if (IS_ERR(filp))
20168c2ecf20Sopenharmony_ci		return filp;
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci	err = hmdfs_client_start_readdir(con, filp, relative_path, len, header);
20198c2ecf20Sopenharmony_ci	if (err) {
20208c2ecf20Sopenharmony_ci		if (err != -ENOENT)
20218c2ecf20Sopenharmony_ci			hmdfs_err("readdir failed dev: %llu err: %d",
20228c2ecf20Sopenharmony_ci				  con->device_id, err);
20238c2ecf20Sopenharmony_ci		fput(filp);
20248c2ecf20Sopenharmony_ci		filp = ERR_PTR(err);
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci
20278c2ecf20Sopenharmony_ci	return filp;
20288c2ecf20Sopenharmony_ci}
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_civoid add_cfn_to_item(struct dentry *dentry, struct hmdfs_peer *con,
20318c2ecf20Sopenharmony_ci		     struct cache_file_node *cfn)
20328c2ecf20Sopenharmony_ci{
20338c2ecf20Sopenharmony_ci	struct file *file = cfn->filp;
20348c2ecf20Sopenharmony_ci	int err;
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	err = hmdfs_add_cache_list(con->device_id, dentry, file);
20378c2ecf20Sopenharmony_ci	if (unlikely(err)) {
20388c2ecf20Sopenharmony_ci		hmdfs_err("add cache list failed devid:%llu err:%d",
20398c2ecf20Sopenharmony_ci			  con->device_id, err);
20408c2ecf20Sopenharmony_ci		return;
20418c2ecf20Sopenharmony_ci	}
20428c2ecf20Sopenharmony_ci}
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ciint hmdfs_add_file_to_cache(struct dentry *dentry, struct hmdfs_peer *con,
20458c2ecf20Sopenharmony_ci			    struct file *file, const char *relative_path)
20468c2ecf20Sopenharmony_ci{
20478c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = con->sbi;
20488c2ecf20Sopenharmony_ci	struct file *newf = file;
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci	if (cache_get_dentry_count(sbi, file) >= sbi->dcache_threshold)
20518c2ecf20Sopenharmony_ci		newf = cache_file_persistent(con, file, relative_path, false);
20528c2ecf20Sopenharmony_ci	else
20538c2ecf20Sopenharmony_ci		cache_file_find_and_delete(con, relative_path);
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	return hmdfs_add_cache_list(con->device_id, dentry, newf);
20568c2ecf20Sopenharmony_ci}
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_cistatic struct file *read_header_and_revalidate(struct hmdfs_peer *con,
20598c2ecf20Sopenharmony_ci					       struct file *filp,
20608c2ecf20Sopenharmony_ci					       const char *relative_path)
20618c2ecf20Sopenharmony_ci{
20628c2ecf20Sopenharmony_ci	struct hmdfs_dcache_header header;
20638c2ecf20Sopenharmony_ci	struct hmdfs_dcache_header *p = NULL;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	if (read_header(con->sbi, filp, &header) == 0)
20668c2ecf20Sopenharmony_ci		p = &header;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	return hmdfs_get_new_dentry_file(con, relative_path, p);
20698c2ecf20Sopenharmony_ci}
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_civoid remote_file_revalidate_cfn(struct dentry *dentry, struct hmdfs_peer *con,
20728c2ecf20Sopenharmony_ci				struct cache_file_node *cfn,
20738c2ecf20Sopenharmony_ci				const char *relative_path)
20748c2ecf20Sopenharmony_ci{
20758c2ecf20Sopenharmony_ci	struct file *file = NULL;
20768c2ecf20Sopenharmony_ci	int err;
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci	file = read_header_and_revalidate(con, cfn->filp, relative_path);
20798c2ecf20Sopenharmony_ci	if (IS_ERR(file))
20808c2ecf20Sopenharmony_ci		return;
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	/*
20838c2ecf20Sopenharmony_ci	 * If the request returned ok but file length is 0, we assume
20848c2ecf20Sopenharmony_ci	 * that the server verified the client cache file is uptodate.
20858c2ecf20Sopenharmony_ci	 */
20868c2ecf20Sopenharmony_ci	if (i_size_read(file->f_inode) == 0) {
20878c2ecf20Sopenharmony_ci		hmdfs_info("The cfn cache for dev:%llu is uptodate",
20888c2ecf20Sopenharmony_ci			    con->device_id);
20898c2ecf20Sopenharmony_ci		fput(file);
20908c2ecf20Sopenharmony_ci		add_cfn_to_item(dentry, con, cfn);
20918c2ecf20Sopenharmony_ci		return;
20928c2ecf20Sopenharmony_ci	}
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	/* OK, cfn is not uptodate, let's remove it and add the new file */
20958c2ecf20Sopenharmony_ci	remove_cfn(cfn);
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_ci	err = hmdfs_add_file_to_cache(dentry, con, file, relative_path);
20988c2ecf20Sopenharmony_ci	if (unlikely(err))
20998c2ecf20Sopenharmony_ci		hmdfs_err("add cache list failed devid:%llu err:%d",
21008c2ecf20Sopenharmony_ci			  con->device_id, err);
21018c2ecf20Sopenharmony_ci	fput(file);
21028c2ecf20Sopenharmony_ci}
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_civoid remote_file_revalidate_item(struct dentry *dentry, struct hmdfs_peer *con,
21058c2ecf20Sopenharmony_ci				 struct clearcache_item *item,
21068c2ecf20Sopenharmony_ci				 const char *relative_path)
21078c2ecf20Sopenharmony_ci{
21088c2ecf20Sopenharmony_ci	struct file *file = NULL;
21098c2ecf20Sopenharmony_ci	int err;
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	file = read_header_and_revalidate(con, item->filp, relative_path);
21128c2ecf20Sopenharmony_ci	if (IS_ERR(file))
21138c2ecf20Sopenharmony_ci		return;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	/*
21168c2ecf20Sopenharmony_ci	 * If the request returned ok but file length is 0, we assume
21178c2ecf20Sopenharmony_ci	 * that the server verified the client cache file is uptodate.
21188c2ecf20Sopenharmony_ci	 */
21198c2ecf20Sopenharmony_ci	if (i_size_read(file->f_inode) == 0) {
21208c2ecf20Sopenharmony_ci		hmdfs_info("The item cache for dev:%llu is uptodate",
21218c2ecf20Sopenharmony_ci			    con->device_id);
21228c2ecf20Sopenharmony_ci		item->time = jiffies;
21238c2ecf20Sopenharmony_ci		fput(file);
21248c2ecf20Sopenharmony_ci		return;
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	/* We need to replace the old item */
21288c2ecf20Sopenharmony_ci	remove_cache_item(item);
21298c2ecf20Sopenharmony_ci	cache_file_find_and_delete(con, relative_path);
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	err = hmdfs_add_file_to_cache(dentry, con, file, relative_path);
21328c2ecf20Sopenharmony_ci	if (unlikely(err))
21338c2ecf20Sopenharmony_ci		hmdfs_err("add cache list failed devid:%llu err:%d",
21348c2ecf20Sopenharmony_ci			  con->device_id, err);
21358c2ecf20Sopenharmony_ci	fput(file);
21368c2ecf20Sopenharmony_ci}
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_cibool get_remote_dentry_file(struct dentry *dentry, struct hmdfs_peer *con)
21398c2ecf20Sopenharmony_ci{
21408c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
21418c2ecf20Sopenharmony_ci	struct cache_file_node *cfn = NULL;
21428c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = con->sbi;
21438c2ecf20Sopenharmony_ci	char *relative_path = NULL;
21448c2ecf20Sopenharmony_ci	int err = 0;
21458c2ecf20Sopenharmony_ci	struct file *filp = NULL;
21468c2ecf20Sopenharmony_ci	struct clearcache_item *item;
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	if (hmdfs_cache_revalidate(READ_ONCE(con->conn_time), con->device_id,
21498c2ecf20Sopenharmony_ci				   dentry))
21508c2ecf20Sopenharmony_ci		return false;
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	relative_path = hmdfs_get_dentry_relative_path(dentry);
21538c2ecf20Sopenharmony_ci	if (unlikely(!relative_path)) {
21548c2ecf20Sopenharmony_ci		hmdfs_err("get relative path failed %d", -ENOMEM);
21558c2ecf20Sopenharmony_ci		return false;
21568c2ecf20Sopenharmony_ci	}
21578c2ecf20Sopenharmony_ci	mutex_lock(&d_info->cache_pull_lock);
21588c2ecf20Sopenharmony_ci	if (hmdfs_cache_revalidate(READ_ONCE(con->conn_time), con->device_id,
21598c2ecf20Sopenharmony_ci				   dentry))
21608c2ecf20Sopenharmony_ci		goto out_unlock;
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci	item = hmdfs_find_cache_item(con->device_id, dentry);
21638c2ecf20Sopenharmony_ci	if (item) {
21648c2ecf20Sopenharmony_ci		remote_file_revalidate_item(dentry, con, item, relative_path);
21658c2ecf20Sopenharmony_ci		kref_put(&item->ref, release_cache_item);
21668c2ecf20Sopenharmony_ci		goto out_unlock;
21678c2ecf20Sopenharmony_ci	}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	cfn = find_cfn(sbi, con->cid, relative_path, false);
21708c2ecf20Sopenharmony_ci	if (cfn) {
21718c2ecf20Sopenharmony_ci		remote_file_revalidate_cfn(dentry, con, cfn, relative_path);
21728c2ecf20Sopenharmony_ci		release_cfn(cfn);
21738c2ecf20Sopenharmony_ci		goto out_unlock;
21748c2ecf20Sopenharmony_ci	}
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	filp = hmdfs_get_new_dentry_file(con, relative_path, NULL);
21778c2ecf20Sopenharmony_ci	if (IS_ERR(filp)) {
21788c2ecf20Sopenharmony_ci		err = PTR_ERR(filp);
21798c2ecf20Sopenharmony_ci		goto out_unlock;
21808c2ecf20Sopenharmony_ci	}
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	err = hmdfs_add_file_to_cache(dentry, con, filp, relative_path);
21838c2ecf20Sopenharmony_ci	if (unlikely(err))
21848c2ecf20Sopenharmony_ci		hmdfs_err("add cache list failed devid:%lu err:%d",
21858c2ecf20Sopenharmony_ci			  (unsigned long)con->device_id, err);
21868c2ecf20Sopenharmony_ci	fput(filp);
21878c2ecf20Sopenharmony_ci
21888c2ecf20Sopenharmony_ciout_unlock:
21898c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->cache_pull_lock);
21908c2ecf20Sopenharmony_ci	if (err && err != -ENOENT)
21918c2ecf20Sopenharmony_ci		hmdfs_err("readdir failed dev:%lu err:%d",
21928c2ecf20Sopenharmony_ci			  (unsigned long)con->device_id, err);
21938c2ecf20Sopenharmony_ci	kfree(relative_path);
21948c2ecf20Sopenharmony_ci	return true;
21958c2ecf20Sopenharmony_ci}
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ciint hmdfs_file_type(const char *name)
21988c2ecf20Sopenharmony_ci{
21998c2ecf20Sopenharmony_ci	if (!name)
22008c2ecf20Sopenharmony_ci		return -EINVAL;
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_ci	if (!strcmp(name, CURRENT_DIR) || !strcmp(name, PARENT_DIR))
22038c2ecf20Sopenharmony_ci		return HMDFS_TYPE_DOT;
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci	return HMDFS_TYPE_COMMON;
22068c2ecf20Sopenharmony_ci}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_cistruct clearcache_item *hmdfs_find_cache_item(uint64_t dev_id,
22098c2ecf20Sopenharmony_ci					      struct dentry *dentry)
22108c2ecf20Sopenharmony_ci{
22118c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
22128c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	if (!d_info)
22158c2ecf20Sopenharmony_ci		return NULL;
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci	spin_lock(&d_info->cache_list_lock);
22188c2ecf20Sopenharmony_ci	list_for_each_entry(item, &(d_info->cache_list_head), list) {
22198c2ecf20Sopenharmony_ci		if (dev_id == item->dev_id) {
22208c2ecf20Sopenharmony_ci			kref_get(&item->ref);
22218c2ecf20Sopenharmony_ci			spin_unlock(&d_info->cache_list_lock);
22228c2ecf20Sopenharmony_ci			return item;
22238c2ecf20Sopenharmony_ci		}
22248c2ecf20Sopenharmony_ci	}
22258c2ecf20Sopenharmony_ci	spin_unlock(&d_info->cache_list_lock);
22268c2ecf20Sopenharmony_ci	return NULL;
22278c2ecf20Sopenharmony_ci}
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_cibool hmdfs_cache_revalidate(unsigned long conn_time, uint64_t dev_id,
22308c2ecf20Sopenharmony_ci			    struct dentry *dentry)
22318c2ecf20Sopenharmony_ci{
22328c2ecf20Sopenharmony_ci	bool ret = false;
22338c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
22348c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
22358c2ecf20Sopenharmony_ci	unsigned int timeout;
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	if (!d_info)
22388c2ecf20Sopenharmony_ci		return ret;
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	timeout = hmdfs_sb(dentry->d_sb)->dcache_timeout;
22418c2ecf20Sopenharmony_ci	spin_lock(&d_info->cache_list_lock);
22428c2ecf20Sopenharmony_ci	list_for_each_entry(item, &(d_info->cache_list_head), list) {
22438c2ecf20Sopenharmony_ci		if (dev_id == item->dev_id) {
22448c2ecf20Sopenharmony_ci			ret = cache_item_revalidate(conn_time, item->time,
22458c2ecf20Sopenharmony_ci						    timeout);
22468c2ecf20Sopenharmony_ci			break;
22478c2ecf20Sopenharmony_ci		}
22488c2ecf20Sopenharmony_ci	}
22498c2ecf20Sopenharmony_ci	spin_unlock(&d_info->cache_list_lock);
22508c2ecf20Sopenharmony_ci	return ret;
22518c2ecf20Sopenharmony_ci}
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_civoid remove_cache_item(struct clearcache_item *item)
22548c2ecf20Sopenharmony_ci{
22558c2ecf20Sopenharmony_ci	bool deleted;
22568c2ecf20Sopenharmony_ci
22578c2ecf20Sopenharmony_ci	spin_lock(&item->d_info->cache_list_lock);
22588c2ecf20Sopenharmony_ci	deleted = list_empty(&item->list);
22598c2ecf20Sopenharmony_ci	if (!deleted)
22608c2ecf20Sopenharmony_ci		list_del_init(&item->list);
22618c2ecf20Sopenharmony_ci	spin_unlock(&item->d_info->cache_list_lock);
22628c2ecf20Sopenharmony_ci	if (!deleted)
22638c2ecf20Sopenharmony_ci		kref_put(&item->ref, release_cache_item);
22648c2ecf20Sopenharmony_ci}
22658c2ecf20Sopenharmony_ci
22668c2ecf20Sopenharmony_civoid release_cache_item(struct kref *ref)
22678c2ecf20Sopenharmony_ci{
22688c2ecf20Sopenharmony_ci	struct clearcache_item *item =
22698c2ecf20Sopenharmony_ci		container_of(ref, struct clearcache_item, ref);
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	if (item->filp)
22728c2ecf20Sopenharmony_ci		fput(item->filp);
22738c2ecf20Sopenharmony_ci	kfree(item);
22748c2ecf20Sopenharmony_ci}
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_civoid hmdfs_remove_cache_filp(struct hmdfs_peer *con, struct dentry *dentry)
22778c2ecf20Sopenharmony_ci{
22788c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
22798c2ecf20Sopenharmony_ci	struct clearcache_item *item_temp = NULL;
22808c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
22818c2ecf20Sopenharmony_ci	//	struct path *lower_path = NULL;
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci	if (!d_info)
22848c2ecf20Sopenharmony_ci		return;
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	spin_lock(&d_info->cache_list_lock);
22878c2ecf20Sopenharmony_ci	list_for_each_entry_safe(item, item_temp, &(d_info->cache_list_head),
22888c2ecf20Sopenharmony_ci				  list) {
22898c2ecf20Sopenharmony_ci		if (con->device_id == item->dev_id) {
22908c2ecf20Sopenharmony_ci			list_del_init(&item->list);
22918c2ecf20Sopenharmony_ci			spin_unlock(&d_info->cache_list_lock);
22928c2ecf20Sopenharmony_ci			cache_file_delete_by_dentry(con, dentry);
22938c2ecf20Sopenharmony_ci			kref_put(&item->ref, release_cache_item);
22948c2ecf20Sopenharmony_ci			return;
22958c2ecf20Sopenharmony_ci		}
22968c2ecf20Sopenharmony_ci	}
22978c2ecf20Sopenharmony_ci	spin_unlock(&d_info->cache_list_lock);
22988c2ecf20Sopenharmony_ci}
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ciint hmdfs_add_cache_list(uint64_t dev_id, struct dentry *dentry,
23018c2ecf20Sopenharmony_ci			 struct file *filp)
23028c2ecf20Sopenharmony_ci{
23038c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
23048c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	if (!d_info)
23078c2ecf20Sopenharmony_ci		return -ENOMEM;
23088c2ecf20Sopenharmony_ci
23098c2ecf20Sopenharmony_ci	item = kzalloc(sizeof(*item), GFP_KERNEL);
23108c2ecf20Sopenharmony_ci	if (!item)
23118c2ecf20Sopenharmony_ci		return -ENOMEM;
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci	item->dev_id = dev_id;
23148c2ecf20Sopenharmony_ci	item->filp = get_file(filp);
23158c2ecf20Sopenharmony_ci	item->time = jiffies;
23168c2ecf20Sopenharmony_ci	item->d_info = d_info;
23178c2ecf20Sopenharmony_ci	kref_init(&item->ref);
23188c2ecf20Sopenharmony_ci	spin_lock(&d_info->cache_list_lock);
23198c2ecf20Sopenharmony_ci	list_add_tail(&(item->list), &(d_info->cache_list_head));
23208c2ecf20Sopenharmony_ci	spin_unlock(&d_info->cache_list_lock);
23218c2ecf20Sopenharmony_ci	return 0;
23228c2ecf20Sopenharmony_ci}
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_civoid hmdfs_add_remote_cache_list(struct hmdfs_peer *con, const char *dir_path)
23258c2ecf20Sopenharmony_ci{
23268c2ecf20Sopenharmony_ci	int err = 0;
23278c2ecf20Sopenharmony_ci	struct remotecache_item *item = NULL;
23288c2ecf20Sopenharmony_ci	struct remotecache_item *item_temp = NULL;
23298c2ecf20Sopenharmony_ci	struct path path, root_path;
23308c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = NULL;
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	err = kern_path(con->sbi->local_dst, 0, &root_path);
23338c2ecf20Sopenharmony_ci	if (err) {
23348c2ecf20Sopenharmony_ci		hmdfs_err("kern_path failed err = %d", err);
23358c2ecf20Sopenharmony_ci		return;
23368c2ecf20Sopenharmony_ci	}
23378c2ecf20Sopenharmony_ci
23388c2ecf20Sopenharmony_ci	err = vfs_path_lookup(root_path.dentry, root_path.mnt, dir_path, 0,
23398c2ecf20Sopenharmony_ci			      &path);
23408c2ecf20Sopenharmony_ci	if (err)
23418c2ecf20Sopenharmony_ci		goto out_put_root;
23428c2ecf20Sopenharmony_ci
23438c2ecf20Sopenharmony_ci	d_info = hmdfs_d(path.dentry);
23448c2ecf20Sopenharmony_ci	if (!d_info) {
23458c2ecf20Sopenharmony_ci		err = -EINVAL;
23468c2ecf20Sopenharmony_ci		goto out;
23478c2ecf20Sopenharmony_ci	}
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci	/* find duplicate con */
23508c2ecf20Sopenharmony_ci	mutex_lock(&d_info->remote_cache_list_lock);
23518c2ecf20Sopenharmony_ci	list_for_each_entry_safe(item, item_temp,
23528c2ecf20Sopenharmony_ci				  &(d_info->remote_cache_list_head), list) {
23538c2ecf20Sopenharmony_ci		if (item->con->device_id == con->device_id) {
23548c2ecf20Sopenharmony_ci			mutex_unlock(&d_info->remote_cache_list_lock);
23558c2ecf20Sopenharmony_ci			goto out;
23568c2ecf20Sopenharmony_ci		}
23578c2ecf20Sopenharmony_ci	}
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci	item = kzalloc(sizeof(*item), GFP_KERNEL);
23608c2ecf20Sopenharmony_ci	if (!item) {
23618c2ecf20Sopenharmony_ci		err = -ENOMEM;
23628c2ecf20Sopenharmony_ci		mutex_unlock(&d_info->remote_cache_list_lock);
23638c2ecf20Sopenharmony_ci		goto out;
23648c2ecf20Sopenharmony_ci	}
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci	item->con = con;
23678c2ecf20Sopenharmony_ci	item->drop_flag = 0;
23688c2ecf20Sopenharmony_ci	list_add(&(item->list), &(d_info->remote_cache_list_head));
23698c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->remote_cache_list_lock);
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ciout:
23728c2ecf20Sopenharmony_ci	path_put(&path);
23738c2ecf20Sopenharmony_ciout_put_root:
23748c2ecf20Sopenharmony_ci	path_put(&root_path);
23758c2ecf20Sopenharmony_ci}
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ciint hmdfs_drop_remote_cache_dents(struct dentry *dentry)
23788c2ecf20Sopenharmony_ci{
23798c2ecf20Sopenharmony_ci	struct path lower_path;
23808c2ecf20Sopenharmony_ci	struct inode *lower_inode = NULL;
23818c2ecf20Sopenharmony_ci	struct remotecache_item *item = NULL;
23828c2ecf20Sopenharmony_ci	struct remotecache_item *item_temp = NULL;
23838c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = NULL;
23848c2ecf20Sopenharmony_ci	char *relative_path = NULL;
23858c2ecf20Sopenharmony_ci
23868c2ecf20Sopenharmony_ci	if (!dentry) {
23878c2ecf20Sopenharmony_ci		hmdfs_err("dentry null and return");
23888c2ecf20Sopenharmony_ci		return 0;
23898c2ecf20Sopenharmony_ci	}
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	d_info = hmdfs_d(dentry);
23928c2ecf20Sopenharmony_ci	if (!d_info) {
23938c2ecf20Sopenharmony_ci		hmdfs_err("d_info null and return");
23948c2ecf20Sopenharmony_ci		return 0;
23958c2ecf20Sopenharmony_ci	}
23968c2ecf20Sopenharmony_ci	hmdfs_get_lower_path(dentry, &lower_path);
23978c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(lower_path.dentry)) {
23988c2ecf20Sopenharmony_ci		hmdfs_put_lower_path(&lower_path);
23998c2ecf20Sopenharmony_ci		return 0;
24008c2ecf20Sopenharmony_ci	}
24018c2ecf20Sopenharmony_ci	lower_inode = d_inode(lower_path.dentry);
24028c2ecf20Sopenharmony_ci	hmdfs_put_lower_path(&lower_path);
24038c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(lower_inode))
24048c2ecf20Sopenharmony_ci		return 0;
24058c2ecf20Sopenharmony_ci	/* only for directory */
24068c2ecf20Sopenharmony_ci	if (!S_ISDIR(lower_inode->i_mode))
24078c2ecf20Sopenharmony_ci		return 0;
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	relative_path = hmdfs_get_dentry_relative_path(dentry);
24108c2ecf20Sopenharmony_ci	if (!relative_path) {
24118c2ecf20Sopenharmony_ci		hmdfs_err("get dentry relative path failed");
24128c2ecf20Sopenharmony_ci		return 0;
24138c2ecf20Sopenharmony_ci	}
24148c2ecf20Sopenharmony_ci	mutex_lock(&d_info->remote_cache_list_lock);
24158c2ecf20Sopenharmony_ci	list_for_each_entry_safe(item, item_temp,
24168c2ecf20Sopenharmony_ci				  &(d_info->remote_cache_list_head), list) {
24178c2ecf20Sopenharmony_ci		if (item->drop_flag) {
24188c2ecf20Sopenharmony_ci			item->drop_flag = 0;
24198c2ecf20Sopenharmony_ci			continue;
24208c2ecf20Sopenharmony_ci		}
24218c2ecf20Sopenharmony_ci		mutex_unlock(&d_info->remote_cache_list_lock);
24228c2ecf20Sopenharmony_ci		hmdfs_send_drop_push(item->con, relative_path);
24238c2ecf20Sopenharmony_ci		mutex_lock(&d_info->remote_cache_list_lock);
24248c2ecf20Sopenharmony_ci		list_del(&item->list);
24258c2ecf20Sopenharmony_ci		kfree(item);
24268c2ecf20Sopenharmony_ci	}
24278c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->remote_cache_list_lock);
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	kfree(relative_path);
24308c2ecf20Sopenharmony_ci	return 0;
24318c2ecf20Sopenharmony_ci}
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci/* Clear the dentry cache files of target directory */
24348c2ecf20Sopenharmony_ciint hmdfs_clear_cache_dents(struct dentry *dentry, bool remove_cache)
24358c2ecf20Sopenharmony_ci{
24368c2ecf20Sopenharmony_ci	struct clearcache_item *item = NULL;
24378c2ecf20Sopenharmony_ci	struct clearcache_item *item_temp = NULL;
24388c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = hmdfs_d(dentry);
24398c2ecf20Sopenharmony_ci	char *path = NULL;
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_ci	if (!d_info)
24428c2ecf20Sopenharmony_ci		return 0;
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_ci	spin_lock(&d_info->cache_list_lock);
24458c2ecf20Sopenharmony_ci	list_for_each_entry_safe(item, item_temp, &(d_info->cache_list_head),
24468c2ecf20Sopenharmony_ci				  list) {
24478c2ecf20Sopenharmony_ci		list_del_init(&item->list);
24488c2ecf20Sopenharmony_ci		kref_put(&item->ref, release_cache_item);
24498c2ecf20Sopenharmony_ci	}
24508c2ecf20Sopenharmony_ci	spin_unlock(&d_info->cache_list_lock);
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci	if (!remove_cache)
24538c2ecf20Sopenharmony_ci		return 0;
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_ci	/* it also need confirm that there are no dentryfile_dev*
24568c2ecf20Sopenharmony_ci	 * under this dentry
24578c2ecf20Sopenharmony_ci	 */
24588c2ecf20Sopenharmony_ci	path = hmdfs_get_dentry_relative_path(dentry);
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci	if (unlikely(!path)) {
24618c2ecf20Sopenharmony_ci		hmdfs_err("get relative path failed");
24628c2ecf20Sopenharmony_ci		return 0;
24638c2ecf20Sopenharmony_ci	}
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	cache_file_destroy_by_path(hmdfs_sb(dentry->d_sb), path);
24668c2ecf20Sopenharmony_ci
24678c2ecf20Sopenharmony_ci	kfree(path);
24688c2ecf20Sopenharmony_ci	return 0;
24698c2ecf20Sopenharmony_ci}
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_civoid hmdfs_mark_drop_flag(uint64_t device_id, struct dentry *dentry)
24728c2ecf20Sopenharmony_ci{
24738c2ecf20Sopenharmony_ci	struct remotecache_item *item = NULL;
24748c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = NULL;
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	d_info = hmdfs_d(dentry);
24778c2ecf20Sopenharmony_ci	if (!d_info) {
24788c2ecf20Sopenharmony_ci		hmdfs_err("d_info null and return");
24798c2ecf20Sopenharmony_ci		return;
24808c2ecf20Sopenharmony_ci	}
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci	mutex_lock(&d_info->remote_cache_list_lock);
24838c2ecf20Sopenharmony_ci	list_for_each_entry(item, &(d_info->remote_cache_list_head), list) {
24848c2ecf20Sopenharmony_ci		if (item->con->device_id == device_id) {
24858c2ecf20Sopenharmony_ci			item->drop_flag = 1;
24868c2ecf20Sopenharmony_ci			break;
24878c2ecf20Sopenharmony_ci		}
24888c2ecf20Sopenharmony_ci	}
24898c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->remote_cache_list_lock);
24908c2ecf20Sopenharmony_ci}
24918c2ecf20Sopenharmony_ci
24928c2ecf20Sopenharmony_civoid hmdfs_clear_drop_flag(struct dentry *dentry)
24938c2ecf20Sopenharmony_ci{
24948c2ecf20Sopenharmony_ci	struct remotecache_item *item = NULL;
24958c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *d_info = NULL;
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_ci	if (!dentry) {
24988c2ecf20Sopenharmony_ci		hmdfs_err("dentry null and return");
24998c2ecf20Sopenharmony_ci		return;
25008c2ecf20Sopenharmony_ci	}
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	d_info = hmdfs_d(dentry);
25038c2ecf20Sopenharmony_ci	if (!d_info) {
25048c2ecf20Sopenharmony_ci		hmdfs_err("d_info null and return");
25058c2ecf20Sopenharmony_ci		return;
25068c2ecf20Sopenharmony_ci	}
25078c2ecf20Sopenharmony_ci
25088c2ecf20Sopenharmony_ci	mutex_lock(&d_info->remote_cache_list_lock);
25098c2ecf20Sopenharmony_ci	list_for_each_entry(item, &(d_info->remote_cache_list_head), list) {
25108c2ecf20Sopenharmony_ci		if (item->drop_flag)
25118c2ecf20Sopenharmony_ci			item->drop_flag = 0;
25128c2ecf20Sopenharmony_ci	}
25138c2ecf20Sopenharmony_ci	mutex_unlock(&d_info->remote_cache_list_lock);
25148c2ecf20Sopenharmony_ci}
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci#define DUSTBIN_SUFFIX ".hwbk"
25178c2ecf20Sopenharmony_cistatic void hmdfs_rename_bak(struct dentry *dentry)
25188c2ecf20Sopenharmony_ci{
25198c2ecf20Sopenharmony_ci	struct path lower_path;
25208c2ecf20Sopenharmony_ci	struct dentry *lower_parent = NULL;
25218c2ecf20Sopenharmony_ci	struct dentry *lower_dentry = NULL;
25228c2ecf20Sopenharmony_ci	struct dentry *new_dentry = NULL;
25238c2ecf20Sopenharmony_ci	char *name = NULL;
25248c2ecf20Sopenharmony_ci	int len = 0;
25258c2ecf20Sopenharmony_ci	int err = 0;
25268c2ecf20Sopenharmony_ci
25278c2ecf20Sopenharmony_ci	hmdfs_get_lower_path(dentry, &lower_path);
25288c2ecf20Sopenharmony_ci	lower_dentry = lower_path.dentry;
25298c2ecf20Sopenharmony_ci	len = strlen(lower_dentry->d_name.name) + strlen(DUSTBIN_SUFFIX) + 2;
25308c2ecf20Sopenharmony_ci	if (len >= NAME_MAX) {
25318c2ecf20Sopenharmony_ci		err = -ENAMETOOLONG;
25328c2ecf20Sopenharmony_ci		goto put_lower_path;
25338c2ecf20Sopenharmony_ci	}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	name = kmalloc(len, GFP_KERNEL);
25368c2ecf20Sopenharmony_ci	if (!name) {
25378c2ecf20Sopenharmony_ci		err = -ENOMEM;
25388c2ecf20Sopenharmony_ci		goto put_lower_path;
25398c2ecf20Sopenharmony_ci	}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	snprintf(name, len, ".%s%s", lower_dentry->d_name.name, DUSTBIN_SUFFIX);
25428c2ecf20Sopenharmony_ci	err = mnt_want_write(lower_path.mnt);
25438c2ecf20Sopenharmony_ci	if (err) {
25448c2ecf20Sopenharmony_ci		hmdfs_info("get write access failed, err %d", err);
25458c2ecf20Sopenharmony_ci		goto free_name;
25468c2ecf20Sopenharmony_ci	}
25478c2ecf20Sopenharmony_ci
25488c2ecf20Sopenharmony_ci	lower_parent = lock_parent(lower_dentry);
25498c2ecf20Sopenharmony_ci	new_dentry = lookup_one_len(name, lower_parent, strlen(name));
25508c2ecf20Sopenharmony_ci	if (IS_ERR(new_dentry)) {
25518c2ecf20Sopenharmony_ci		err = PTR_ERR(new_dentry);
25528c2ecf20Sopenharmony_ci		hmdfs_info("lookup new dentry failed, err %d", err);
25538c2ecf20Sopenharmony_ci		goto unlock_parent;
25548c2ecf20Sopenharmony_ci	}
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_ci	err = vfs_rename(d_inode(lower_parent), lower_dentry,
25578c2ecf20Sopenharmony_ci			 d_inode(lower_parent), new_dentry, NULL, 0);
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	dput(new_dentry);
25608c2ecf20Sopenharmony_ciunlock_parent:
25618c2ecf20Sopenharmony_ci	unlock_dir(lower_parent);
25628c2ecf20Sopenharmony_ci	mnt_drop_write(lower_path.mnt);
25638c2ecf20Sopenharmony_cifree_name:
25648c2ecf20Sopenharmony_ci	kfree(name);
25658c2ecf20Sopenharmony_ciput_lower_path:
25668c2ecf20Sopenharmony_ci	hmdfs_put_lower_path(&lower_path);
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	if (err)
25698c2ecf20Sopenharmony_ci		hmdfs_err("failed to rename file, err %d", err);
25708c2ecf20Sopenharmony_ci}
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ciint hmdfs_root_unlink(uint64_t device_id, struct path *root_path,
25738c2ecf20Sopenharmony_ci		      const char *unlink_dir, const char *unlink_name)
25748c2ecf20Sopenharmony_ci{
25758c2ecf20Sopenharmony_ci	int err = 0;
25768c2ecf20Sopenharmony_ci	struct path path;
25778c2ecf20Sopenharmony_ci	struct dentry *child_dentry = NULL;
25788c2ecf20Sopenharmony_ci	struct inode *dir = NULL;
25798c2ecf20Sopenharmony_ci	struct inode *child_inode = NULL;
25808c2ecf20Sopenharmony_ci	kuid_t tmp_uid;
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci	err = vfs_path_lookup(root_path->dentry, root_path->mnt,
25838c2ecf20Sopenharmony_ci			      unlink_dir, LOOKUP_DIRECTORY, &path);
25848c2ecf20Sopenharmony_ci	if (err) {
25858c2ecf20Sopenharmony_ci		hmdfs_err("found path failed err = %d", err);
25868c2ecf20Sopenharmony_ci		return err;
25878c2ecf20Sopenharmony_ci	}
25888c2ecf20Sopenharmony_ci	dir = d_inode(path.dentry);
25898c2ecf20Sopenharmony_ci	inode_lock_nested(dir, I_MUTEX_PARENT);
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	child_dentry = lookup_one_len(unlink_name, path.dentry,
25928c2ecf20Sopenharmony_ci				      strlen(unlink_name));
25938c2ecf20Sopenharmony_ci	if (IS_ERR(child_dentry)) {
25948c2ecf20Sopenharmony_ci		err = PTR_ERR(child_dentry);
25958c2ecf20Sopenharmony_ci		hmdfs_err("lookup_one_len failed, err = %d", err);
25968c2ecf20Sopenharmony_ci		goto unlock_out;
25978c2ecf20Sopenharmony_ci	}
25988c2ecf20Sopenharmony_ci	if (d_is_negative(child_dentry)) {
25998c2ecf20Sopenharmony_ci		err = -ENOENT;
26008c2ecf20Sopenharmony_ci		dput(child_dentry);
26018c2ecf20Sopenharmony_ci		goto unlock_out;
26028c2ecf20Sopenharmony_ci	}
26038c2ecf20Sopenharmony_ci	child_inode = d_inode(child_dentry);
26048c2ecf20Sopenharmony_ci	if (!child_inode)
26058c2ecf20Sopenharmony_ci		goto unlock_out;
26068c2ecf20Sopenharmony_ci
26078c2ecf20Sopenharmony_ci	tmp_uid = hmdfs_override_inode_uid(dir);
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	hmdfs_mark_drop_flag(device_id, path.dentry);
26108c2ecf20Sopenharmony_ci	ihold(child_inode);
26118c2ecf20Sopenharmony_ci	err = vfs_unlink(dir, child_dentry, NULL);
26128c2ecf20Sopenharmony_ci	/*
26138c2ecf20Sopenharmony_ci	 * -EOWNERDEAD means we want to put the file in a specail dir instead of
26148c2ecf20Sopenharmony_ci	 *  deleting it, specifically dustbin in phone, so that user can
26158c2ecf20Sopenharmony_ci	 *  recover the deleted images and videos.
26168c2ecf20Sopenharmony_ci	 */
26178c2ecf20Sopenharmony_ci	if (err == -EOWNERDEAD) {
26188c2ecf20Sopenharmony_ci		hmdfs_rename_bak(child_dentry);
26198c2ecf20Sopenharmony_ci		err = 0;
26208c2ecf20Sopenharmony_ci	}
26218c2ecf20Sopenharmony_ci	if (err)
26228c2ecf20Sopenharmony_ci		hmdfs_err("unlink path failed err = %d", err);
26238c2ecf20Sopenharmony_ci	hmdfs_revert_inode_uid(dir, tmp_uid);
26248c2ecf20Sopenharmony_ci	dput(child_dentry);
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ciunlock_out:
26278c2ecf20Sopenharmony_ci	inode_unlock(dir);
26288c2ecf20Sopenharmony_ci	if (child_inode)
26298c2ecf20Sopenharmony_ci		iput(child_inode);
26308c2ecf20Sopenharmony_ci	path_put(&path);
26318c2ecf20Sopenharmony_ci	return err;
26328c2ecf20Sopenharmony_ci}
26338c2ecf20Sopenharmony_ci
26348c2ecf20Sopenharmony_cistruct dentry *hmdfs_root_mkdir(uint64_t device_id, const char *local_dst_path,
26358c2ecf20Sopenharmony_ci				const char *mkdir_dir, const char *mkdir_name,
26368c2ecf20Sopenharmony_ci				umode_t mode)
26378c2ecf20Sopenharmony_ci{
26388c2ecf20Sopenharmony_ci	int err;
26398c2ecf20Sopenharmony_ci	struct path path;
26408c2ecf20Sopenharmony_ci	struct dentry *child_dentry = NULL;
26418c2ecf20Sopenharmony_ci	struct dentry *ret = NULL;
26428c2ecf20Sopenharmony_ci	char *mkdir_path = NULL;
26438c2ecf20Sopenharmony_ci	char *mkdir_abs_path = NULL;
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ci	mkdir_path = hmdfs_connect_path(mkdir_dir, mkdir_name);
26468c2ecf20Sopenharmony_ci	if (!mkdir_path)
26478c2ecf20Sopenharmony_ci		return ERR_PTR(-EACCES);
26488c2ecf20Sopenharmony_ci
26498c2ecf20Sopenharmony_ci	mkdir_abs_path =
26508c2ecf20Sopenharmony_ci		hmdfs_get_dentry_absolute_path(local_dst_path, mkdir_path);
26518c2ecf20Sopenharmony_ci	if (!mkdir_abs_path) {
26528c2ecf20Sopenharmony_ci		ret = ERR_PTR(-ENOMEM);
26538c2ecf20Sopenharmony_ci		goto out;
26548c2ecf20Sopenharmony_ci	}
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	child_dentry = kern_path_create(AT_FDCWD, mkdir_abs_path,
26578c2ecf20Sopenharmony_ci					&path, LOOKUP_DIRECTORY);
26588c2ecf20Sopenharmony_ci	if (IS_ERR(child_dentry)) {
26598c2ecf20Sopenharmony_ci		ret = child_dentry;
26608c2ecf20Sopenharmony_ci		goto out;
26618c2ecf20Sopenharmony_ci	}
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_ci	hmdfs_mark_drop_flag(device_id, child_dentry->d_parent);
26648c2ecf20Sopenharmony_ci	err = vfs_mkdir(d_inode(path.dentry), child_dentry, mode);
26658c2ecf20Sopenharmony_ci	if (err) {
26668c2ecf20Sopenharmony_ci		hmdfs_err("mkdir failed! err=%d", err);
26678c2ecf20Sopenharmony_ci		ret = ERR_PTR(err);
26688c2ecf20Sopenharmony_ci		goto out_put;
26698c2ecf20Sopenharmony_ci	}
26708c2ecf20Sopenharmony_ci	ret = dget(child_dentry);
26718c2ecf20Sopenharmony_ciout_put:
26728c2ecf20Sopenharmony_ci	done_path_create(&path, child_dentry);
26738c2ecf20Sopenharmony_ciout:
26748c2ecf20Sopenharmony_ci	kfree(mkdir_path);
26758c2ecf20Sopenharmony_ci	kfree(mkdir_abs_path);
26768c2ecf20Sopenharmony_ci	return ret;
26778c2ecf20Sopenharmony_ci}
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_cistruct dentry *hmdfs_root_create(uint64_t device_id, const char *local_dst_path,
26808c2ecf20Sopenharmony_ci				 const char *create_dir,
26818c2ecf20Sopenharmony_ci				 const char *create_name,
26828c2ecf20Sopenharmony_ci				 umode_t mode, bool want_excl)
26838c2ecf20Sopenharmony_ci{
26848c2ecf20Sopenharmony_ci	int err;
26858c2ecf20Sopenharmony_ci	struct path path;
26868c2ecf20Sopenharmony_ci	struct dentry *child_dentry = NULL;
26878c2ecf20Sopenharmony_ci	struct dentry *ret = NULL;
26888c2ecf20Sopenharmony_ci	char *create_path = NULL;
26898c2ecf20Sopenharmony_ci	char *create_abs_path = NULL;
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_ci	create_path = hmdfs_connect_path(create_dir, create_name);
26928c2ecf20Sopenharmony_ci	if (!create_path)
26938c2ecf20Sopenharmony_ci		return ERR_PTR(-EACCES);
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	create_abs_path =
26968c2ecf20Sopenharmony_ci		hmdfs_get_dentry_absolute_path(local_dst_path, create_path);
26978c2ecf20Sopenharmony_ci	if (!create_abs_path) {
26988c2ecf20Sopenharmony_ci		ret = ERR_PTR(-ENOMEM);
26998c2ecf20Sopenharmony_ci		goto out;
27008c2ecf20Sopenharmony_ci	}
27018c2ecf20Sopenharmony_ci
27028c2ecf20Sopenharmony_ci	child_dentry = kern_path_create(AT_FDCWD, create_abs_path, &path, 0);
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	if (IS_ERR(child_dentry)) {
27058c2ecf20Sopenharmony_ci		ret = child_dentry;
27068c2ecf20Sopenharmony_ci		goto out;
27078c2ecf20Sopenharmony_ci	}
27088c2ecf20Sopenharmony_ci	hmdfs_mark_drop_flag(device_id, child_dentry->d_parent);
27098c2ecf20Sopenharmony_ci	err = vfs_create(d_inode(path.dentry), child_dentry, mode, want_excl);
27108c2ecf20Sopenharmony_ci	if (err) {
27118c2ecf20Sopenharmony_ci		hmdfs_err("path create failed! err=%d", err);
27128c2ecf20Sopenharmony_ci		ret = ERR_PTR(err);
27138c2ecf20Sopenharmony_ci		goto out_put;
27148c2ecf20Sopenharmony_ci	}
27158c2ecf20Sopenharmony_ci	ret = dget(child_dentry);
27168c2ecf20Sopenharmony_ciout_put:
27178c2ecf20Sopenharmony_ci	done_path_create(&path, child_dentry);
27188c2ecf20Sopenharmony_ciout:
27198c2ecf20Sopenharmony_ci	kfree(create_path);
27208c2ecf20Sopenharmony_ci	kfree(create_abs_path);
27218c2ecf20Sopenharmony_ci	return ret;
27228c2ecf20Sopenharmony_ci}
27238c2ecf20Sopenharmony_ci
27248c2ecf20Sopenharmony_ciint hmdfs_root_rmdir(uint64_t device_id, struct path *root_path,
27258c2ecf20Sopenharmony_ci		     const char *rmdir_dir, const char *rmdir_name)
27268c2ecf20Sopenharmony_ci{
27278c2ecf20Sopenharmony_ci	int err = 0;
27288c2ecf20Sopenharmony_ci	struct path path;
27298c2ecf20Sopenharmony_ci	struct dentry *child_dentry = NULL;
27308c2ecf20Sopenharmony_ci	struct inode *dir = NULL;
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	err = vfs_path_lookup(root_path->dentry, root_path->mnt,
27338c2ecf20Sopenharmony_ci			      rmdir_dir, LOOKUP_DIRECTORY, &path);
27348c2ecf20Sopenharmony_ci	if (err) {
27358c2ecf20Sopenharmony_ci		hmdfs_err("found path failed err = %d", err);
27368c2ecf20Sopenharmony_ci		return err;
27378c2ecf20Sopenharmony_ci	}
27388c2ecf20Sopenharmony_ci	dir = d_inode(path.dentry);
27398c2ecf20Sopenharmony_ci	inode_lock_nested(dir, I_MUTEX_PARENT);
27408c2ecf20Sopenharmony_ci
27418c2ecf20Sopenharmony_ci	child_dentry = lookup_one_len(rmdir_name, path.dentry,
27428c2ecf20Sopenharmony_ci				      strlen(rmdir_name));
27438c2ecf20Sopenharmony_ci	if (IS_ERR(child_dentry)) {
27448c2ecf20Sopenharmony_ci		err = PTR_ERR(child_dentry);
27458c2ecf20Sopenharmony_ci		hmdfs_err("lookup_one_len failed, err = %d", err);
27468c2ecf20Sopenharmony_ci		goto unlock_out;
27478c2ecf20Sopenharmony_ci	}
27488c2ecf20Sopenharmony_ci	if (d_is_negative(child_dentry)) {
27498c2ecf20Sopenharmony_ci		err = -ENOENT;
27508c2ecf20Sopenharmony_ci		dput(child_dentry);
27518c2ecf20Sopenharmony_ci		goto unlock_out;
27528c2ecf20Sopenharmony_ci	}
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	hmdfs_mark_drop_flag(device_id, path.dentry);
27558c2ecf20Sopenharmony_ci	err = vfs_rmdir(dir, child_dentry);
27568c2ecf20Sopenharmony_ci	if (err)
27578c2ecf20Sopenharmony_ci		hmdfs_err("rmdir failed err = %d", err);
27588c2ecf20Sopenharmony_ci	dput(child_dentry);
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ciunlock_out:
27618c2ecf20Sopenharmony_ci	inode_unlock(dir);
27628c2ecf20Sopenharmony_ci	path_put(&path);
27638c2ecf20Sopenharmony_ci	return err;
27648c2ecf20Sopenharmony_ci}
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ciint hmdfs_root_rename(struct hmdfs_sb_info *sbi, uint64_t device_id,
27678c2ecf20Sopenharmony_ci		      const char *oldpath, const char *oldname,
27688c2ecf20Sopenharmony_ci		      const char *newpath, const char *newname,
27698c2ecf20Sopenharmony_ci		      unsigned int flags)
27708c2ecf20Sopenharmony_ci{
27718c2ecf20Sopenharmony_ci	int err = 0;
27728c2ecf20Sopenharmony_ci	struct path path_dst;
27738c2ecf20Sopenharmony_ci	struct path path_old;
27748c2ecf20Sopenharmony_ci	struct path path_new;
27758c2ecf20Sopenharmony_ci	struct dentry *trap = NULL;
27768c2ecf20Sopenharmony_ci	struct dentry *old_dentry = NULL;
27778c2ecf20Sopenharmony_ci	struct dentry *new_dentry = NULL;
27788c2ecf20Sopenharmony_ci
27798c2ecf20Sopenharmony_ci	err = kern_path(sbi->local_dst, 0, &path_dst);
27808c2ecf20Sopenharmony_ci	if (err) {
27818c2ecf20Sopenharmony_ci		hmdfs_err("kern_path for local dst failed %d", err);
27828c2ecf20Sopenharmony_ci		return err;
27838c2ecf20Sopenharmony_ci	}
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_ci	err = vfs_path_lookup(path_dst.dentry, path_dst.mnt, oldpath, 0,
27868c2ecf20Sopenharmony_ci			      &path_old);
27878c2ecf20Sopenharmony_ci	if (err) {
27888c2ecf20Sopenharmony_ci		hmdfs_info("lookup oldpath from local_dst failed, err %d", err);
27898c2ecf20Sopenharmony_ci		goto put_path_dst;
27908c2ecf20Sopenharmony_ci	}
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci	err = vfs_path_lookup(path_dst.dentry, path_dst.mnt, newpath, 0,
27938c2ecf20Sopenharmony_ci			      &path_new);
27948c2ecf20Sopenharmony_ci	if (err) {
27958c2ecf20Sopenharmony_ci		hmdfs_info("lookup newpath from local_dst failed, err %d", err);
27968c2ecf20Sopenharmony_ci		goto put_path_old;
27978c2ecf20Sopenharmony_ci	}
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci	err = mnt_want_write(path_dst.mnt);
28008c2ecf20Sopenharmony_ci	if (err) {
28018c2ecf20Sopenharmony_ci		hmdfs_info("get write access failed for local_dst, err %d",
28028c2ecf20Sopenharmony_ci			   err);
28038c2ecf20Sopenharmony_ci		goto put_path_new;
28048c2ecf20Sopenharmony_ci	}
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	trap = lock_rename(path_new.dentry, path_old.dentry);
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	old_dentry = lookup_one_len(oldname, path_old.dentry, strlen(oldname));
28098c2ecf20Sopenharmony_ci	if (IS_ERR(old_dentry)) {
28108c2ecf20Sopenharmony_ci		err = PTR_ERR(old_dentry);
28118c2ecf20Sopenharmony_ci		hmdfs_info("lookup old dentry failed, err %d", err);
28128c2ecf20Sopenharmony_ci		goto unlock;
28138c2ecf20Sopenharmony_ci	}
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci	/* source should not be ancestor of target */
28168c2ecf20Sopenharmony_ci	if (old_dentry == trap) {
28178c2ecf20Sopenharmony_ci		err = -EINVAL;
28188c2ecf20Sopenharmony_ci		goto put_old_dentry;
28198c2ecf20Sopenharmony_ci	}
28208c2ecf20Sopenharmony_ci
28218c2ecf20Sopenharmony_ci	new_dentry = lookup_one_len(newname, path_new.dentry, strlen(newname));
28228c2ecf20Sopenharmony_ci	if (IS_ERR(new_dentry)) {
28238c2ecf20Sopenharmony_ci		err = PTR_ERR(new_dentry);
28248c2ecf20Sopenharmony_ci		hmdfs_info("lookup new dentry failed, err %d", err);
28258c2ecf20Sopenharmony_ci		goto put_old_dentry;
28268c2ecf20Sopenharmony_ci	}
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ci	/*
28298c2ecf20Sopenharmony_ci	 * Exchange rename is not supported, thus target should not be an
28308c2ecf20Sopenharmony_ci	 * ancestor of source.
28318c2ecf20Sopenharmony_ci	 */
28328c2ecf20Sopenharmony_ci	if (trap == new_dentry) {
28338c2ecf20Sopenharmony_ci		err = -ENOTEMPTY;
28348c2ecf20Sopenharmony_ci		goto put_new_dentry;
28358c2ecf20Sopenharmony_ci	}
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	if (d_is_positive(new_dentry) && (flags & RENAME_NOREPLACE)) {
28388c2ecf20Sopenharmony_ci		err = -EEXIST;
28398c2ecf20Sopenharmony_ci		goto put_new_dentry;
28408c2ecf20Sopenharmony_ci	}
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci	hmdfs_mark_drop_flag(device_id, path_old.dentry);
28438c2ecf20Sopenharmony_ci	if (path_old.dentry != path_new.dentry)
28448c2ecf20Sopenharmony_ci		hmdfs_mark_drop_flag(device_id, path_new.dentry);
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	err = vfs_rename(d_inode(path_old.dentry), old_dentry,
28478c2ecf20Sopenharmony_ci			 d_inode(path_new.dentry), new_dentry, NULL, 0);
28488c2ecf20Sopenharmony_ci
28498c2ecf20Sopenharmony_ciput_new_dentry:
28508c2ecf20Sopenharmony_ci	dput(new_dentry);
28518c2ecf20Sopenharmony_ciput_old_dentry:
28528c2ecf20Sopenharmony_ci	dput(old_dentry);
28538c2ecf20Sopenharmony_ciunlock:
28548c2ecf20Sopenharmony_ci	unlock_rename(path_new.dentry, path_old.dentry);
28558c2ecf20Sopenharmony_ci	mnt_drop_write(path_dst.mnt);
28568c2ecf20Sopenharmony_ciput_path_new:
28578c2ecf20Sopenharmony_ci	path_put(&path_new);
28588c2ecf20Sopenharmony_ciput_path_old:
28598c2ecf20Sopenharmony_ci	path_put(&path_old);
28608c2ecf20Sopenharmony_ciput_path_dst:
28618c2ecf20Sopenharmony_ci	path_put(&path_dst);
28628c2ecf20Sopenharmony_ci
28638c2ecf20Sopenharmony_ci	return err;
28648c2ecf20Sopenharmony_ci}
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ciint hmdfs_get_path_in_sb(struct super_block *sb, const char *name,
28678c2ecf20Sopenharmony_ci			 unsigned int flags, struct path *path)
28688c2ecf20Sopenharmony_ci{
28698c2ecf20Sopenharmony_ci	int err;
28708c2ecf20Sopenharmony_ci
28718c2ecf20Sopenharmony_ci	err = kern_path(name, flags, path);
28728c2ecf20Sopenharmony_ci	if (err) {
28738c2ecf20Sopenharmony_ci		hmdfs_err("can't get %s %d\n", name, err);
28748c2ecf20Sopenharmony_ci		return err;
28758c2ecf20Sopenharmony_ci	}
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci	/* should ensure the path is belong sb */
28788c2ecf20Sopenharmony_ci	if (path->dentry->d_sb != sb) {
28798c2ecf20Sopenharmony_ci		err = -EINVAL;
28808c2ecf20Sopenharmony_ci		hmdfs_err("Wrong sb: %s on %s", name,
28818c2ecf20Sopenharmony_ci			  path->dentry->d_sb->s_type->name);
28828c2ecf20Sopenharmony_ci		path_put(path);
28838c2ecf20Sopenharmony_ci	}
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci	return err;
28868c2ecf20Sopenharmony_ci}
2887