18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/hmdfs/inode_cloud.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/fs_stack.h>
98c2ecf20Sopenharmony_ci#include <linux/namei.h>
108c2ecf20Sopenharmony_ci#include <linux/xattr.h>
118c2ecf20Sopenharmony_ci#include <linux/string.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "comm/socket_adapter.h"
148c2ecf20Sopenharmony_ci#include "hmdfs.h"
158c2ecf20Sopenharmony_ci#include "hmdfs_client.h"
168c2ecf20Sopenharmony_ci#include "hmdfs_dentryfile.h"
178c2ecf20Sopenharmony_ci#include "hmdfs_dentryfile_cloud.h"
188c2ecf20Sopenharmony_ci#include "hmdfs_share.h"
198c2ecf20Sopenharmony_ci#include "hmdfs_trace.h"
208c2ecf20Sopenharmony_ci#include "authority/authentication.h"
218c2ecf20Sopenharmony_ci#include "stash.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciuint32_t make_ino_raw_cloud(uint8_t *cloud_id)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	struct qstr str;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	str.len = CLOUD_RECORD_ID_LEN;
288c2ecf20Sopenharmony_ci	str.name = cloud_id;
298c2ecf20Sopenharmony_ci	return hmdfs_dentry_hash(&str, CLOUD_RECORD_ID_LEN);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistruct hmdfs_lookup_cloud_ret *lookup_cloud_dentry(struct dentry *child_dentry,
338c2ecf20Sopenharmony_ci					      const struct qstr *qstr,
348c2ecf20Sopenharmony_ci					      uint64_t dev_id)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	int err;
378c2ecf20Sopenharmony_ci	struct hmdfs_lookup_cloud_ret *lookup_ret;
388c2ecf20Sopenharmony_ci	struct hmdfs_dentry_cloud *dentry = NULL;
398c2ecf20Sopenharmony_ci	struct clearcache_item *cache_item = NULL;
408c2ecf20Sopenharmony_ci	struct hmdfs_dcache_lookup_ctx_cloud ctx;
418c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	err = get_cloud_cache_file(child_dentry->d_parent, sbi);
448c2ecf20Sopenharmony_ci	if (unlikely(err != 0))
458c2ecf20Sopenharmony_ci		return NULL;
468c2ecf20Sopenharmony_ci	cache_item = hmdfs_find_cache_item(dev_id, child_dentry->d_parent);
478c2ecf20Sopenharmony_ci	if (!cache_item)
488c2ecf20Sopenharmony_ci		return NULL;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	lookup_ret = kmalloc(sizeof(*lookup_ret), GFP_KERNEL);
518c2ecf20Sopenharmony_ci	if (!lookup_ret)
528c2ecf20Sopenharmony_ci		goto out;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	hmdfs_init_dcache_lookup_ctx_cloud(&ctx, sbi, qstr, cache_item->filp);
558c2ecf20Sopenharmony_ci	dentry = hmdfs_find_dentry_cloud(child_dentry, &ctx);
568c2ecf20Sopenharmony_ci	if (!dentry) {
578c2ecf20Sopenharmony_ci		kfree(lookup_ret);
588c2ecf20Sopenharmony_ci		lookup_ret = NULL;
598c2ecf20Sopenharmony_ci		goto out;
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	lookup_ret->i_mode = le16_to_cpu(dentry->i_mode);
638c2ecf20Sopenharmony_ci	lookup_ret->i_size = le64_to_cpu(dentry->i_size);
648c2ecf20Sopenharmony_ci	lookup_ret->i_mtime = le64_to_cpu(dentry->i_mtime);
658c2ecf20Sopenharmony_ci	memcpy(lookup_ret->record_id, dentry->record_id, CLOUD_RECORD_ID_LEN);
668c2ecf20Sopenharmony_ci	memcpy(lookup_ret->reserved, dentry->reserved, CLOUD_DENTRY_RESERVED_LENGTH);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	hmdfs_unlock_file(ctx.filp, get_dentry_group_pos(ctx.bidx),
698c2ecf20Sopenharmony_ci			  DENTRYGROUP_SIZE);
708c2ecf20Sopenharmony_ci	kfree(ctx.page);
718c2ecf20Sopenharmony_ciout:
728c2ecf20Sopenharmony_ci	kref_put(&cache_item->ref, release_cache_item);
738c2ecf20Sopenharmony_ci	return lookup_ret;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic struct hmdfs_lookup_cloud_ret *
778c2ecf20Sopenharmony_cihmdfs_lookup_by_cloud(struct dentry *dentry, unsigned int flags)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	struct hmdfs_lookup_cloud_ret *result = NULL;
808c2ecf20Sopenharmony_ci	char *file_name = NULL;
818c2ecf20Sopenharmony_ci	struct qstr qstr;
828c2ecf20Sopenharmony_ci	int file_name_len = dentry->d_name.len;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	file_name = kzalloc(NAME_MAX + 1, GFP_KERNEL);
858c2ecf20Sopenharmony_ci	if (!file_name)
868c2ecf20Sopenharmony_ci		return NULL;
878c2ecf20Sopenharmony_ci	strncpy(file_name, dentry->d_name.name, file_name_len);
888c2ecf20Sopenharmony_ci	qstr.name = file_name;
898c2ecf20Sopenharmony_ci	qstr.len = strlen(file_name);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	result = lookup_cloud_dentry(dentry, &qstr, CLOUD_DEVICE);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	kfree(file_name);
948c2ecf20Sopenharmony_ci	return result;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/*
988c2ecf20Sopenharmony_ci * hmdfs_update_inode_size - update inode size when finding aready existed
998c2ecf20Sopenharmony_ci * inode.
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci * First of all, if the file is opened for writing, we don't update inode size
1028c2ecf20Sopenharmony_ci * here, because inode size is about to be changed after writing.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci * If the file is not opened, simply update getattr_isize(not actual inode size,
1058c2ecf20Sopenharmony_ci * just a value showed to user). This is safe because inode size will be
1068c2ecf20Sopenharmony_ci * up-to-date after open.
1078c2ecf20Sopenharmony_ci *
1088c2ecf20Sopenharmony_ci * If the file is opened for read:
1098c2ecf20Sopenharmony_ci * a. getattr_isize == HMDFS_STALE_REMOTE_ISIZE
1108c2ecf20Sopenharmony_ci *   1) i_size == new_size, nothing need to be done.
1118c2ecf20Sopenharmony_ci *   2) i_size > new_size, we keep the i_size and set getattr_isize to new_size,
1128c2ecf20Sopenharmony_ci *      stale data might be readed in this case, which is fine because file is
1138c2ecf20Sopenharmony_ci *      opened before remote truncate the file.
1148c2ecf20Sopenharmony_ci *   3) i_size < new_size, we drop the last page of the file if i_size is not
1158c2ecf20Sopenharmony_ci *      aligned to PAGE_SIZE, clear getattr_isize, and update i_size to
1168c2ecf20Sopenharmony_ci *      new_size.
1178c2ecf20Sopenharmony_ci * b. getattr_isize != HMDFS_STALE_REMOTE_ISIZE, getattr_isize will only be set
1188c2ecf20Sopenharmony_ci *    after 2).
1198c2ecf20Sopenharmony_ci *   4) getattr_isize > i_size, this situation is impossible.
1208c2ecf20Sopenharmony_ci *   5) i_size >= new_size, this case is the same as 2).
1218c2ecf20Sopenharmony_ci *   6) i_size < new_size, this case is the same as 3).
1228c2ecf20Sopenharmony_ci */
1238c2ecf20Sopenharmony_cistatic void hmdfs_update_inode_size(struct inode *inode, uint64_t new_size)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	struct hmdfs_inode_info *info = hmdfs_i(inode);
1268c2ecf20Sopenharmony_ci	int writecount;
1278c2ecf20Sopenharmony_ci	uint64_t size;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	inode_lock(inode);
1308c2ecf20Sopenharmony_ci	size = info->getattr_isize;
1318c2ecf20Sopenharmony_ci	if (size == HMDFS_STALE_REMOTE_ISIZE)
1328c2ecf20Sopenharmony_ci		size = i_size_read(inode);
1338c2ecf20Sopenharmony_ci	if (size == new_size) {
1348c2ecf20Sopenharmony_ci		inode_unlock(inode);
1358c2ecf20Sopenharmony_ci		return;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	writecount = atomic_read(&inode->i_writecount);
1398c2ecf20Sopenharmony_ci	/* check if writing is in progress */
1408c2ecf20Sopenharmony_ci	if (writecount > 0) {
1418c2ecf20Sopenharmony_ci		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
1428c2ecf20Sopenharmony_ci		inode_unlock(inode);
1438c2ecf20Sopenharmony_ci		return;
1448c2ecf20Sopenharmony_ci	}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	/* check if there is no one who opens the file */
1478c2ecf20Sopenharmony_ci	if (kref_read(&info->ref) == 0)
1488c2ecf20Sopenharmony_ci		goto update_info;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/* check if there is someone who opens the file for read */
1518c2ecf20Sopenharmony_ci	if (writecount == 0) {
1528c2ecf20Sopenharmony_ci		uint64_t aligned_size;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci		/* use inode size here instead of getattr_isize */
1558c2ecf20Sopenharmony_ci		size = i_size_read(inode);
1568c2ecf20Sopenharmony_ci		if (new_size <= size)
1578c2ecf20Sopenharmony_ci			goto update_info;
1588c2ecf20Sopenharmony_ci		/*
1598c2ecf20Sopenharmony_ci		 * if the old inode size is not aligned to HMDFS_PAGE_SIZE, we
1608c2ecf20Sopenharmony_ci		 * need to drop the last page of the inode, otherwise zero will
1618c2ecf20Sopenharmony_ci		 * be returned while reading the new range in the page after
1628c2ecf20Sopenharmony_ci		 * chaning inode size.
1638c2ecf20Sopenharmony_ci		 */
1648c2ecf20Sopenharmony_ci		aligned_size = round_down(size, HMDFS_PAGE_SIZE);
1658c2ecf20Sopenharmony_ci		if (aligned_size != size)
1668c2ecf20Sopenharmony_ci			truncate_inode_pages(inode->i_mapping, aligned_size);
1678c2ecf20Sopenharmony_ci		i_size_write(inode, new_size);
1688c2ecf20Sopenharmony_ci		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
1698c2ecf20Sopenharmony_ci		inode_unlock(inode);
1708c2ecf20Sopenharmony_ci		return;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ciupdate_info:
1748c2ecf20Sopenharmony_ci	info->getattr_isize = new_size;
1758c2ecf20Sopenharmony_ci	inode_unlock(inode);
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_cistatic void hmdfs_update_inode(struct inode *inode,
1798c2ecf20Sopenharmony_ci			       struct hmdfs_lookup_cloud_ret *lookup_result)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	struct hmdfs_time_t remote_mtime = {
1828c2ecf20Sopenharmony_ci		.tv_sec = lookup_result->i_mtime,
1838c2ecf20Sopenharmony_ci		.tv_nsec = 0,
1848c2ecf20Sopenharmony_ci	};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	/*
1878c2ecf20Sopenharmony_ci	 * We only update mtime if the file is not opened for writing. If we do
1888c2ecf20Sopenharmony_ci	 * update it before writing is about to start, user might see the mtime
1898c2ecf20Sopenharmony_ci	 * up-and-down if system time in server and client do not match. However
1908c2ecf20Sopenharmony_ci	 * mtime in client will eventually match server after timeout without
1918c2ecf20Sopenharmony_ci	 * writing.
1928c2ecf20Sopenharmony_ci	 */
1938c2ecf20Sopenharmony_ci	if (!inode_is_open_for_write(inode))
1948c2ecf20Sopenharmony_ci		inode->i_mtime = remote_mtime;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/*
1978c2ecf20Sopenharmony_ci	 * We don't care i_size of dir, and lock inode for dir
1988c2ecf20Sopenharmony_ci	 * might cause deadlock.
1998c2ecf20Sopenharmony_ci	 */
2008c2ecf20Sopenharmony_ci	if (S_ISREG(inode->i_mode))
2018c2ecf20Sopenharmony_ci		hmdfs_update_inode_size(inode, lookup_result->i_size);
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic void hmdfs_fill_inode_permission(struct inode *inode, struct inode *dir,
2058c2ecf20Sopenharmony_ci				     umode_t mode)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION
2088c2ecf20Sopenharmony_ci	inode->i_uid = dir->i_uid;
2098c2ecf20Sopenharmony_ci	inode->i_gid = dir->i_gid;
2108c2ecf20Sopenharmony_ci#endif
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistruct hmdfs_peer peer;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistruct inode *fill_inode_cloud(struct super_block *sb, struct hmdfs_lookup_cloud_ret *res, struct inode *dir)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	int ret = 0;
2188c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
2198c2ecf20Sopenharmony_ci	struct hmdfs_inode_info *info;
2208c2ecf20Sopenharmony_ci	umode_t mode = res->i_mode;
2218c2ecf20Sopenharmony_ci	peer.device_id = CLOUD_DEVICE;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	inode = hmdfs_iget5_locked_cloud(sb, &peer, res);
2248c2ecf20Sopenharmony_ci	if (!inode)
2258c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	info = hmdfs_i(inode);
2288c2ecf20Sopenharmony_ci	info->inode_type = HMDFS_LAYER_OTHER_CLOUD;
2298c2ecf20Sopenharmony_ci	/* the inode was found in cache */
2308c2ecf20Sopenharmony_ci	if (!(inode->i_state & I_NEW)) {
2318c2ecf20Sopenharmony_ci		hmdfs_fill_inode_permission(inode, dir, mode);
2328c2ecf20Sopenharmony_ci		hmdfs_update_inode(inode, res);
2338c2ecf20Sopenharmony_ci		return inode;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	inode->i_ctime.tv_sec = 0;
2378c2ecf20Sopenharmony_ci	inode->i_ctime.tv_nsec = 0;
2388c2ecf20Sopenharmony_ci	inode->i_mtime.tv_sec = res->i_mtime;
2398c2ecf20Sopenharmony_ci	inode->i_mtime.tv_nsec = 0;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	inode->i_uid = USER_DATA_RW_UID;
2428c2ecf20Sopenharmony_ci	inode->i_gid = USER_DATA_RW_GID;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (S_ISDIR(mode))
2458c2ecf20Sopenharmony_ci		inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH;
2468c2ecf20Sopenharmony_ci	else if (S_ISREG(mode))
2478c2ecf20Sopenharmony_ci		inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
2488c2ecf20Sopenharmony_ci	else {
2498c2ecf20Sopenharmony_ci		ret = -EIO;
2508c2ecf20Sopenharmony_ci		goto bad_inode;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	if (S_ISREG(mode)) {
2548c2ecf20Sopenharmony_ci		inode->i_op = &hmdfs_dev_file_iops_cloud;
2558c2ecf20Sopenharmony_ci		inode->i_fop = &hmdfs_dev_file_fops_cloud;
2568c2ecf20Sopenharmony_ci		inode->i_size = res->i_size;
2578c2ecf20Sopenharmony_ci		set_nlink(inode, 1);
2588c2ecf20Sopenharmony_ci	} else if (S_ISDIR(mode)) {
2598c2ecf20Sopenharmony_ci		inode->i_op = &hmdfs_dev_dir_inode_ops_cloud;
2608c2ecf20Sopenharmony_ci		inode->i_fop = &hmdfs_dev_dir_ops_cloud;
2618c2ecf20Sopenharmony_ci		set_nlink(inode, 2);
2628c2ecf20Sopenharmony_ci	} else {
2638c2ecf20Sopenharmony_ci		ret = -EIO;
2648c2ecf20Sopenharmony_ci		goto bad_inode;
2658c2ecf20Sopenharmony_ci	}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	inode->i_mapping->a_ops = &hmdfs_dev_file_aops_cloud;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	hmdfs_fill_inode_permission(inode, dir, mode);
2708c2ecf20Sopenharmony_ci	unlock_new_inode(inode);
2718c2ecf20Sopenharmony_ci	return inode;
2728c2ecf20Sopenharmony_cibad_inode:
2738c2ecf20Sopenharmony_ci	iget_failed(inode);
2748c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic struct dentry *hmdfs_lookup_cloud_dentry(struct inode *parent_inode,
2788c2ecf20Sopenharmony_ci						 struct dentry *child_dentry,
2798c2ecf20Sopenharmony_ci						 int flags)
2808c2ecf20Sopenharmony_ci{
2818c2ecf20Sopenharmony_ci	struct dentry *ret = NULL;
2828c2ecf20Sopenharmony_ci	struct inode *inode = NULL;
2838c2ecf20Sopenharmony_ci	struct super_block *sb = parent_inode->i_sb;
2848c2ecf20Sopenharmony_ci	struct hmdfs_lookup_cloud_ret *lookup_result = NULL;
2858c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *gdi = hmdfs_d(child_dentry);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	lookup_result = hmdfs_lookup_by_cloud(child_dentry, flags);
2888c2ecf20Sopenharmony_ci	if (lookup_result != NULL) {
2898c2ecf20Sopenharmony_ci		if (in_share_dir(child_dentry))
2908c2ecf20Sopenharmony_ci			gdi->file_type = HM_SHARE;
2918c2ecf20Sopenharmony_ci		inode = fill_inode_cloud(sb, lookup_result, parent_inode);
2928c2ecf20Sopenharmony_ci		if (IS_ERR(inode)) {
2938c2ecf20Sopenharmony_ci			ret = ERR_CAST(inode);
2948c2ecf20Sopenharmony_ci			goto out;
2958c2ecf20Sopenharmony_ci		}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci		check_and_fixup_ownership_remote(parent_inode,
2988c2ecf20Sopenharmony_ci						 inode,
2998c2ecf20Sopenharmony_ci						 child_dentry);
3008c2ecf20Sopenharmony_ci		ret = d_splice_alias(inode, child_dentry);
3018c2ecf20Sopenharmony_ci		if (!IS_ERR_OR_NULL(ret))
3028c2ecf20Sopenharmony_ci			child_dentry = ret;
3038c2ecf20Sopenharmony_ci	} else {
3048c2ecf20Sopenharmony_ci		ret = ERR_PTR(-ENOENT);
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ciout:
3088c2ecf20Sopenharmony_ci	kfree(lookup_result);
3098c2ecf20Sopenharmony_ci	return ret;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistruct dentry *hmdfs_lookup_cloud(struct inode *parent_inode,
3138c2ecf20Sopenharmony_ci				   struct dentry *child_dentry,
3148c2ecf20Sopenharmony_ci				   unsigned int flags)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	int err = 0;
3178c2ecf20Sopenharmony_ci	struct dentry *ret = NULL;
3188c2ecf20Sopenharmony_ci	struct hmdfs_dentry_info *gdi = NULL;
3198c2ecf20Sopenharmony_ci	struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	trace_hmdfs_lookup_remote(parent_inode, child_dentry, flags);
3228c2ecf20Sopenharmony_ci	if (child_dentry->d_name.len > NAME_MAX) {
3238c2ecf20Sopenharmony_ci		err = -ENAMETOOLONG;
3248c2ecf20Sopenharmony_ci		ret = ERR_PTR(-ENAMETOOLONG);
3258c2ecf20Sopenharmony_ci		goto out;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	err = init_hmdfs_dentry_info(sbi, child_dentry,
3298c2ecf20Sopenharmony_ci				     HMDFS_LAYER_OTHER_CLOUD);
3308c2ecf20Sopenharmony_ci	if (err) {
3318c2ecf20Sopenharmony_ci		ret = ERR_PTR(err);
3328c2ecf20Sopenharmony_ci		goto out;
3338c2ecf20Sopenharmony_ci	}
3348c2ecf20Sopenharmony_ci	gdi = hmdfs_d(child_dentry);
3358c2ecf20Sopenharmony_ci	gdi->device_id = hmdfs_d(child_dentry->d_parent)->device_id;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	ret = hmdfs_lookup_cloud_dentry(parent_inode, child_dentry, flags);
3388c2ecf20Sopenharmony_ci	/*
3398c2ecf20Sopenharmony_ci	 * don't return error if inode do not exist, so that vfs can continue
3408c2ecf20Sopenharmony_ci	 * to create it.
3418c2ecf20Sopenharmony_ci	 */
3428c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(ret)) {
3438c2ecf20Sopenharmony_ci		err = PTR_ERR(ret);
3448c2ecf20Sopenharmony_ci		if (err == -ENOENT)
3458c2ecf20Sopenharmony_ci			ret = NULL;
3468c2ecf20Sopenharmony_ci	} else {
3478c2ecf20Sopenharmony_ci		child_dentry = ret;
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ciout:
3518c2ecf20Sopenharmony_ci	if (!err)
3528c2ecf20Sopenharmony_ci		hmdfs_set_time(child_dentry, jiffies);
3538c2ecf20Sopenharmony_ci	trace_hmdfs_lookup_remote_end(parent_inode, child_dentry, err);
3548c2ecf20Sopenharmony_ci	return ret;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ciint hmdfs_mkdir_cloud(struct inode *dir, struct dentry *dentry, umode_t mode)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	return -EPERM;
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ciint hmdfs_create_cloud(struct inode *dir, struct dentry *dentry, umode_t mode,
3638c2ecf20Sopenharmony_ci			bool want_excl)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	return -EPERM;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ciint hmdfs_rmdir_cloud(struct inode *dir, struct dentry *dentry)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	return -EPERM;
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ciint hmdfs_unlink_cloud(struct inode *dir, struct dentry *dentry)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	return 0;
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ciint hmdfs_rename_cloud(struct inode *old_dir, struct dentry *old_dentry,
3798c2ecf20Sopenharmony_ci			struct inode *new_dir, struct dentry *new_dentry,
3808c2ecf20Sopenharmony_ci			unsigned int flags)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	return -EPERM;
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic int hmdfs_dir_setattr_cloud(struct dentry *dentry, struct iattr *ia)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	// Do not support dir setattr
3888c2ecf20Sopenharmony_ci	return 0;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ciconst struct inode_operations hmdfs_dev_dir_inode_ops_cloud = {
3928c2ecf20Sopenharmony_ci	.lookup = hmdfs_lookup_cloud,
3938c2ecf20Sopenharmony_ci	.mkdir = hmdfs_mkdir_cloud,
3948c2ecf20Sopenharmony_ci	.create = hmdfs_create_cloud,
3958c2ecf20Sopenharmony_ci	.rmdir = hmdfs_rmdir_cloud,
3968c2ecf20Sopenharmony_ci	.unlink = hmdfs_unlink_cloud,
3978c2ecf20Sopenharmony_ci	.rename = hmdfs_rename_cloud,
3988c2ecf20Sopenharmony_ci	.setattr = hmdfs_dir_setattr_cloud,
3998c2ecf20Sopenharmony_ci	.permission = hmdfs_permission,
4008c2ecf20Sopenharmony_ci};
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic int hmdfs_setattr_cloud(struct dentry *dentry, struct iattr *ia)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	struct hmdfs_inode_info *info = hmdfs_i(d_inode(dentry));
4058c2ecf20Sopenharmony_ci	struct inode *inode = d_inode(dentry);
4068c2ecf20Sopenharmony_ci	int err = 0;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (hmdfs_inode_is_stashing(info))
4098c2ecf20Sopenharmony_ci		return -EAGAIN;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	if (ia->ia_valid & ATTR_SIZE) {
4128c2ecf20Sopenharmony_ci		err = inode_newsize_ok(inode, ia->ia_size);
4138c2ecf20Sopenharmony_ci		if (err)
4148c2ecf20Sopenharmony_ci			return err;
4158c2ecf20Sopenharmony_ci		truncate_setsize(inode, ia->ia_size);
4168c2ecf20Sopenharmony_ci		info->getattr_isize = HMDFS_STALE_REMOTE_ISIZE;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci	if (ia->ia_valid & ATTR_MTIME)
4198c2ecf20Sopenharmony_ci		inode->i_mtime = ia->ia_mtime;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	return err;
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic int hmdfs_get_cached_attr_cloud(const struct path *path,
4268c2ecf20Sopenharmony_ci					struct kstat *stat, u32 request_mask,
4278c2ecf20Sopenharmony_ci					unsigned int flags)
4288c2ecf20Sopenharmony_ci{
4298c2ecf20Sopenharmony_ci	struct inode *inode = d_inode(path->dentry);
4308c2ecf20Sopenharmony_ci	struct hmdfs_inode_info *info = hmdfs_i(inode);
4318c2ecf20Sopenharmony_ci	uint64_t size = info->getattr_isize;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	stat->ino = inode->i_ino;
4348c2ecf20Sopenharmony_ci	stat->mtime = inode->i_mtime;
4358c2ecf20Sopenharmony_ci	stat->mode = inode->i_mode;
4368c2ecf20Sopenharmony_ci	stat->uid.val = inode->i_uid.val;
4378c2ecf20Sopenharmony_ci	stat->gid.val = inode->i_gid.val;
4388c2ecf20Sopenharmony_ci	if (size == HMDFS_STALE_REMOTE_ISIZE)
4398c2ecf20Sopenharmony_ci		size = i_size_read(inode);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	stat->size = size;
4428c2ecf20Sopenharmony_ci	return 0;
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ciconst struct inode_operations hmdfs_dev_file_iops_cloud = {
4468c2ecf20Sopenharmony_ci	.setattr = hmdfs_setattr_cloud,
4478c2ecf20Sopenharmony_ci	.permission = hmdfs_permission,
4488c2ecf20Sopenharmony_ci	.getattr = hmdfs_get_cached_attr_cloud,
4498c2ecf20Sopenharmony_ci	.listxattr = NULL,
4508c2ecf20Sopenharmony_ci};
451