162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/hmdfs/inode_cloud_merge.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "hmdfs_merge_view.h" 962306a36Sopenharmony_ci#include <linux/atomic.h> 1062306a36Sopenharmony_ci#include <linux/fs.h> 1162306a36Sopenharmony_ci#include <linux/fs_stack.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/list.h> 1462306a36Sopenharmony_ci#include <linux/mount.h> 1562306a36Sopenharmony_ci#include <linux/namei.h> 1662306a36Sopenharmony_ci#include <linux/rwsem.h> 1762306a36Sopenharmony_ci#include <linux/slab.h> 1862306a36Sopenharmony_ci#include <linux/types.h> 1962306a36Sopenharmony_ci#include "authority/authentication.h" 2062306a36Sopenharmony_ci#include "hmdfs_trace.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic struct inode *fill_inode_merge(struct super_block *sb, 2362306a36Sopenharmony_ci struct inode *parent_inode, 2462306a36Sopenharmony_ci struct dentry *child_dentry, 2562306a36Sopenharmony_ci struct dentry *lo_d_dentry) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci int ret = 0; 2862306a36Sopenharmony_ci struct dentry *fst_lo_d = NULL; 2962306a36Sopenharmony_ci struct hmdfs_inode_info *info = NULL; 3062306a36Sopenharmony_ci struct inode *inode = NULL; 3162306a36Sopenharmony_ci umode_t mode; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (lo_d_dentry) { 3462306a36Sopenharmony_ci fst_lo_d = lo_d_dentry; 3562306a36Sopenharmony_ci dget(fst_lo_d); 3662306a36Sopenharmony_ci } else { 3762306a36Sopenharmony_ci fst_lo_d = hmdfs_get_fst_lo_d(child_dentry); 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci if (!fst_lo_d) { 4062306a36Sopenharmony_ci inode = ERR_PTR(-EINVAL); 4162306a36Sopenharmony_ci goto out; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO) 4462306a36Sopenharmony_ci inode = hmdfs_iget_locked_root(sb, HMDFS_ROOT_MERGE_CLOUD, NULL, 4562306a36Sopenharmony_ci NULL); 4662306a36Sopenharmony_ci else 4762306a36Sopenharmony_ci inode = hmdfs_iget5_locked_cloud_merge(sb, fst_lo_d); 4862306a36Sopenharmony_ci if (!inode) { 4962306a36Sopenharmony_ci hmdfs_err("iget5_locked get inode NULL"); 5062306a36Sopenharmony_ci inode = ERR_PTR(-ENOMEM); 5162306a36Sopenharmony_ci goto out; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci if (!(inode->i_state & I_NEW)) 5462306a36Sopenharmony_ci goto out; 5562306a36Sopenharmony_ci info = hmdfs_i(inode); 5662306a36Sopenharmony_ci if (hmdfs_i(parent_inode)->inode_type == HMDFS_LAYER_ZERO) 5762306a36Sopenharmony_ci info->inode_type = HMDFS_LAYER_FIRST_MERGE_CLOUD; 5862306a36Sopenharmony_ci else 5962306a36Sopenharmony_ci info->inode_type = HMDFS_LAYER_OTHER_MERGE_CLOUD; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci inode->i_uid = USER_DATA_RW_UID; 6262306a36Sopenharmony_ci inode->i_gid = USER_DATA_RW_GID; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci update_inode_attr(inode, child_dentry); 6562306a36Sopenharmony_ci mode = d_inode(fst_lo_d)->i_mode; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (S_ISREG(mode)) { 6862306a36Sopenharmony_ci inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 6962306a36Sopenharmony_ci inode->i_op = &hmdfs_file_iops_cloud_merge; 7062306a36Sopenharmony_ci inode->i_fop = &hmdfs_file_fops_merge; 7162306a36Sopenharmony_ci set_nlink(inode, 1); 7262306a36Sopenharmony_ci } else if (S_ISDIR(mode)) { 7362306a36Sopenharmony_ci inode->i_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IXOTH; 7462306a36Sopenharmony_ci inode->i_op = &hmdfs_dir_iops_cloud_merge; 7562306a36Sopenharmony_ci inode->i_fop = &hmdfs_dir_fops_merge; 7662306a36Sopenharmony_ci set_nlink(inode, get_num_comrades(child_dentry) + 2); 7762306a36Sopenharmony_ci } else { 7862306a36Sopenharmony_ci ret = -EIO; 7962306a36Sopenharmony_ci goto bad_inode; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci unlock_new_inode(inode); 8362306a36Sopenharmony_ciout: 8462306a36Sopenharmony_ci dput(fst_lo_d); 8562306a36Sopenharmony_ci return inode; 8662306a36Sopenharmony_cibad_inode: 8762306a36Sopenharmony_ci iget_failed(inode); 8862306a36Sopenharmony_ci return ERR_PTR(ret); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic struct hmdfs_dentry_comrade * 9262306a36Sopenharmony_cicloud_merge_lookup_comrade(struct hmdfs_sb_info *sbi, 9362306a36Sopenharmony_ci const char *name, 9462306a36Sopenharmony_ci int devid, 9562306a36Sopenharmony_ci unsigned int flags) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci int err; 9862306a36Sopenharmony_ci struct path root, path; 9962306a36Sopenharmony_ci struct hmdfs_dentry_comrade *comrade = NULL; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci err = kern_path(sbi->real_dst, LOOKUP_DIRECTORY, &root); 10262306a36Sopenharmony_ci if (err) { 10362306a36Sopenharmony_ci comrade = ERR_PTR(err); 10462306a36Sopenharmony_ci goto out; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci err = vfs_path_lookup(root.dentry, root.mnt, name, flags, &path); 10862306a36Sopenharmony_ci if (err) { 10962306a36Sopenharmony_ci comrade = ERR_PTR(err); 11062306a36Sopenharmony_ci goto root_put; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci comrade = alloc_comrade(path.dentry, devid); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci path_put(&path); 11662306a36Sopenharmony_ciroot_put: 11762306a36Sopenharmony_ci path_put(&root); 11862306a36Sopenharmony_ciout: 11962306a36Sopenharmony_ci return comrade; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic void merge_lookup_sync(struct hmdfs_dentry_info_merge *mdi, 12362306a36Sopenharmony_ci struct hmdfs_sb_info *sbi, 12462306a36Sopenharmony_ci int devid, 12562306a36Sopenharmony_ci const char *name, 12662306a36Sopenharmony_ci unsigned int flags) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci struct hmdfs_dentry_comrade *comrade; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci comrade = cloud_merge_lookup_comrade(sbi, name, devid, flags); 13162306a36Sopenharmony_ci if (IS_ERR(comrade)) 13262306a36Sopenharmony_ci return; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci mutex_lock(&mdi->comrade_list_lock); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (!is_valid_comrade(mdi, hmdfs_cm(comrade))) 13762306a36Sopenharmony_ci destroy_comrade(comrade); 13862306a36Sopenharmony_ci else 13962306a36Sopenharmony_ci link_comrade(&mdi->comrade_list, comrade); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci mutex_unlock(&mdi->comrade_list_lock); 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int lookup_merge_normal(struct dentry *dentry, unsigned int flags) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci int ret = -ENOMEM; 14762306a36Sopenharmony_ci int devid = -1; 14862306a36Sopenharmony_ci struct dentry *pdentry = dget_parent(dentry); 14962306a36Sopenharmony_ci struct hmdfs_dentry_info_merge *mdi = hmdfs_dm(dentry); 15062306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(dentry->d_sb); 15162306a36Sopenharmony_ci char *rname, *ppath, *cpath; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci rname = hmdfs_get_real_dname(dentry, &devid, &mdi->type); 15462306a36Sopenharmony_ci if (unlikely(!rname)) { 15562306a36Sopenharmony_ci goto out; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci ppath = hmdfs_merge_get_dentry_relative_path(pdentry); 15962306a36Sopenharmony_ci if (unlikely(!ppath)) { 16062306a36Sopenharmony_ci hmdfs_err("failed to get parent relative path"); 16162306a36Sopenharmony_ci goto out_rname; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci cpath = kzalloc(PATH_MAX, GFP_KERNEL); 16562306a36Sopenharmony_ci if (unlikely(!cpath)) { 16662306a36Sopenharmony_ci hmdfs_err("failed to get child device_view path"); 16762306a36Sopenharmony_ci goto out_ppath; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (mdi->type != DT_REG || devid == 0) { 17162306a36Sopenharmony_ci snprintf(cpath, PATH_MAX, "device_view/local%s/%s", ppath, 17262306a36Sopenharmony_ci rname); 17362306a36Sopenharmony_ci merge_lookup_sync(mdi, sbi, 0, cpath, flags); 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci if (mdi->type == DT_REG && !is_comrade_list_empty(mdi)) { 17662306a36Sopenharmony_ci ret = 0; 17762306a36Sopenharmony_ci goto found; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci snprintf(cpath, PATH_MAX, "device_view/%s%s/%s", CLOUD_CID, 18162306a36Sopenharmony_ci ppath, rname); 18262306a36Sopenharmony_ci merge_lookup_sync(mdi, sbi, CLOUD_DEVICE, cpath, flags); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci ret = -ENOENT; 18562306a36Sopenharmony_ci if (!is_comrade_list_empty(mdi)) 18662306a36Sopenharmony_ci ret = 0; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cifound: 18962306a36Sopenharmony_ci kfree(cpath); 19062306a36Sopenharmony_ciout_ppath: 19162306a36Sopenharmony_ci kfree(ppath); 19262306a36Sopenharmony_ciout_rname: 19362306a36Sopenharmony_ci kfree(rname); 19462306a36Sopenharmony_ciout: 19562306a36Sopenharmony_ci dput(pdentry); 19662306a36Sopenharmony_ci return ret; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci/** 20062306a36Sopenharmony_ci * do_lookup_merge_root - lookup the root of the merge view(root/merge_view) 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * It's common for a network filesystem to incur various of faults, so we 20362306a36Sopenharmony_ci * intent to show mercy for faults here, except faults reported by the local. 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_cistatic int do_lookup_cloud_merge_root(struct path path_dev, 20662306a36Sopenharmony_ci struct dentry *child_dentry, unsigned int flags) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct hmdfs_dentry_comrade *comrade; 20962306a36Sopenharmony_ci const int buf_len = 21062306a36Sopenharmony_ci max((int)HMDFS_CID_SIZE + 1, (int)sizeof(DEVICE_VIEW_LOCAL)); 21162306a36Sopenharmony_ci char *buf = kzalloc(buf_len, GFP_KERNEL); 21262306a36Sopenharmony_ci LIST_HEAD(head); 21362306a36Sopenharmony_ci int ret; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (!buf) 21662306a36Sopenharmony_ci return -ENOMEM; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci // lookup real_dst/device_view/local 21962306a36Sopenharmony_ci memcpy(buf, DEVICE_VIEW_LOCAL, sizeof(DEVICE_VIEW_LOCAL)); 22062306a36Sopenharmony_ci comrade = lookup_comrade(path_dev, buf, HMDFS_DEVID_LOCAL, flags); 22162306a36Sopenharmony_ci if (IS_ERR(comrade)) { 22262306a36Sopenharmony_ci ret = PTR_ERR(comrade); 22362306a36Sopenharmony_ci goto out; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci link_comrade(&head, comrade); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci memcpy(buf, CLOUD_CID, 6); 22862306a36Sopenharmony_ci buf[5] = '\0'; 22962306a36Sopenharmony_ci comrade = lookup_comrade(path_dev, buf, CLOUD_DEVICE, flags); 23062306a36Sopenharmony_ci if (IS_ERR(comrade)) { 23162306a36Sopenharmony_ci ret = 0; 23262306a36Sopenharmony_ci goto out; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci link_comrade(&head, comrade); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci assign_comrades_unlocked(child_dentry, &head); 23862306a36Sopenharmony_ci ret = 0; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ciout: 24162306a36Sopenharmony_ci kfree(buf); 24262306a36Sopenharmony_ci return ret; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic int lookup_cloud_merge_root(struct inode *root_inode, 24662306a36Sopenharmony_ci struct dentry *child_dentry, unsigned int flags) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 24962306a36Sopenharmony_ci struct path path_dev; 25062306a36Sopenharmony_ci int ret = -ENOENT; 25162306a36Sopenharmony_ci int buf_len; 25262306a36Sopenharmony_ci char *buf = NULL; 25362306a36Sopenharmony_ci bool locked, down; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci // consider additional one slash and one '\0' 25662306a36Sopenharmony_ci buf_len = strlen(sbi->real_dst) + 1 + sizeof(DEVICE_VIEW_ROOT); 25762306a36Sopenharmony_ci if (buf_len > PATH_MAX) 25862306a36Sopenharmony_ci return -ENAMETOOLONG; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci buf = kmalloc(buf_len, GFP_KERNEL); 26162306a36Sopenharmony_ci if (unlikely(!buf)) 26262306a36Sopenharmony_ci return -ENOMEM; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci sprintf(buf, "%s/%s", sbi->real_dst, DEVICE_VIEW_ROOT); 26562306a36Sopenharmony_ci lock_root_inode_shared(root_inode, &locked, &down); 26662306a36Sopenharmony_ci ret = hmdfs_get_path_in_sb(child_dentry->d_sb, buf, LOOKUP_DIRECTORY, 26762306a36Sopenharmony_ci &path_dev); 26862306a36Sopenharmony_ci if (ret) 26962306a36Sopenharmony_ci goto free_buf; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci ret = do_lookup_cloud_merge_root(path_dev, child_dentry, flags); 27262306a36Sopenharmony_ci path_put(&path_dev); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cifree_buf: 27562306a36Sopenharmony_ci kfree(buf); 27662306a36Sopenharmony_ci restore_root_inode_sem(root_inode, locked, down); 27762306a36Sopenharmony_ci return ret; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci// do this in a map-reduce manner 28162306a36Sopenharmony_cistruct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode, 28262306a36Sopenharmony_ci struct dentry *child_dentry, 28362306a36Sopenharmony_ci unsigned int flags) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci bool create = flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET); 28662306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 28762306a36Sopenharmony_ci struct hmdfs_inode_info *pii = hmdfs_i(parent_inode); 28862306a36Sopenharmony_ci struct inode *child_inode = NULL; 28962306a36Sopenharmony_ci struct dentry *ret_dentry = NULL; 29062306a36Sopenharmony_ci int err = 0; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* 29362306a36Sopenharmony_ci * Internal flags like LOOKUP_CREATE should not pass to device view. 29462306a36Sopenharmony_ci * LOOKUP_REVAL is needed because dentry cache in hmdfs might be stale 29562306a36Sopenharmony_ci * after rename in lower fs. LOOKUP_DIRECTORY is not needed because 29662306a36Sopenharmony_ci * merge_view can do the judgement that whether result is directory or 29762306a36Sopenharmony_ci * not. 29862306a36Sopenharmony_ci */ 29962306a36Sopenharmony_ci flags = flags & LOOKUP_REVAL; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci child_dentry->d_fsdata = NULL; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (child_dentry->d_name.len > NAME_MAX) { 30462306a36Sopenharmony_ci err = -ENAMETOOLONG; 30562306a36Sopenharmony_ci goto out; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci err = init_hmdfs_dentry_info_merge(sbi, child_dentry); 30962306a36Sopenharmony_ci if (unlikely(err)) 31062306a36Sopenharmony_ci goto out; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (pii->inode_type == HMDFS_LAYER_ZERO) { 31362306a36Sopenharmony_ci hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_FIRST_MERGE_CLOUD; 31462306a36Sopenharmony_ci err = lookup_cloud_merge_root(parent_inode, child_dentry, flags); 31562306a36Sopenharmony_ci } else { 31662306a36Sopenharmony_ci hmdfs_dm(child_dentry)->dentry_type = HMDFS_LAYER_OTHER_MERGE_CLOUD; 31762306a36Sopenharmony_ci err = lookup_merge_normal(child_dentry, flags); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (!err) { 32162306a36Sopenharmony_ci struct hmdfs_inode_info *info = NULL; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci child_inode = fill_inode_merge(parent_inode->i_sb, parent_inode, 32462306a36Sopenharmony_ci child_dentry, NULL); 32562306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 32662306a36Sopenharmony_ci err = PTR_ERR(child_inode); 32762306a36Sopenharmony_ci goto out; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci info = hmdfs_i(child_inode); 33062306a36Sopenharmony_ci if (info->inode_type == HMDFS_LAYER_FIRST_MERGE) 33162306a36Sopenharmony_ci hmdfs_root_inode_perm_init(child_inode); 33262306a36Sopenharmony_ci else 33362306a36Sopenharmony_ci check_and_fixup_ownership_remote(parent_inode, 33462306a36Sopenharmony_ci child_inode, 33562306a36Sopenharmony_ci child_dentry); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci ret_dentry = d_splice_alias(child_inode, child_dentry); 33862306a36Sopenharmony_ci if (IS_ERR(ret_dentry)) { 33962306a36Sopenharmony_ci clear_comrades(child_dentry); 34062306a36Sopenharmony_ci err = PTR_ERR(ret_dentry); 34162306a36Sopenharmony_ci goto out; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci if (ret_dentry) 34462306a36Sopenharmony_ci child_dentry = ret_dentry; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci goto out; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if ((err == -ENOENT) && create) 35062306a36Sopenharmony_ci err = 0; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ciout: 35362306a36Sopenharmony_ci return err ? ERR_PTR(err) : ret_dentry; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ciconst struct inode_operations hmdfs_file_iops_cloud_merge = { 35762306a36Sopenharmony_ci .getattr = hmdfs_getattr_merge, 35862306a36Sopenharmony_ci .setattr = hmdfs_setattr_merge, 35962306a36Sopenharmony_ci .permission = hmdfs_permission, 36062306a36Sopenharmony_ci}; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ciint do_mkdir_cloud_merge(struct inode *parent_inode, struct dentry *child_dentry, 36362306a36Sopenharmony_ci umode_t mode, struct inode *lo_i_parent, 36462306a36Sopenharmony_ci struct dentry *lo_d_child) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci int ret = 0; 36762306a36Sopenharmony_ci struct super_block *sb = parent_inode->i_sb; 36862306a36Sopenharmony_ci struct inode *child_inode = NULL; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci ret = vfs_mkdir(&nop_mnt_idmap, lo_i_parent, lo_d_child, mode); 37162306a36Sopenharmony_ci if (ret) 37262306a36Sopenharmony_ci goto out; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci child_inode = 37562306a36Sopenharmony_ci fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child); 37662306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 37762306a36Sopenharmony_ci ret = PTR_ERR(child_inode); 37862306a36Sopenharmony_ci goto out; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci d_add(child_dentry, child_inode); 38262306a36Sopenharmony_ci /* nlink should be increased with the joining of children */ 38362306a36Sopenharmony_ci set_nlink(parent_inode, 2); 38462306a36Sopenharmony_ci hmdfs_update_meta(parent_inode); 38562306a36Sopenharmony_ciout: 38662306a36Sopenharmony_ci return ret; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ciint do_create_cloud_merge(struct inode *parent_inode, struct dentry *child_dentry, 39062306a36Sopenharmony_ci umode_t mode, bool want_excl, struct inode *lo_i_parent, 39162306a36Sopenharmony_ci struct dentry *lo_d_child) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci int ret = 0; 39462306a36Sopenharmony_ci struct super_block *sb = parent_inode->i_sb; 39562306a36Sopenharmony_ci struct inode *child_inode = NULL; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ret = vfs_create(&nop_mnt_idmap, lo_i_parent, lo_d_child, mode, want_excl); 39862306a36Sopenharmony_ci if (ret) 39962306a36Sopenharmony_ci goto out; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci child_inode = 40262306a36Sopenharmony_ci fill_inode_merge(sb, parent_inode, child_dentry, lo_d_child); 40362306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 40462306a36Sopenharmony_ci ret = PTR_ERR(child_inode); 40562306a36Sopenharmony_ci goto out; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci d_add(child_dentry, child_inode); 40962306a36Sopenharmony_ci /* nlink should be increased with the joining of children */ 41062306a36Sopenharmony_ci set_nlink(parent_inode, 2); 41162306a36Sopenharmony_ci hmdfs_update_meta(parent_inode); 41262306a36Sopenharmony_ciout: 41362306a36Sopenharmony_ci return ret; 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ciint hmdfs_do_ops_cloud_merge(struct inode *i_parent, struct dentry *d_child, 41762306a36Sopenharmony_ci struct dentry *lo_d_child, struct path path, 41862306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci int ret = 0; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (rec_op_para->is_last) { 42362306a36Sopenharmony_ci switch (rec_op_para->opcode) { 42462306a36Sopenharmony_ci case F_MKDIR_MERGE: 42562306a36Sopenharmony_ci ret = do_mkdir_cloud_merge(i_parent, d_child, 42662306a36Sopenharmony_ci rec_op_para->mode, 42762306a36Sopenharmony_ci d_inode(path.dentry), lo_d_child); 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci case F_CREATE_MERGE: 43062306a36Sopenharmony_ci ret = do_create_cloud_merge(i_parent, d_child, 43162306a36Sopenharmony_ci rec_op_para->mode, 43262306a36Sopenharmony_ci rec_op_para->want_excl, 43362306a36Sopenharmony_ci d_inode(path.dentry), lo_d_child); 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci default: 43662306a36Sopenharmony_ci ret = -EINVAL; 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci ret = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), lo_d_child, 44162306a36Sopenharmony_ci rec_op_para->mode); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci if (ret) 44462306a36Sopenharmony_ci hmdfs_err("vfs_ops failed, ops %d, err = %d", 44562306a36Sopenharmony_ci rec_op_para->opcode, ret); 44662306a36Sopenharmony_ci return ret; 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ciint hmdfs_create_lower_cloud_dentry(struct inode *i_parent, struct dentry *d_child, 45062306a36Sopenharmony_ci struct dentry *lo_d_parent, bool is_dir, 45162306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = i_parent->i_sb->s_fs_info; 45462306a36Sopenharmony_ci struct hmdfs_dentry_comrade *new_comrade = NULL; 45562306a36Sopenharmony_ci struct dentry *lo_d_child = NULL; 45662306a36Sopenharmony_ci char *path_buf = kmalloc(PATH_MAX, GFP_KERNEL); 45762306a36Sopenharmony_ci char *absolute_path_buf = kmalloc(PATH_MAX, GFP_KERNEL); 45862306a36Sopenharmony_ci char *path_name = NULL; 45962306a36Sopenharmony_ci struct path path = { .mnt = NULL, .dentry = NULL }; 46062306a36Sopenharmony_ci int ret = 0; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (unlikely(!path_buf || !absolute_path_buf)) { 46362306a36Sopenharmony_ci ret = -ENOMEM; 46462306a36Sopenharmony_ci goto out; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci path_name = dentry_path_raw(lo_d_parent, path_buf, PATH_MAX); 46862306a36Sopenharmony_ci if (IS_ERR(path_name)) { 46962306a36Sopenharmony_ci ret = PTR_ERR(path_name); 47062306a36Sopenharmony_ci goto out; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci if ((strlen(sbi->real_dst) + strlen(path_name) + 47362306a36Sopenharmony_ci strlen(d_child->d_name.name) + 2) > PATH_MAX) { 47462306a36Sopenharmony_ci ret = -ENAMETOOLONG; 47562306a36Sopenharmony_ci goto out; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci sprintf(absolute_path_buf, "%s%s/%s", sbi->real_dst, path_name, 47962306a36Sopenharmony_ci d_child->d_name.name); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (is_dir) 48262306a36Sopenharmony_ci lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf, 48362306a36Sopenharmony_ci &path, LOOKUP_DIRECTORY); 48462306a36Sopenharmony_ci else 48562306a36Sopenharmony_ci lo_d_child = kern_path_create(AT_FDCWD, absolute_path_buf, 48662306a36Sopenharmony_ci &path, 0); 48762306a36Sopenharmony_ci if (IS_ERR(lo_d_child)) { 48862306a36Sopenharmony_ci ret = PTR_ERR(lo_d_child); 48962306a36Sopenharmony_ci goto out; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci // to ensure link_comrade after vfs_mkdir succeed 49262306a36Sopenharmony_ci ret = hmdfs_do_ops_cloud_merge(i_parent, d_child, lo_d_child, path, 49362306a36Sopenharmony_ci rec_op_para); 49462306a36Sopenharmony_ci if (ret) 49562306a36Sopenharmony_ci goto out_put; 49662306a36Sopenharmony_ci new_comrade = alloc_comrade(lo_d_child, HMDFS_DEVID_LOCAL); 49762306a36Sopenharmony_ci if (IS_ERR(new_comrade)) { 49862306a36Sopenharmony_ci ret = PTR_ERR(new_comrade); 49962306a36Sopenharmony_ci goto out_put; 50062306a36Sopenharmony_ci } else { 50162306a36Sopenharmony_ci link_comrade_unlocked(d_child, new_comrade); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci update_inode_attr(d_inode(d_child), d_child); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ciout_put: 50762306a36Sopenharmony_ci done_path_create(&path, lo_d_child); 50862306a36Sopenharmony_ciout: 50962306a36Sopenharmony_ci kfree(absolute_path_buf); 51062306a36Sopenharmony_ci kfree(path_buf); 51162306a36Sopenharmony_ci return ret; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic int create_lo_d_parent_recur(struct dentry *d_parent, 51562306a36Sopenharmony_ci struct dentry *d_child, umode_t mode, 51662306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci struct dentry *lo_d_parent, *d_pparent; 51962306a36Sopenharmony_ci int ret = 0; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 52262306a36Sopenharmony_ci if (!lo_d_parent) { 52362306a36Sopenharmony_ci d_pparent = dget_parent(d_parent); 52462306a36Sopenharmony_ci ret = create_lo_d_parent_recur(d_pparent, d_parent, 52562306a36Sopenharmony_ci d_inode(d_parent)->i_mode, 52662306a36Sopenharmony_ci rec_op_para); 52762306a36Sopenharmony_ci dput(d_pparent); 52862306a36Sopenharmony_ci if (ret) 52962306a36Sopenharmony_ci goto out; 53062306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 53162306a36Sopenharmony_ci if (!lo_d_parent) { 53262306a36Sopenharmony_ci ret = -ENOENT; 53362306a36Sopenharmony_ci goto out; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci rec_op_para->is_last = false; 53762306a36Sopenharmony_ci rec_op_para->mode = mode; 53862306a36Sopenharmony_ci ret = hmdfs_create_lower_cloud_dentry(d_inode(d_parent), d_child, lo_d_parent, 53962306a36Sopenharmony_ci true, rec_op_para); 54062306a36Sopenharmony_ciout: 54162306a36Sopenharmony_ci dput(lo_d_parent); 54262306a36Sopenharmony_ci return ret; 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ciint create_lo_d_cloud_child(struct inode *i_parent, struct dentry *d_child, 54662306a36Sopenharmony_ci bool is_dir, struct hmdfs_recursive_para *rec_op_para) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct dentry *d_pparent, *lo_d_parent, *lo_d_child; 54962306a36Sopenharmony_ci struct dentry *d_parent = dget_parent(d_child); 55062306a36Sopenharmony_ci int ret = 0; 55162306a36Sopenharmony_ci mode_t d_child_mode = rec_op_para->mode; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 55462306a36Sopenharmony_ci if (!lo_d_parent) { 55562306a36Sopenharmony_ci d_pparent = dget_parent(d_parent); 55662306a36Sopenharmony_ci ret = create_lo_d_parent_recur(d_pparent, d_parent, 55762306a36Sopenharmony_ci d_inode(d_parent)->i_mode, 55862306a36Sopenharmony_ci rec_op_para); 55962306a36Sopenharmony_ci dput(d_pparent); 56062306a36Sopenharmony_ci if (unlikely(ret)) { 56162306a36Sopenharmony_ci lo_d_child = ERR_PTR(ret); 56262306a36Sopenharmony_ci goto out; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 56562306a36Sopenharmony_ci if (!lo_d_parent) { 56662306a36Sopenharmony_ci lo_d_child = ERR_PTR(-ENOENT); 56762306a36Sopenharmony_ci goto out; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci rec_op_para->is_last = true; 57162306a36Sopenharmony_ci rec_op_para->mode = d_child_mode; 57262306a36Sopenharmony_ci ret = hmdfs_create_lower_cloud_dentry(i_parent, d_child, lo_d_parent, is_dir, 57362306a36Sopenharmony_ci rec_op_para); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ciout: 57662306a36Sopenharmony_ci dput(d_parent); 57762306a36Sopenharmony_ci dput(lo_d_parent); 57862306a36Sopenharmony_ci return ret; 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ciint hmdfs_mkdir_cloud_merge(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci int ret = 0; 58462306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para = NULL; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci // confict_name & file_type is checked by hmdfs_mkdir_local 58762306a36Sopenharmony_ci if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { 58862306a36Sopenharmony_ci ret = -EACCES; 58962306a36Sopenharmony_ci goto out; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); 59262306a36Sopenharmony_ci if (!rec_op_para) { 59362306a36Sopenharmony_ci ret = -ENOMEM; 59462306a36Sopenharmony_ci goto out; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci hmdfs_init_recursive_para(rec_op_para, F_MKDIR_MERGE, mode, false, 59862306a36Sopenharmony_ci NULL); 59962306a36Sopenharmony_ci ret = create_lo_d_cloud_child(dir, dentry, true, rec_op_para); 60062306a36Sopenharmony_ciout: 60162306a36Sopenharmony_ci hmdfs_trace_merge(trace_hmdfs_mkdir_merge, dir, dentry, ret); 60262306a36Sopenharmony_ci if (ret) 60362306a36Sopenharmony_ci d_drop(dentry); 60462306a36Sopenharmony_ci kfree(rec_op_para); 60562306a36Sopenharmony_ci return ret; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ciint hmdfs_create_cloud_merge(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, 60962306a36Sopenharmony_ci bool want_excl) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para = NULL; 61262306a36Sopenharmony_ci int ret = 0; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); 61562306a36Sopenharmony_ci if (!rec_op_para) { 61662306a36Sopenharmony_ci ret = -ENOMEM; 61762306a36Sopenharmony_ci goto out; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci hmdfs_init_recursive_para(rec_op_para, F_CREATE_MERGE, mode, want_excl, 62062306a36Sopenharmony_ci NULL); 62162306a36Sopenharmony_ci // confict_name & file_type is checked by hmdfs_create_local 62262306a36Sopenharmony_ci ret = create_lo_d_cloud_child(dir, dentry, false, rec_op_para); 62362306a36Sopenharmony_ciout: 62462306a36Sopenharmony_ci hmdfs_trace_merge(trace_hmdfs_create_merge, dir, dentry, ret); 62562306a36Sopenharmony_ci if (ret) 62662306a36Sopenharmony_ci d_drop(dentry); 62762306a36Sopenharmony_ci kfree(rec_op_para); 62862306a36Sopenharmony_ci return ret; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic int rename_lo_d_cloud_child(struct hmdfs_rename_para *rename_para, 63262306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para) 63362306a36Sopenharmony_ci{ 63462306a36Sopenharmony_ci struct dentry *d_pparent, *lo_d_parent; 63562306a36Sopenharmony_ci struct dentry *d_parent = dget_parent(rename_para->new_dentry); 63662306a36Sopenharmony_ci int ret = 0; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 63962306a36Sopenharmony_ci if (!lo_d_parent) { 64062306a36Sopenharmony_ci d_pparent = dget_parent(d_parent); 64162306a36Sopenharmony_ci ret = create_lo_d_parent_recur(d_pparent, d_parent, 64262306a36Sopenharmony_ci d_inode(d_parent)->i_mode, 64362306a36Sopenharmony_ci rec_op_para); 64462306a36Sopenharmony_ci dput(d_pparent); 64562306a36Sopenharmony_ci if (unlikely(ret)) 64662306a36Sopenharmony_ci goto out; 64762306a36Sopenharmony_ci lo_d_parent = hmdfs_get_lo_d(d_parent, HMDFS_DEVID_LOCAL); 64862306a36Sopenharmony_ci if (!lo_d_parent) { 64962306a36Sopenharmony_ci ret = -ENOENT; 65062306a36Sopenharmony_ci goto out; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci ret = do_rename_merge(rename_para->old_dir, rename_para->old_dentry, 65462306a36Sopenharmony_ci rename_para->new_dir, rename_para->new_dentry, 65562306a36Sopenharmony_ci rename_para->flags); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ciout: 65862306a36Sopenharmony_ci dput(d_parent); 65962306a36Sopenharmony_ci dput(lo_d_parent); 66062306a36Sopenharmony_ci return ret; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic int hmdfs_rename_cloud_merge(struct mnt_idmap *idmap, struct inode *old_dir, 66462306a36Sopenharmony_ci struct dentry *old_dentry, 66562306a36Sopenharmony_ci struct inode *new_dir, 66662306a36Sopenharmony_ci struct dentry *new_dentry, 66762306a36Sopenharmony_ci unsigned int flags) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct hmdfs_recursive_para *rec_op_para = NULL; 67062306a36Sopenharmony_ci struct hmdfs_rename_para rename_para = { old_dir, old_dentry, new_dir, 67162306a36Sopenharmony_ci new_dentry, flags }; 67262306a36Sopenharmony_ci int ret = 0; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON || 67562306a36Sopenharmony_ci hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) { 67662306a36Sopenharmony_ci ret = -EACCES; 67762306a36Sopenharmony_ci goto rename_out; 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (hmdfs_i(old_dir)->inode_type != hmdfs_i(new_dir)->inode_type) { 68162306a36Sopenharmony_ci hmdfs_err("in different view"); 68262306a36Sopenharmony_ci ret = -EPERM; 68362306a36Sopenharmony_ci goto rename_out; 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci rec_op_para = kmalloc(sizeof(*rec_op_para), GFP_KERNEL); 68762306a36Sopenharmony_ci if (!rec_op_para) { 68862306a36Sopenharmony_ci ret = -ENOMEM; 68962306a36Sopenharmony_ci goto rename_out; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci trace_hmdfs_rename_merge(old_dir, old_dentry, new_dir, new_dentry, 69262306a36Sopenharmony_ci flags); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci hmdfs_init_recursive_para(rec_op_para, F_MKDIR_MERGE, 0, 0, NULL); 69562306a36Sopenharmony_ci ret = rename_lo_d_cloud_child(&rename_para, rec_op_para); 69662306a36Sopenharmony_ci if (ret != 0) { 69762306a36Sopenharmony_ci d_drop(new_dentry); 69862306a36Sopenharmony_ci } else { 69962306a36Sopenharmony_ci hmdfs_update_meta(old_dir); 70062306a36Sopenharmony_ci if (old_dir != new_dir) 70162306a36Sopenharmony_ci hmdfs_update_meta(new_dir); 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci if (S_ISREG(old_dentry->d_inode->i_mode) && !ret) 70562306a36Sopenharmony_ci d_invalidate(old_dentry); 70662306a36Sopenharmony_cirename_out: 70762306a36Sopenharmony_ci kfree(rec_op_para); 70862306a36Sopenharmony_ci return ret; 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_civoid hmdfs_update_meta(struct inode *dir) 71262306a36Sopenharmony_ci{ 71362306a36Sopenharmony_ci dir->__i_ctime = dir->i_mtime = current_time(dir); 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ciconst struct inode_operations hmdfs_dir_iops_cloud_merge = { 71762306a36Sopenharmony_ci .lookup = hmdfs_lookup_cloud_merge, 71862306a36Sopenharmony_ci .mkdir = hmdfs_mkdir_cloud_merge, 71962306a36Sopenharmony_ci .create = hmdfs_create_cloud_merge, 72062306a36Sopenharmony_ci .rmdir = hmdfs_rmdir_merge, 72162306a36Sopenharmony_ci .unlink = hmdfs_unlink_merge, 72262306a36Sopenharmony_ci .rename = hmdfs_rename_cloud_merge, 72362306a36Sopenharmony_ci .permission = hmdfs_permission, 72462306a36Sopenharmony_ci}; 725